Old school source code management :-)
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 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 | ; FILENAME: AB.ASM P386 IDEAL JUMPS LOCALS @_ INCLUDE "USEFUL.INC" ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- segment code org 100h assume cs :code, ds :code, es :nothing, ss :code start: jmp main REM -- if you've finish coding a program (C/C++ or Pascal) REM after 3 months(an average span of medium-size REM software development) which coding frequency is REM 4 hours every day and saving the program is 5 minutes, REM this number(5000) in theory could let you retrieve REM your initial project code roughly 3 months ago, REM allowing other programmer, who wants tinker with your REM code and see how you gradually develop your program MAX_FILE_COUNT = 5000 label oldTSRAddr dword oldTSROfs dw ? oldTSRSeg dw ? REM -- backup is false tentatively canWeBackup db 0 handleOfFileToBackup dw ? handleOfDuplicate dw ? REM -- length does not include the NULL byte terminator filenameLength dw ? extensionList db ' .PAS .INC .C .H .CPP .HPP' db ' .ASM .MAC .CXX .HXX .HDR ' , 0 fileNameExtLastCharOffset dw ? fileNameExtLength dw ? nextFnameExtLastCharOffset dw ? fileToBackup db DOS_MAXPATHLEN dup(?) filenameToAdjust db DOS_MAXPATHLEN dup(?) fnameMostSignificantExtOffset dw ? REM -- the NULL is copied when you copy the digit REM extension to the extension fileToBackup. REM this is the digit filename toDigit db 8 dup(?), NULL REM -- pascal is a special case in our TSR program REM I found out that Turbo Pascal Editor, REM version 7 in particular don't directly save the REM source code to a .PAS, rather it renames the REM editor temporary file which has an extension REM of .$$$ to a .PAS pascalFNameOffset dw ? buffer db 1 dup(?) mcbAsciiNameLength dw ? struc langNameList len dw ? desc db 8 dup(NULL) ends pascalLang langNameList< 5, 'TURBO' > langNameList< 2, 'TP' > langNameList< 3, 'TPX' > langNameList< 2, 'BP' > langNameList< 3, 'BPX' > langNameList< 6, 'PASCAL' > db NULL ccplusLang langNameList< 2, 'TC' > langNameList< 3, 'TCX' > langNameList< 2, 'BC' > langNameList< 3, 'BCX' > langNameList< 2, 'QC' > langNameList< 3, 'QCX' > langNameList< 1, 'C' > db NULL langToDetect dw ? dta db 256 dup(?) prevDTASeg dw ? prevDTAOffs dw ? ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isLanguageInMem? push ax push bx push cx push ds push si push es push di @_firstMCB: mov ah , DOS_GET_INITIAL_MCB pushf call [ cs :oldTSRAddr] push cs pop ds mov es , [word es : bx -2] ;............................................................................ @_traverseMCB: mov bx , [ cs :langToDetect] @_loopPascalLang: mov di , 0 mov cx , 8 @_findMCBAsciiNameLength: inc di cmp [(mcb es : di ).asciiName], NULL loopne @_findMCBAsciiNameLength mov [ cs :mcbAsciiNameLength], di mov cx , [(langNameList cs : bx ).len] REM -- if not same string length scan the REM next language name cmp cx , [ cs :mcbAsciiNameLength] ohNo @_scanNextLanguageName lea di , [ es :mcb.asciiName] lea si , [(langNameList cs : bx ).desc] cld repe cmpsb ohYes @_found @_scanNextLanguageName: add bx , size langNameList cmp [(langNameList cs : bx ).desc], NULL ohYes @_stopScanningLang jmp @_loopPascalLang @_stopScanningLang: @_scanTheNextMCB: cmp [ es :mcb.linkIndicator], 'Z' je @_notFound mov ax , es inc ax add ax , [ es :mcb.paragraphLen] mov es , ax jmp @_traverseMCB ;............................................................................ @_found: ste jmp @_finish ;............................................................................ @_notFound: cle jmp @_finish @_finish: pop di pop es pop si pop ds pop cx pop bx pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isPascalInMem? REM Input(s): REM langToDetect -- pass here to offset of name list of REM the language REM Output(s): REM Equality/Zero Flag -- if present in memory ;............................................................................ mov [ cs :langToDetect], offset pascalLang call isLanguageInMem? ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isCCPlusplusInMem? REM Input(s): REM langToDetect -- pass here to offset of name list of REM the language REM Output(s): REM Equality/Zero Flag -- if present in memory ;............................................................................ mov [ cs :langToDetect], offset ccplusLang call isLanguageInMem? ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- REM -- you might think that 10 can be stored in byte variable REM of course it is, but since we want to obtain a quotient REM of double word we must divide it by 2 double words. REM EDX(high doubleword:remainder) EAX(low doubleword:quotient) by10 dd 10 proc regEAXConvertTo8Digit push ebx push ecx push edx push eax mov cx , 8 mov bx , 8 mov edx, 0 @_divideBy10: div [ cs :by10] dec bx add dl , '0' mov [ cs :toDigit+ bx ], dl mov edx, 0 loop @_divideBy10 pop eax pop edx pop ecx pop ebx ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc createNewName pusha pushf push cs pop ds mov ah , DOS_GET_DTA pushf call [ cs :oldTSRAddr] push es pop [prevDTASeg] push bx pop [prevDTAOffs] mov ah , DOS_SET_DTA mov dx , offset dta pushf call [ cs :oldTSRAddr] push cs pop es mov cx , [ cs :filenameLength] mov di , offset fileToBackup add di , cx mov al , '.' std repne scasb REM -- create a subdirectory out of fileToBackup add di , 3 mov [byte es : di ], '@' mov [byte es : di +1], 'B' mov [byte es : di +2], NULL REM -- we have no use for carry mov ah , DOS_CREATE_DIRECTORY mov dx , offset fileToBackup pushf call [ cs :oldTSRAddr] mov [byte es : di +2], '\' mov [byte es : di +3], NULL REM -- for example a file is named REM MP1.C this will create a number filename REM in subdirectory MP1.C@B REM -- skip past the directory's at sign add di , 3 mov [ cs :fnameMostSignificantExtOffset], di jmp @_startOfFindANewFilename ;............................................................................; @_startOfFindANewFilename: REM -- the number filename mov eax, 0 jmp @_findANewFilename ;............................................................................ @_findANewFileName: call regEAXConvertTo8Digit REM -- if we exhaust filenames number list adjust ... cmp eax, MAX_FILE_COUNT + 1 ohYes @_adjustListOfFileHistory jmp @_createAUniqueFilename @_createAUniqueFilename: inc eax REM -- preserved the file counter push eax mov di , [ cs :fnameMostSignificantExtOffset] REM -- 8 digit number filename plus NULL character mov cx , 9 mov si , offset toDigit cld rep movsb mov ah , DOS_FILE_FIND_FIRST mov cx , DOS_NORMAL_FILE mov dx , offset fileToBackup pushf call [ cs :oldTSRAddr] REM -- restore the file counter pop eax REM -- file is existing jnc @_findANewFileName REM -- the above loop is terminated when REM we found a file name that does not already REM exist jmp @_finally ;............................................................................ @_adjustListOfFileHistory: pusha REM -- we will remove the first file from the list mov eax, 0 call regEAXConvertTo8Digit mov di , [ cs :fnameMostSignificantExtOffset] REM -- 8 digit number filename plus NULL character mov cx , 9 mov si , offset toDigit cld rep movsb mov ah , DOS_FILE_DELETE mov dx , offset fileToBackup pushf call [ cs :oldTSRAddr] REM -- for ax := 0 to MAX_FILE_COUNT - 1 do REM adjust filenames mov eax, 0 @_adjustThis: mov si , offset fileToBackup mov di , offset filenameToAdjust mov cx , DOS_MAXPATHLEN cld rep movsb REM -- construct the name of file to be rename call regEAXConvertTo8Digit mov di , [ cs :fnameMostSignificantExtOffset] REM -- 8 digit number filename plus NULL character mov cx , 9 mov si , offset toDigit cld rep movsb REM -- construct the new name for file to renamed inc eax call regEAXConvertTo8Digit mov di , [ cs :fnameMostSignificantExtOffset] REM -- filenameToBackup and filenameToAdjust is REM adjacent in memory, so it is just REM okay to do the following light trick: REM di += DOS_MAXPATHLEN; which essentially REM will point DI to the new name or the REM filenameToAdjust's dot character add di , DOS_MAXPATHLEN mov si , offset toDigit REM -- 8 digit number filename plus NULL character mov cx , 9 cld rep movsb REM -- preserve the file counter push eax REM -- now we can rename the file mov ah , DOS_FILE_RENAME mov dx , offset filenameToAdjust mov di , offset fileToBackup pushf call [ cs :oldTSRAddr] REM -- restore the file counter pop eax cmp eax, MAX_FILE_COUNT ohYes @_stopRenaming jmp @_adjustThis ;............................................................................ @_stopRenaming: REM -- from MAX_FILE_NUMBER to MAX_FILE_NUMBER - 1 REM so when create a unique filename is performed REM it has no knowing that MAX_FILE_NUMBER REM adjustments were made, then after inc eax REM is performed, register EAX holds REM the number MAX_FILE_NUMBER again popa mov eax, MAX_FILE_COUNT - 1 jmp @_createAUniqueFilename ;............................................................................ @_finally: mov ah , DOS_SET_DTA push [ cs :prevDTAOffs] pop dx push [ cs :prevDTASeg] pop ds pushf call [ cs :oldTSRAddr] popf popa ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc copyByteByByte pusha push cs pop ds REM -- go the beginning of file, from there we will REM do a byte by byte read of the file to backup mov bx , [ cs :handleOfFileToBackup] mov ah , DOS_FILE_MOVE_PTR mov al , DOS_FILE_BEGIN REM -- longword offset is in CX : DX pair, REM conventionally longword is put in DX : AX pair, REM but since AX register is use in function REM the designer of DOS opted to put the REM longword file offset in CX : DX mov cx , 0 mov dx , 0 pushf call [ cs :oldTSRAddr] mov ah , DOS_FILE_CREATE mov dx , offset fileToBackup mov cx , 00 pushf call [ cs :oldTSRAddr] mov [ cs :handleOfDuplicate], ax jmp @_doTheCopying ;............................................................................ @_doTheCopying: mov dx , offset buffer @_byteRead: mov bx , [ cs :handleOfFileToBackup] mov ah , DOS_FILE_READ mov cx , size buffer pushf call [ cs :oldTSRAddr] REM -- if read size is 0 then no more to read REM so just end the loop cmp ax , 0 ohYes @_finally @_byteWrite: mov cx , ax mov bx , [ cs :handleOfDuplicate] mov ah , DOS_FILE_WRITE pushf call [ cs :oldTSRAddr] jmp @_byteRead ;............................................................................ @_finally: mov bx , [ cs :handleOfDuplicate] mov ah , DOS_FILE_CLOSE pushf call [ cs :oldTSRAddr] popa ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc extensionMatch? REM Input Register(s): REM DS : DX = offset of filename REM Output Register(s): REM DS : DX = offset of filename REM Zero/Equality Flag: REM Set when TRUE -- z / e REM Clear when FALSE -- nz / ne ;............................................................................ REM -- for an unknown reason Turbo Pascal REM editor seems to be lacking in stack space REM whenever we push all the registers(using PUSHA ) REM the rename function can't continue, so I REM opt to preserve only those registers that REM are used in this function push ax push cx push dx push es push ds push si push di push ds pop es REM -- find the offset of NULL character REM dx holds the offset of the filename REM of the interrupted program mov di , dx REM -- scan the AsciiZ NULL character mov al , NULL mov cx , DOS_MAXPATHLEN cld repne scasb REM -- inc cx instr. excludes the null byte from REM string length inc cx mov [ cs :filenameLength], DOS_MAXPATHLEN sub [ cs :filenameLength], cx REM -- 2 is the distance of the DI register termination REM back to the character before the NULL character sub di , 2 REM -- from the NULL character offset - 2 is the last REM character mov [ cs :fileNameExtLastCharOffset], di REM -- the following instr. is use for the REM comparison( cmpsb ) of the asciiz filename REM against the extension list push cs pop es mov [ cs :nextFnameExtLastCharOffset], offset extensionList jmp @_tryExtIfMatchExtList ;............................................................................ @_tryExtIfMatchExtList: mov di , [ cs :nextFnameExtLastCharOffset] @_tryFindTheDotCharacter: inc di cmp [byte cs : di ], '.' ohYes @_countTheCharacter cmp [byte cs : di ], NULL ohYes @_noExtMatch jmp @_tryFindTheDotCharacter @_countTheCharacter: mov cx , 0 @_thenCount: inc di inc cx cmp [byte cs : di ], ' ' ohNo @_thenCount REM -- exclude the space character dec cx mov [ cs :fileNameExtLength], cx dec di mov [ cs :nextFnameExtLastCharOffset], di mov cx , [ cs :fileNameExtLength] mov si , [ cs :fileNameExtLastCharOffset] mov di , [ cs :nextFnameExtLastCharOffset] std repe cmpsb ohYes @_extMatch mov di , [ cs :nextFnameExtLastCharOffset] jmp @_tryFindTheDotCharacter @_extMatch: pop di pop si pop ds pop es pop dx pop cx pop ax ste ret @_noExtMatch: pop di pop si pop ds pop es pop dx pop cx pop ax cle ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc dosIntercept jmp @_beginning tsrMarker db 'AB-MLTH' @_beginning: pushf REM -- Pascal 7 Editor is a special case, it doesn't REM directly saves the source file to .PAS, instead REM it save it first to temporary file then save REM rename it to .PAS cmp ah , DOS_FILE_RENAME ohYes @_tryRename cmp ah , DOS_FILE_CREATE ohYes @_tryExtension cmp ah , DOS_FILE_CREATE_SAFE ohYes @_tryExtension cmp ah , DOS_FILE_CLOSE ohYes @_tryBackup jmp @_toOldRoutine ;............................................................................ REM -- this is a special case for Turbo Pascal 7 Editor REM which does not directly save source code to its REM Pascal filename, rather, it renames the editor REM swap file which has an extension of .$$$ to .PAS @_tryRename: call isCCPlusplusInMem? ohNo @_tryIfPascalRename jmp @_continueInterceptingRename @_tryIfPascalRename: call isPascalInMem? ohNo @_toOldRoutine jmp @_continueInterceptingRename @_continueInterceptingRename: mov [ cs :pascalFNameOffset], di push ds push dx REM -- from the calling rename: REM DS : DX = ES : DI REM where ES : DI is the new name of the rename REM and DS : DX is the filename to test its REM extension push es pop ds push di pop dx call extensionMatch? ohNo @_pascalNoMatch jmp @_backupPascalFilenameAndHandle ;............................................................................ @_pascalNoMatch: REM -- no match so do the ff: REM restore the previous registers, REM then the flag of the interrupted program pop dx pop ds popf pushf call [ cs :oldTSRAddr] jc @_contNoMatchFinal @_contNoMatchFinal: retf 2 ;............................................................................ @_backupPascalFilenameAndHandle: REM -- no match so do the ff: REM restore the previous registers, pop dx pop ds push ds push si push es push di REM -- then from the rename do the copy string of REM of the renamed's new name to the REM fileToBackup REM assign: ES : DI = DS : SI REM destination: REM ES = CS REM DI = offset fileToBackup REM source:(the new name of to be renamed temp file) REM DS = ES REM SI = [ cs :pascalFNameOffset] --> previously REM this is the DI , but we save REM first DI to the variable REM pascal filename offset to avoid REM confusion in variable assignments push es pop ds mov si , [ cs :pascalFNameOffset] push cs pop es mov di , offset fileToBackup mov cx , [ cs :filenameLength] inc cx cld rep movsb pop di pop es pop si pop ds REM -- restore the flag of the interrupted program popf REM -- the rename pushf call [ cs :oldTSRAddr] jnc @_cont push ax push dx mov ah , 02 mov dl , 176 pushf call [ cs :oldTSRAddr] pop dx pop ax retf 2 @_cont: REM -- preserve rename's flag and registers pushf push ax push ds push dx push cs pop ds mov ah , DOS_FILE_OPEN mov al , 0 mov dx , offset fileToBackup pushf call [ cs :oldTSRAddr] jnc @_continueBackuppingPascalHandle jmp @_doNotBackupPascalHandleAndDoNotCloseHandle ;............................................................................ @_continueBackuppingPascalHandle: mov [ cs :handleOfFileToBackup], ax setnc [ cs :canWeBackup] REM -- restore rename's registers and flag pop dx pop ds pop ax popf REM -- preserve it we are doing the file close pushf push ax push bx REM -- when the file is close it will be REM be backupped mov ah , DOS_FILE_CLOSE mov bx , [ cs :handleOfFileToBackup] int 21h REM -- restore the rename's previous registers REM and flag, not from the file close pop bx pop ax popf retf 2 ;............................................................................ @_doNotBackupPascalHandleAndDoNotCloseHandle: REM -- cannot open a file so just do the ff: REM restore previous registers and , REM restore flag of the interrupted REM program pop dx pop ds pop ax popf REM -- return to interrupted program retf 2 ;............................................................................ @_tryExtension: REM -- before we invoke the hooked FILE CREATE/FILE CREATE SAFE REM we test first if the filename's extension if it REM match our filename extension list call isCCPlusplusInMem? ohNo @_tryIfPascalExtension jmp @_continueInterceptingExtension @_tryIfPascalExtension: call isPascalInMem? ohNo @_toOldRoutine jmp @_continueInterceptingExtension @_continueInterceptingExtension: call extensionMatch? ohYes @_backupFilenameAndHandle jmp @_noExtensionMatch ;............................................................................ @_backupFilenameAndHandle: pusha push cs pop es mov di , offset fileToBackup mov si , dx mov cx , [ cs :filenameLength] BUG -- this just one line that is missing from the BUG distributed diskette cause a very erroneous BUG critical error when the file is saved inc cx cld rep movsb popa REM -- restore previous state of flag REM this flag comes from the interrupted program REM not from this routine REM then invoke the hooked routine which is REM FILE CREATE/FILE CREATE SAFE popf pushf call [ cs :oldTSRAddr] setnc [ cs :canWeBackup] mov [ cs :handleOfFileToBackup], ax REM -- return to the interrupted program, REM but do not load the flags from the stack REM instead leave it as it is retf 2 ;............................................................................ @_noExtensionMatch: REM -- filename's extension does not match our filenames REM extension list, so just invoke the hooked routine REM which is the FILE CREATE/FILE CREATE SAFE jmp @_toOldRoutine ;............................................................................ @_tryBackup: cmp bx , [ cs :handleOfFileToBackup] ohNo @_toOldRoutine cmp [ cs :canWeBackup], 1 ohYes @_sound mov [ cs :canWeBackup], 0 jmp @_toOldRoutine ;............................................................................ @_sound: call createNewName call copyByteByByte mov [ cs :canWeBackup], 0 jmp @_toOldRoutine ;............................................................................ @_toOldRoutine: popf jmp [ cs :oldTSRAddr] endp tsrSize = ( ( $ - start ) + 256 + 16 ) / 16 hookedIntr = 21h ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc freeEnvironment REM Output Register(s): REM ES - segment address of the Environment Offset ;............................................................................ push ax mov ah , DOS_RELEASE_MEM mov es , [ ds :ENVIRONMENT_SEGMENT] int 21h pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isTSRInMem? REM Output Register(s): REM ES - segment address of the TSR REM Zero/Equality Flag: REM Set when TRUE -- z / e REM Clear when FALSE -- nz / ne ;............................................................................ mov ah , DOS_INTR_GET_VECT mov al , 21h int 21h REM -- 8 is an arbitrary value, it can be REM any number greater than one, but for REM the program to surely detect if it really match REM we choose more or less 8 mov cx , 8 mov si , offset tsrMarker mov di , bx REM -- we add 3 to DI , the tsrmarker offset REM from the beginning of jmp instruction is 3 add di , 3 cld repe cmpsb ohYes @_alreadyInMem jmp @_notInMem ;............................................................................ @_notInMem: REM -- the ff. will force clear the equality cle jmp @_finally ;............................................................................ @_alreadyInMem: ste jmp @_finally ;............................................................................ @_finally: ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc removeTSRInMem REM Input Register(s): REM ES - segment address of the TSR REM Output Register(s): REM Zero/Equality Flag: REM Set when SUCCESS -- z / e REM Clear when FAILED -- nz / ne REM Carry Flag: REM Set when FAILED -- c REM Clear when SUCCESS -- nc ;............................................................................ push ax ;............................................................................ @_tryRelease: mov ah , DOS_RELEASE_MEM int 21h jc @_clearEqual REM -- success removing ste jmp @_finally ;............................................................................ @_clearEqual: REM -- no success in removing cle jmp @_finally ;............................................................................ @_finally: pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc putCodeInMem REM -- returns nothing. REM this function does not return to the calling function REM instead it directly returns to DOS REM so it is okay not to preserve used registers ;............................................................................ REM -- we have no use for environment strings call freeEnvironment mov ah , DOS_INTR_GET_VECT mov al , hookedIntr int 21h mov [oldTSROfs], bx mov [oldTSRSeg], es mov ah , DOS_INTR_SET_VECT mov al , hookedIntr lea dx , [dosIntercept] int 21h mov ah , DOS_KEEP_TSR mov dx , tsrSize int 21h endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isCommandLineEmpty? REM -- returns equal(e/z) when true otherwise not equal(ne/nz) ;............................................................................ REM -- do we have a command line? test the length pusha cmp [byte es :COMMAND_LINE_LEN_OFFSET], 00h jz @_noCommandLine mov di , 81h mov ch , 0 mov cl , [byte es :80h] mov al , ' ' cld repe scasb je @_noCommandLine clz jmp @_finally @_noCommandLine: ste jmp @_finally @_finally: popa ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isCommandLineSlashU? REM Output Register(s): REM Zero/Equality Flag: REM Set when TRUE -- z / e REM Clear when FALSE -- nz / ne ;............................................................................ push ax push cx push dx push di push si REM -- scan for slash character mov al , '/' mov ch , 0 mov cl , [byte ds :COMMAND_LINE_LEN_OFFSET] mov di , COMMAND_LINE_OFFSET cld repne scasb ohNo @_finally REM -- convert the next character to uppercase mov ax , DOS_CHAR_UP_CASE mov dl , [byte di ] int 21h mov [byte di ], dl cmp [byte di ], 'U' ohNo @_finally jmp @_finally ;............................................................................ @_finally: pop si pop di pop dx pop cx pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc restoreOldRoutine REM Input Register(s): REM ES - segment address of the TSR REM Output Register(s): REM None ;............................................................................ push ax push dx push ds mov ax , [ es :oldTSRSeg] mov ds , ax mov ah , DOS_INTR_SET_VECT mov al , hookedIntr mov dx , [ es :oldTSROfs] int 21h pop ds pop dx pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc motd newLine jmp @_motdj @_michael db 'Vrxsz~w;Yn~u' @_terminator db '$' @_motdj: mov cx , offset @_terminator - offset @_michael mov si , offset @_michael @_motdjloop: xor [byte ptr si ], 27 inc si loop @_motdjloop mov ah , 09h mov dx , offset @_michael int 21h newLine newLine puts '"Programming today is a race between software' newLine puts ' engineers striving to build bigger and better' newLine puts ' idiot-proof programs, and the universe' newLine puts ' trying to produce bigger and better idiots.' newLine puts ' So far, the universe is winning."' newLine newLine puts ' -- Rich Cook' newLine ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc main ;............................................................................ @_tryCommandLine: call isCommandLineEmpty? ohYes @_tryInstall call isCommandLineSlashU? ohYes @_tryUninstall puts 'Unknown Option' jmp @_finally ;............................................................................ @_tryUninstall: call isTSRInMem? ohNo @_tsrNotYetInMem call removeTSRInMem ohNo @_cantRemoveTSRInMem call restoreOldRoutine puts 'Augmented Backups Unloaded' jmp @_finally ;............................................................................ @_cantRemoveTSRInMem: puts 'Cant' 't Remove Augmented Backups in Memory' jmp @_finally ;............................................................................ @_tryInstall: call isTSRInMem? ohYes @_tsrAlreadyInMem puts 'Augmented Backups Loaded' call motd call putCodeInMem jmp @_finally ;............................................................................ @_tsrNotYetInMem: puts 'Augmented Backups Not Yet In Memory' jmp @_finally ;............................................................................ @_tsrAlreadyInMem: puts 'Augmented Backups Already in Memory' jmp @_finally ;............................................................................ @_finally: call motd mov ah , DOS_EXIT int 21h ;............................................................................ endp ends end start ; MICHAEL BUEN |
AK.ASM
Augmented Key is a keyboard automator for Turbo C and Turbo Pascal. I love keyboard shortcuts, there's no mouse shortcuts yet at the time :p heheh
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 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 | ; FILENAME: AK.ASM P386 IDEAL JUMPS LOCALS @_ include 'useful.inc' ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- segment code org 100h assume cs :code, ds :code, es :nothing, ss :code start: jmp main REM -- Backspace and CarriageReturn key respectively BS = 08h NL = 0Dh TAB = 09h REM -- we use the alternate keyboard cursor movements(Wordstar-like) REM hotkey, as the Turbo C++ editor refuse REM to distinguish LEFT from CTRL+LEFT, and also REM with RIGHT from CTRL+RIGHT when we REM press the hotkey CTRL+ ENTER . REM -- The Ctrl+S in Pascal and C/C++ is move left REM Ctrl+D Ctrl+E and Ctrl+X are right, up, down REM respectively KB_CTRL_S = 13h KB_CTRL_X = 18h KB_CTRL_E = 05h KB_CTRL_D = 04h KB_UP = 4800h KB_DOWN = 5000h KB_LEFT = 4B00h KB_RIGHT = 4D00h KB_CTRL_RIGHT_BRACKET = 1B1Dh KB_CTRL_LEFT_BRACKET = 1A1Bh INDENT_HOTKEY = KB_CTRL_RIGHT_BRACKET UNINDENT_HOTKEY = KB_CTRL_LEFT_BRACKET UP = KB_CTRL_E DOWN = KB_CTRL_X LEFT = KB_CTRL_S RIGHT = KB_CTRL_D REM -- ASCII code of Enter KB_CTRL_ENTER_ASCII = 1C0Ah REM -- Scan code of Enter SHORTCUT_HOTKEY = KB_CTRL_ENTER_ASCII KB_SOFTWARE_INTR = 16h ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- label dosBusyFlagAddr dword dosBusyFlagOfs dw ? dosBusyFlagSeg dw ? struc keyTemplates label shortcut word firstKey db ' ' secondKey db ' ' textToInsertOffset dw ? ends stuffing db FALSE ptrToText dw ? label keyBuff word firstKeyBuff db 0 secondKeyBuff db 0 C_DoubleKeys keyTemplates< 'e' , 'i' , C_elseIf > keyTemplates< 's' , 't' , C_struct > keyTemplates< 's' , 'w' , C_switch > keyTemplates< 'i' , 'e' , C_ifElse > keyTemplates< 'c' , 'a' , C_case > keyTemplates< 'c' , 'o' , C_continue > keyTemplates< 'c' , 'l' , C_class > keyTemplates< '#' , 'i' , C_include > keyTemplates< '#' , 'd' , C_define > keyTemplates< '#' , '#' , C_includeU > keyTemplates< 'i' , 'n' , C_intFunc > keyTemplates< 'v' , 'o' , C_voidFunc > keyTemplates< 'd' , 'o' , C_doubleFunc > keyTemplates< 'c' , 'p' , C_cprintf > keyTemplates< 'c' , 's' , C_cscanf > db NULL, NULL C_SingleKeys keyTemplates< , 'i' , C_if > keyTemplates< , 'w' , C_while > keyTemplates< , 'u' , C_unsigned > keyTemplates< , 'e' , C_else > keyTemplates< , 'd' , C_do > keyTemplates< , 'f' , C_for > keyTemplates< , 'b' , C_break > keyTemplates< , 'r' , C_return > keyTemplates< , 'g' , C_gotoxy > keyTemplates< , 'p' , C_printf > keyTemplates< , 's' , C_scanf > keyTemplates< , '!' , C_program > db NULL, NULL Pas_DoubleKeys keyTemplates< 'w' , 'h' , Pas_while > keyTemplates< 'w' , 'i' , Pas_with > keyTemplates< 'r' , 'u' , Pas_repeatUntil > keyTemplates< 'r' , 'e' , Pas_recordEnd > keyTemplates< 'f' , 'o' , Pas_for > keyTemplates< 'f' , 'd' , Pas_for_down > keyTemplates< 'f' , 'u' , Pas_function > keyTemplates< 'c' , 'a' , Pas_case > keyTemplates< 'c' , 'o' , Pas_continue > keyTemplates< 'b' , 'e' , Pas_beginEnd > keyTemplates< 'b' , 'r' , Pas_break > keyTemplates< 'i' , 'e' , Pas_ifElse > keyTemplates< 'e' , 'i' , Pas_elseIf > keyTemplates< 'i' , 'n' , Pas_integer > keyTemplates< 'o' , 'b' , Pas_object > db NULL, NULL Pas_SingleKeys keyTemplates< , 'p' , Pas_procedure > keyTemplates< , 'e' , Pas_else > keyTemplates< , 'i' , Pas_if > keyTemplates< , 'a' , Pas_array > keyTemplates< , 'w' , Pas_writeln > keyTemplates< , 'r' , Pas_readln > keyTemplates< , 'g' , Pas_gotoxy > keyTemplates< , '!' , Pas_program > db NULL, NULL REM -- Pascal double keys Pas_while db BS, BS, 'do' , NL db 'begin' , NL, NL db 'end;' , LEFT, LEFT, LEFT, LEFT db UP, UP, UP db 'while ' db LEFT db NULL Pas_with db BS, BS, 'do' , NL db 'begin' , NL, NL db 'end;' , LEFT, LEFT, LEFT, LEFT db UP, UP, UP db 'with ' db LEFT db NULL Pas_repeatUntil db BS, BS db 'repeat' , NL, NL db 'until ;' , LEFT db NULL Pas_recordEnd db 'cord' , NL, NL db 'end;' db NULL Pas_for db BS, BS, ':= to do' , NL db 'begin' , NL, NL db 'end;' , LEFT, LEFT, LEFT, LEFT db UP, UP, UP db 'for ' db LEFT db NULL Pas_for_down db BS, BS, ':= downto do' , NL db 'begin' , NL, NL db 'end;' , LEFT, LEFT, LEFT, LEFT db UP, UP, UP db 'for ' db LEFT db NULL Pas_function db BS, BS, ':;' , NL db 'begin' , NL, NL db 'end;' , NL db UP, UP, UP, UP db 'function ' db NULL Pas_case db BS, BS, 'of' , NL db ':' , NL db ':' , NL db 'end;' , LEFT, LEFT, LEFT, LEFT db UP, UP, UP db 'case ' db LEFT db NULL Pas_continue db 'ntinue;' , NL db NULL Pas_beginEnd db 'gin' , NL, NL db 'end;' , LEFT, LEFT, LEFT, LEFT db UP, TAB db NULL Pas_break db 'eak;' , NL db NULL Pas_ifElse db BS, BS, 'then' , NL db 'begin' , NL, NL db 'end' , NL db 'else' , NL db 'begin' , NL, NL db 'end;' , LEFT, LEFT, LEFT, LEFT db UP, UP, UP, UP db UP, UP, UP db 'if ' db LEFT db NULL Pas_elseIf db BS, BS, 'then' , NL db 'begin' , NL, NL db 'end' , LEFT, LEFT, LEFT db UP, UP, UP db 'else if ' db LEFT db NULL Pas_integer db 'teger;' , NL db NULL Pas_object db BS, BS, 'object' , NL db 'private' , NL, NL db 'public' , NL, NL db 'end;' , LEFT, LEFT, LEFT, LEFT db UP, UP, UP, UP, UP db NULL REM -- Pascal Single Keys Pas_procedure db BS, ';' , NL db 'begin' , NL, NL db 'end;' , NL db UP, UP, UP, UP db 'procedure ' db NULL Pas_else db 'lse' , NL db 'begin' , NL, NL db 'end;' , LEFT, LEFT, LEFT, LEFT db UP db NULL Pas_if db BS, 'then' , NL db 'begin' , NL, NL db 'end;' , LEFT, LEFT, LEFT, LEFT db UP, UP, UP db 'if ' db LEFT db NULL Pas_array db 'rray [ .. ] of' db LEFT, LEFT, LEFT, LEFT, LEFT, LEFT, LEFT db NULL Pas_writeln db 'riteln;' , LEFT db NULL Pas_readln db 'eadln;' , LEFT db NULL Pas_gotoxy db 'otoxy( , );' db LEFT, LEFT, LEFT, LEFT, LEFT db NULL Pas_program db BS db 'uses crt, dos, printer, graph;' , NL db 'var' , NL db NL db NL db 'begin' , NL db NL db 'end.' , LEFT, LEFT, LEFT, LEFT db UP, UP, UP, UP, TAB db NULL REM -- C double keys C_elseIf db BS, BS, ')' ,NL db '{' , NL, NL db '}' , LEFT db UP, UP, UP db 'else if( ' db LEFT db NULL C_struct db 'ruct' , NL db '{' , NL db NL db '};' , LEFT, LEFT db UP, UP, UP db RIGHT, RIGHT, RIGHT, RIGHT db RIGHT, RIGHT db ' ' db NULL C_switch db BS, BS, ')' , NL db '{' , NL db 'case :' ,NL, NL db ' break;' , NL, NL, BS db 'case :' ,NL, NL db ' break;' , NL, NL, BS db 'default:' , NL, NL db ' break;' , NL, BS db '}' , LEFT db UP, UP, UP, UP, UP, UP, UP db UP, UP, UP, UP, UP, UP db 'switch( ' db LEFT db NULL C_ifElse db BS, BS, ')' , NL db '{' , NL, NL db '}' , NL db 'else' , NL db '{' , NL, NL db '}' , LEFT db UP, UP, UP, UP db UP, UP, UP db 'if( ' db LEFT db NULL C_case db 'se:' , NL, NL db ' break;' db LEFT, LEFT, LEFT, LEFT, LEFT, LEFT db UP, UP, ' ' db NULL C_continue db 'ntinue;' , NL db NULL C_class db 'ass' , NL db '{' , NL db 'private:' , NL, NL db 'protected:' , NL, NL db 'public:' , NL, NL db '};' , LEFT, LEFT db UP, UP, UP, UP, UP, UP, UP, UP db RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, ' ' db NULL C_include db 'nclude <.h>' , LEFT, LEFT, LEFT db NULL C_define db 'efine ' db NULL C_includeU db BS, 'include ".h"' , LEFT, LEFT, LEFT db NULL C_intFunc db 't ()' , NL db '{' , NL db NL db '}' , NL db UP, UP, UP, UP, RIGHT, RIGHT, RIGHT, RIGHT db NULL C_voidFunc db 'id ()' , NL db '{' , NL db NL db '}' , NL db UP, UP, UP, UP, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT db NULL C_doubleFunc db 'uble ()' , NL db '{' , NL db NL db '}' , NL db UP, UP, UP, UP db RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT, RIGHT db NULL C_cprintf db 'rintf( "", );' db LEFT, LEFT, LEFT, LEFT, LEFT, LEFT db NULL C_cscanf db 'canf( "", );' db LEFT, LEFT, LEFT, LEFT, LEFT, LEFT db NULL REM -- C single keys C_if db BS, ')' , NL db '{' , NL, NL db '}' , LEFT db UP, UP, UP db 'if( ' db LEFT db NULL C_while db BS, ')' , NL db '{' , NL, NL db '}' , LEFT db UP, UP, UP db 'while( ' db LEFT db NULL C_unsigned db 'nsigned ' db NULL C_else db 'lse' , NL db '{' , NL, NL db '}' , LEFT db UP db NULL C_do db 'o' , NL db '{' , NL db '}' , NL db 'while( );' db LEFT, LEFT, LEFT db NULL C_for db BS, '; ; )' , NL db '{' , NL, NL db '}' , LEFT db UP, UP, UP db 'for( ' db NULL C_break db 'reak;' , NL db NULL C_return db 'eturn ' db NULL C_printf db 'rintf( "", );' db LEFT, LEFT, LEFT, LEFT, LEFT, LEFT db NULL C_scanf db 'canf( "", );' db LEFT, LEFT, LEFT, LEFT, LEFT, LEFT db NULL C_gotoxy db 'otoxy( , );' db LEFT, LEFT, LEFT, LEFT, LEFT db NULL C_program db BS db '#include <stdio.h>' , NL db '#include <io.h>' , NL db '#include <conio.h>' , NL db '#include <math.h>' , NL db NL db 'void main()' , NL db '{' , NL db NL db '}' , LEFT, UP, TAB db NULL CPas_indent db 0Bh, 'I' db NULL CPas_unindent db 0Bh, 'U' db NULL doublekeysPtr dw ? singlekeysPtr dw ? REM -- prev address of keyboard interrupt 16h label preAKAddr dword preAKOffset dw ? preAKSegment dw ? initialMCBSegment dw ? mcbAsciiNameLength dw ? struc langNameList len dw ? desc db 8 dup(NULL) ends pascalLang langNameList< 5, 'TURBO' > langNameList< 2, 'TP' > langNameList< 3, 'TPX' > langNameList< 2, 'BP' > langNameList< 3, 'BPX' > langNameList< 6, 'PASCAL' > db NULL ccplusLang langNameList< 2, 'TC' > langNameList< 3, 'TCX' > langNameList< 2, 'BC' > langNameList< 3, 'BCX' > langNameList< 2, 'QC' > langNameList< 3, 'QCX' > langNameList< 1, 'C' > db NULL langToDetect dw ? ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isLanguageInMem? push ax push bx push cx push ds push si push es push di @_firstMCB: push [ cs :initialMCBSegment] pop es push cs pop ds ;............................................................................ @_traverseMCB: mov bx , [ cs :langToDetect] @_loopLang: mov di , 0 mov cx , 8 @_findMCBAsciiNameLength: inc di cmp [(mcb es : di ).asciiName], NULL loopne @_findMCBAsciiNameLength mov [ cs :mcbAsciiNameLength], di mov cx , [(langNameList cs : bx ).len] REM -- if not same string length scan the REM next language name cmp cx , [ cs :mcbAsciiNameLength] ohNo @_scanNextLanguageName lea di , [ es :mcb.asciiName] lea si , [(langNameList cs : bx ).desc] cld repe cmpsb ohYes @_found @_scanNextLanguageName: add bx , size langNameList cmp [(langNameList cs : bx ).desc], NULL ohYes @_stopScanningLang jmp @_loopLang @_stopScanningLang: @_scanTheNextMCB: cmp [ es :mcb.linkIndicator], 'Z' je @_notFound mov ax , es inc ax add ax , [ es :mcb.paragraphLen] mov es , ax jmp @_traverseMCB ;............................................................................ @_found: ste jmp @_finish ;............................................................................ @_notFound: cle jmp @_finish @_finish: pop di pop es pop si pop ds pop cx pop bx pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isPascalInMem? REM Input(s): REM langToDetect -- pass here to offset of name list of REM the language REM Output(s): REM Equality/Zero Flag -- if present in memory ;............................................................................ mov [ cs :langToDetect], offset pascalLang call isLanguageInMem? ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isCCPlusplusInMem? REM Input(s): REM langToDetect -- pass here to offset of name list of REM the language REM Output(s): REM Equality/Zero Flag -- if present in memory ;............................................................................ mov [ cs :langToDetect], offset ccplusLang call isLanguageInMem? ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc getInitialMCBSegment REM Purpose: REM Get initial MCB Segment, which is very useful REM in traversing memory links, to see if a particular REM program is in memory REM In our program this is use for inquiring the REM language loaded in memory (Pascal or C/C++?) REM Input(s): REM None REM Output(s): REM initialMCBSegment: data type = word ;............................................................................ push ax push es push bx mov ah , DOS_GET_INITIAL_MCB int 21h mov ax , [word es : bx -2] mov [ cs :initialMCBSegment], ax pop bx pop es pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc insertAtOurBuffer REM Purpose: REM Simulate keyboard buffer reading REM Input(s): REM None REM Output(s): REM keybuff: data type = word REM has two components: REM firstkeyBuff REM secondkeyBuff ;............................................................................ pusha mov ah , BIOS_GET_CURSOR_POS REM -- 0 is page number mov bh , 0 int 10h mov cx , dx REM -- DH is row DL is column dec dl mov ah , BIOS_SET_CURSOR_POS int 10h mov ah , BIOS_READ_CHAR_AT_POS int 10h mov [ cs :secondKeyBuff], al REM -- DH is row DL is column dec dl mov ah , BIOS_SET_CURSOR_POS int 10h mov ah , BIOS_READ_CHAR_AT_POS int 10h mov [ cs :firstKeyBuff], al mov ah , BIOS_SET_CURSOR_POS REM -- 0 is page number mov bh , 0 mov dx , cx int 10h popa ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc keyIntercept jmp @_beginning tsrMarker db 'AK-MLTH' @_beginning: pushf push es push di les di , [ cs :dosBusyFlagAddr] cmp [byte ptr es : di ], 0 ohYes @_continueBeginning @_donotContinueBeginning: pop di pop es popf jmp @_doOld @_continueBeginning: pop di pop es popf cmp ah , BIOS_OLD_READKEY ohYes @_tryReadkey cmp ah , BIOS_NEW_READKEY ohYes @_tryReadkey cmp ah , BIOS_OLD_KEYSTAT ohYes @_tryKeystat cmp ah , BIOS_NEW_KEYSTAT ohYes @_tryKeystat ;............................................................................ @_tryReadkey: cmp [ cs :stuffing], TRUE ohYes @_fakeReadkey jmp @_realReadkey ;............................................................................ @_realReadkey: pushf call [ cs :preAKAddr] cmp ax , SHORTCUT_HOTKEY ohYes @_readKeyShortcutContinue cmp ax , INDENT_HOTKEY ohYes @_readkeyIndent cmp ax , UNINDENT_HOTKEY ohYes @_readkeyUnindent jmp @_readkeyShortcutNotTriggerBackToCaller @_readkeyIndent: mov [ cs :stuffing], TRUE mov [ cs :ptrToText], offset CPas_indent jmp @_fakeReadkey @_readkeyUnindent: mov [ cs :stuffing], TRUE mov [ cs :ptrToText], offset CPas_unindent jmp @_fakeReadkey @_readkeyShortcutContinue: call insertAtOurBuffer call isPascalInMem? ohYes @_readkeyPascal call isCCPlusplusInMem? ohYes @_readkeyCCPlusplus jmp @_doOld ;............................................................................ @_readkeyPascal: mov [ cs :doublekeysPtr], offset Pas_doubleKeys mov [ cs :singlekeysPtr], offset Pas_singleKeys jmp @_readkeyLanguage ;............................................................................ @_readkeyCCPlusplus: mov [ cs :doublekeysPtr], offset C_doubleKeys mov [ cs :singlekeysPtr], offset C_singleKeys jmp @_readkeyLanguage ;............................................................................ @_readkeyLanguage: push dx push bx mov dx , [ cs :keyBuff] mov bx , [ cs :doublekeysPtr] @_readkeyDoublekeyCheckKeysLoop: cmp [(keyTemplates cs : bx ).shortcut], NULL ohYes @_readkeyDoublekeyShortcutNotAvailable cmp [(keyTemplates cs : bx ).shortcut], dx ohYes @_readkeyDoublekeyShortcutAvailable add bx , size keyTemplates jmp @_readkeyDoublekeyCheckKeysLoop @_readkeyDoublekeyShortcutAvailable: REM -- clear first our own keyboard buffer mov [ cs :keyBuff], 0000h mov bx , [(keyTemplates cs : bx ).textToInsertOffset] mov [ cs :ptrToText], bx mov [ cs :stuffing], TRUE jmp @_readkeyDoublekeyCheckKeysStop @_readkeyDoublekeyShortcutNotAvailable: mov [ cs :ptrToText], 0 mov [ cs :stuffing], FALSE jmp @_readkeyDoublekeyCheckKeysStop @_readkeyDoublekeyCheckKeysStop: pop bx pop dx cmp [ cs :stuffing], TRUE je @_fakeReadkey push dx push bx mov dl , [ cs :secondKeybuff] mov bx , [ cs :singlekeysPtr] @_readkeySinglekeyCheckKeysLoop: cmp [(keyTemplates cs : bx ).secondKey], NULL ohYes @_readkeySinglekeyShortcutNotAvailable cmp [(keyTemplates cs : bx ).secondKey], dl ohYes @_readkeySinglekeyShortcutAvailable add bx , size keyTemplates jmp @_readkeySinglekeyCheckKeysLoop @_readkeySinglekeyShortcutAvailable: REM -- clear first our own keyboard buffer mov [ cs :keyBuff], 0000h mov bx , [(keyTemplates cs : bx ).textToInsertOffset] mov [ cs :ptrToText], bx mov [ cs :stuffing], TRUE jmp @_readkeySinglekeyCheckKeysStop @_readkeySinglekeyShortcutNotAvailable: mov [ cs :ptrToText], 0 mov [ cs :stuffing], FALSE jmp @_readkeySinglekeyCheckKeysStop @_readkeySinglekeyCheckKeysStop: pop bx pop dx cmp [ cs :stuffing], TRUE je @_fakeReadkey iret ;............................................................................ @_fakeReadkey: push bx mov bx , [ cs :ptrToText] mov al , [byte cs : bx ] mov ah , 0 inc [ cs :ptrToText] mov bx , [ cs :ptrToText] cmp [byte cs : bx ], NULL setne [ cs :stuffing] pop bx iret ;............................................................................ @_readkeyShortcutNotTriggerBackToCaller: iret ;............................................................................ @_tryKeystat: cmp [ cs :stuffing], TRUE ohYes @_fakeKeystat jmp @_realKeystat ;............................................................................ @_realKeystat: pushf call [ cs :preAKAddr] REM -- Zero keys Available so just back to caller jz @_keystatBackToCaller cmp ax , SHORTCUT_HOTKEY ohYes @_keyStatShortcutContinue cmp ax , INDENT_HOTKEY ohYes @_keystatIndent cmp ax , UNINDENT_HOTKEY ohYes @_keystatUnindent jmp @_keystatBackToCaller @_keystatIndent: mov ah , BIOS_OLD_READKEY pushf call [ cs :preAKAddr] mov [ cs :stuffing], TRUE mov [ cs :ptrToText], offset CPas_indent jmp @_fakeKeystat @_keystatUnindent: mov ah , BIOS_OLD_READKEY pushf call [ cs :preAKAddr] mov [ cs :stuffing], TRUE mov [ cs :ptrToText], offset CPas_unindent jmp @_fakeKeystat @_keystatShortcutContinue: REM -- we do this just to remove the hotkey REM so it won't be evaluated again, REM if you try to remove this REM three lines of code you'll see REM the insertion of keys will go into REM infinitum mov ah , BIOS_OLD_READKEY pushf call [ cs :preAKAddr] call insertAtOurBuffer call isPascalInMem? ohYes @_keystatPascal call isCCPlusplusInMem? ohYes @_keystatCCPlusplus stz retf 2 ;............................................................................ @_keystatPascal: mov [ cs :doublekeysPtr], offset Pas_doubleKeys mov [ cs :singlekeysPtr], offset Pas_singleKeys jmp @_keystatLanguage ;............................................................................ @_keystatCCPlusplus: mov [ cs :doublekeysPtr], offset C_doubleKeys mov [ cs :singlekeysPtr], offset C_singleKeys jmp @_keystatLanguage ;............................................................................ @_keystatLanguage: push dx push bx mov dx , [ cs :keyBuff] mov bx , [ cs :doublekeysPtr] @_keystatDoubleCheckKeysLoop: cmp [(keyTemplates cs : bx ).shortcut], NULL ohYes @_keystatDoubleShortcutNotAvailable cmp [(keyTemplates cs : bx ).shortcut], dx ohYes @_keystatDoubleShortcutAvailable add bx , size keyTemplates jmp @_keystatDoubleCheckKeysLoop @_keystatDoubleShortcutAvailable: REM -- clear first our own keyboard buffer mov [ cs :keyBuff], 0000h mov bx , [(keyTemplates cs : bx ).textToInsertOffset] mov [ cs :ptrToText], bx mov [ cs :stuffing], TRUE jmp @_keystatDoubleCheckKeysStop @_keystatDoubleShortcutNotAvailable: mov [ cs :ptrToText], 0 mov [ cs :stuffing], FALSE jmp @_keystatDoubleCheckKeysStop @_keystatDoubleCheckKeysStop: pop bx pop dx cmp [ cs :stuffing], TRUE je @_fakekeystat push dx push bx mov dl , [ cs :secondKeybuff] mov bx , [ cs :singlekeysPtr] @_keystatSingleCheckKeysLoop: cmp [(keyTemplates cs : bx ).secondKey], NULL ohYes @_keystatSingleShortcutNotAvailable cmp [(keyTemplates cs : bx ).secondKey], dl ohYes @_keystatSingleShortcutAvailable add bx , size keyTemplates jmp @_keystatSingleCheckKeysLoop @_keystatSingleShortcutAvailable: REM -- clear first our own keyboard buffer mov [ cs :keyBuff], 0000h mov bx , [(keyTemplates cs : bx ).textToInsertOffset] mov [ cs :ptrToText], bx mov [ cs :stuffing], TRUE jmp @_keystatSingleCheckKeysStop @_keystatSingleShortcutNotAvailable: mov [ cs :ptrToText], 0 mov [ cs :stuffing], FALSE jmp @_keystatSingleCheckKeysStop @_keystatSingleCheckKeysStop: pop bx pop dx cmp [ cs :stuffing], TRUE je @_fakekeyStat mov [ cs :keyBuff], 0 stz retf 2 ;............................................................................ @_fakeKeystat: push bx mov bx , [ cs :ptrToText] mov al , [byte cs : bx ] mov ah , 0 cmp al , NULL ohNo @_continueKeystatOrdinaryKey mov [ cs :stuffing], FALSE stz retf 2 @_continueKeystatOrdinaryKey: jmp @_keystatInsert @_keystatInsert: pop bx REM -- clear zero meaning simulate key availability clz retf 2 ;............................................................................ @_keystatShortcutNotTriggerBackToCaller: clz retf 2 ;............................................................................ @_keystatBackToCaller: retf 2 ;............................................................................ @_doOld: jmp [ cs :preAKAddr] endp tsrSize = ( ( $ - start ) + 256 + 16 ) / 16 ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc freeEnvironment REM Output Register(s): REM ES - segment address of the Environment ;............................................................................ push ax mov ah , DOS_RELEASE_MEM mov es , [ ds :ENVIRONMENT_SEGMENT] int 21h pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isTSRInMem? REM Output Register(s): REM ES - segment address of the TSR REM Zero/Equality Flag: REM Set when TRUE -- z / e REM Clear when FALSE -- nz / ne ;............................................................................ push si push di push ax push cx mov ah , DOS_INTR_GET_VECT mov al , KB_SOFTWARE_INTR int 21h REM -- 8 is an arbitrary value, it can be REM any number greater than one, but for REM the program to surely detect if TS REM signature really match we choose REM more or less 8 mov cx , 8 mov si , offset tsrMarker mov di , bx REM -- we add 3 to DI , the tsrmarker offset REM from the beginning of jmp instruction is 3 add di , 3 cld repe cmpsb ohYes @_alreadyInMem jmp @_notInMem ;............................................................................ @_notInMem: REM -- the ff. will force clear the equality cle jmp @_finally ;............................................................................ @_alreadyInMem: ste jmp @_finally ;............................................................................ @_finally: pop cx pop ax pop di pop si ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc removeTSRInMem REM Input Register(s): REM ES - segment address of the TSR REM Output Register(s): REM Zero/Equality Flag: REM Set when SUCCESS -- z / e REM Clear when FAILED -- nz / ne REM Carry Flag: REM Set when FAILED -- c REM Clear when SUCCESS -- nc ;............................................................................ push ax ;............................................................................ @_tryRelease: mov ah , DOS_RELEASE_MEM int 21h jc @_clearEqual REM -- success removing ste jmp @_finally ;............................................................................ @_clearEqual: REM -- no success in removing cle jmp @_finally ;............................................................................ @_finally: pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc putCodeInMem REM -- returns nothing. REM this function does not return to the calling function REM instead it directly returns to DOS REM so it is okay not to preserve used registers ;............................................................................ REM -- we have no use for environment strings call freeEnvironment mov ah , DOS_GET_BUSY_FLAG_ADDR int 21h mov [dosBusyFlagOfs], bx mov [dosBusyFlagSeg], es mov ah , DOS_INTR_GET_VECT mov al , KB_SOFTWARE_INTR int 21h mov [preAKOffset], bx mov [preAKSegment], es mov ah , DOS_INTR_SET_VECT mov al , KB_SOFTWARE_INTR mov dx , offset keyIntercept int 21h mov ah , DOS_KEEP_TSR mov dx , tsrSize int 21h endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isCommandLineEmpty? REM -- returns equal(e/z) when true otherwise not equal(ne/nz) ;............................................................................ REM -- do we have a command line? test the length pusha cmp [byte es :COMMAND_LINE_LEN_OFFSET], 00h jz @_noCommandLine mov di , 81h mov ch , 0 mov cl , [byte es :80h] mov al , ' ' cld repe scasb je @_noCommandLine clz jmp @_finally @_noCommandLine: ste jmp @_finally @_finally: popa ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isCommandLineSlashU? REM Output Register(s): REM Zero/Equality Flag: REM Set when TRUE -- z / e REM Clear when FALSE -- nz / ne ;............................................................................ push ax push cx push dx push di push si REM -- scan for slash character mov al , '/' mov ch , 0 mov cl , [byte ds :80h] mov di , 81h cld repne scasb ohNo @_finally REM -- convert the next character to uppercase mov ax , DOS_CHAR_UP_CASE mov dl , [byte di ] int 21h mov [byte di ], dl cmp [byte di ], 'U' ohNo @_finally jmp @_finally ;............................................................................ @_finally: pop si pop di pop dx pop cx pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc restoreOldRoutine REM Input Register(s): REM ES - segment address of the TSR REM Output Register(s): REM None ;............................................................................ push ax push dx push ds mov ax , [ es :preAKSegment] mov ds , ax mov ah , DOS_INTR_SET_VECT mov al , KB_SOFTWARE_INTR mov dx , [ es :preAKOffset] int 21h pop ds pop dx pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc motd newLine jmp @_motdj @_michael db 'Vrxsz~w;Yn~u' @_terminator db '$' @_motdj: mov cx , offset @_terminator - offset @_michael mov si , offset @_michael @_motdjloop: xor [byte ptr si ], 27 inc si loop @_motdjloop mov ah , 09h mov dx , offset @_michael int 21h newLine newLine puts '"From the programmer' 's point of view,' newLine puts ' a user is just a peripheral that types' newline puts ' in when the program issues a read request."' newLine newLine puts ' -- From Java Book(the source Sun)' newLine ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc main call getInitialMCBSegment @_tryCommandLine: call isCommandLineEmpty? ohYes @_tryInstall call isCommandLineSlashU? ohYes @_tryUninstall puts 'Unknown Option' jmp @_finally ;............................................................................ @_tryUninstall: call isTSRInMem? ohNo @_tsrNotYetInMem call removeTSRInMem ohNo @_cantRemoveTSRInMem call restoreOldRoutine puts 'Augmented Keys Unloaded' jmp @_finally ;............................................................................ @_cantRemoveTSRInMem: puts 'Cant' 't Remove Augmented Keys in Memory' jmp @_finally ;............................................................................ @_tryInstall: call isTSRInMem? ohYes @_tsrAlreadyInMem puts 'Augmented Keys Loaded' call motd call putCodeInMem jmp @_finally ;............................................................................ @_tsrNotYetInMem: puts 'Augmented Keys not yet in memory' jmp @_finally ;............................................................................ @_tsrAlreadyInMem: puts 'Augmented Keys already in memory' jmp @_finally ;............................................................................ @_finally: call motd mov ah , DOS_EXIT int 21h ;............................................................................ endp ends end start ; MICHAEL BUEN |
AH.ASM
Augumented Help. Extends Turbo C/C++ and Turbo Pascal help functionality
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 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 | ; FILENAME: AH.ASM P386 IDEAL JUMPS LOCALS @_ include 'useful.inc' ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- segment code org 100h assume cs :code, ds :code, es :nothing, ss :code start: jmp main KB_PAGE_UP = 4900h KB_PAGE_DOWN = 5100h KB_ESCAPE = 011Bh KB_TAB = 0F09h KB_SHIFT_TAB = 0F00h KB_ENTER = 1C0Dh KB_INSERT = 5200h KB_HOME = 4700h KB_F11 = 8500h KB_CTRL_F10 = 6700h SHORTCUT_HOTKEY = KB_CTRL_F10 KB_SOFTWARE_INTR = 16h KB_ALT_PLUS = 8300h PASTE_HOTKEY = KB_ALT_PLUS REM -- The Ctrl+S in Pascal and C/C++ is move left REM Ctrl+D Ctrl+E and Ctrl+X are right, up, down REM respectively KB_CTRL_S = 13h KB_CTRL_X = 18h KB_CTRL_E = 05h KB_CTRL_D = 04h UP = KB_CTRL_E DOWN = KB_CTRL_X LEFT = KB_CTRL_S RIGHT = KB_CTRL_D REM -- this special symbol is use in pasting an example HOME = 3 ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- label dosBusyFlagAddr dword dosBusyFlagOfs dw ? dosBusyFlagSeg dw ? REM -- prev address of keyboard interrupt 16h label preAHAddr dword preAHOffset dw ? preAHSegment dw ? initialMCBSegment dw ? mcbAsciiNameLength dw ? struc langNameList len dw ? desc db 8 dup(NULL) ends WIN_X1 = 7 WIN_Y1 = 3 WIN_X2 = 73 WIN_Y2 = 21 WIN_FGCOLOR = YELLOW WIN_BGCOLOR = CYAN WIN_TITLEFGCOLOR = WHITE WIN_TITLEBGCOLOR = RED WIN_RELATED_FGCOLOR = BLACK WIN_RELATED_BGCOLOR = CYAN SHADOW_COLOR = ( BLACK shl 4 ) or LIGHTGRAY cursorRowLoopVar db ? cursorColLoopVar db ? REM -- 4000 is 80x25 = 2000 chars + another 2000 REM for the chars' attribute SCREEN_BUFFER_SIZE = 4000 helpWinBackSave db SCREEN_BUFFER_SIZE dup(?) label prevCursorPos word prevCursorCol db ? prevCursorRow db ? pascalLang langNameList< 5, 'TURBO' > langNameList< 2, 'TP' > langNameList< 3, 'TPX' > langNameList< 2, 'BP' > langNameList< 3, 'BPX' > langNameList< 6, 'PASCAL' > db NULL ccplusLang langNameList< 2, 'TC' > langNameList< 3, 'TCX' > langNameList< 2, 'BC' > langNameList< 3, 'BCX' > langNameList< 2, 'QC' > langNameList< 3, 'QCX' > langNameList< 1, 'C' > db NULL langToDetect dw ? helpFilename db 'augment.hlp' , NULL helpFilenameFullPath db DOS_MAXPATHLEN dup(?) helpFileHandle dw ? buffer db ? bytesRead dw ? struc topicLink column db ? row db ? stringLength db ? description db 60 dup(?) ends REM -- this is the index to the related topics relatedTopicIndex dw ? relatedTopics topicLink 70 dup(?) relatedTopicsCount dw ? topicPageCount dw ? topicCurrentPage dw ? struc topicPageFileLoc label dataDWord dword dataLoWord dw ? dataHiWord dw ? ends topicFirstPageLoc topicPageFileLoc <> topicPageLocList topicPageFileLoc 15 dup(<>) REM -- use for determining if the lines we read REM already exceeds MAX_LINE_IN_A_PAGE lineCountTheFile db ? REM -- use for determining if the lines display in screen REM already exceeds MAX_LINE_IN_A_PAGE lineCountTheScreen dw ? MAX_LINE_IN_PAGE = WIN_Y2 - WIN_Y1 - 2 MAX_COLUMN_IN_PAGE = 80 BEEP = 7 keywordAtCursorLen db ? keywordAtCursor db 80 dup(?) keywordFromFileLen db ? keywordFromFile db 80 dup(?) clipboardLength dw 0 clipboardBuffer db 10000 dup(?) clipboardLinesCount dw ? ptrToText dw ? endingInsertOffset dw ? stuffing db FALSE dta db 256 dup(?) prevDTASeg dw ? prevDTAOffs dw ? ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isLanguageInMem? push ax push bx push cx push ds push si push es push di @_firstMCB: push [ cs :initialMCBSegment] pop es push cs pop ds ;............................................................................ @_traverseMCB: mov bx , [ cs :langToDetect] @_loopLang: mov di , 0 mov cx , 8 @_findMCBAsciiNameLength: inc di cmp [(mcb es : di ).asciiName], NULL loopne @_findMCBAsciiNameLength mov [ cs :mcbAsciiNameLength], di mov cx , [(langNameList cs : bx ).len] REM -- if not same string length scan the REM next language name cmp cx , [ cs :mcbAsciiNameLength] ohNo @_scanNextLanguageName lea di , [ es :mcb.asciiName] lea si , [(langNameList cs : bx ).desc] cld repe cmpsb ohYes @_found @_scanNextLanguageName: add bx , size langNameList cmp [(langNameList cs : bx ).desc], NULL ohYes @_stopScanningLang jmp @_loopLang @_stopScanningLang: @_scanTheNextMCB: cmp [ es :mcb.linkIndicator], 'Z' je @_notFound mov ax , es inc ax add ax , [ es :mcb.paragraphLen] mov es , ax jmp @_traverseMCB ;............................................................................ @_found: ste jmp @_finish ;............................................................................ @_notFound: cle jmp @_finish @_finish: pop di pop es pop si pop ds pop cx pop bx pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isPascalInMem? REM Input(s): REM langToDetect -- pass here to offset of name list of REM the language REM Output(s): REM Equality/Zero Flag -- if present in memory ;............................................................................ mov [ cs :langToDetect], offset pascalLang call isLanguageInMem? ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isCCPlusplusInMem? REM Input(s): REM langToDetect -- pass here to offset of name list of REM the language REM Output(s): REM Equality/Zero Flag -- if present in memory ;............................................................................ mov [ cs :langToDetect], offset ccplusLang call isLanguageInMem? ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc whatIsTheKeyword? REM Purpose: REM See if there is a word at the current cursor REM position REM REM Output Registers: REM Equality clear if there is no keyword at cursor REM Equality set if there is a keyword at cursor REM REM Output Variables: REM keywordAtCursor: data type = Pascal-like string ;............................................................................ mov ah , BIOS_GET_CURSOR_POS mov bh , 0 int 10h mov [ cs :prevCursorPos], dx mov cx , dx mov ah , BIOS_READ_CHAR_AT_POS mov bh , 0 int 10h cmp al , '.' je @_hasKeyword cmp al , '0' jl @_checkCharAtLeft REM -- the number 9 character REM precedes the colon character so REM it is just safe to do this kind REM of comparison cmp al , ':' jle @_hasKeyword cmp al , 'A' jl @_checkCharAtLeft cmp al , 'Z' jle @_hasKeyword cmp al , '_' je @_hasKeyword cmp al , 'a' jl @_checkCharAtLeft cmp al , 'z' jle @_hasKeyword jmp @_checkCharAtLeft ;............................................................................ @_checkCharAtLeft: REM -- now try if the character at the left REM is also valid dec cl mov dx , cx mov ah , BIOS_SET_CURSOR_POS mov bh , 0 int 10h mov ah , BIOS_READ_CHAR_AT_POS mov bh , 0 int 10h cmp al , '.' je @_hasKeyword cmp al , '0' jl @_noKeyword REM -- the number 9 character REM precedes the colon character so REM it is just safe to do this kind REM of comparison cmp al , ':' jle @_hasKeyword cmp al , 'A' jl @_noKeyword cmp al , 'Z' jle @_hasKeyword cmp al , '_' je @_hasKeyword cmp al , 'a' jl @_noKeyword cmp al , 'z' jle @_hasKeyword jmp @_noKeyword ;............................................................................ @_hasKeyword: mov dx , cx mov ah , BIOS_SET_CURSOR_POS mov bh , 0 int 10h REM -- loop until no more valid char @_loopWhileValidChar: REM -- this loop will go the beginning of the string mov ah , BIOS_READ_CHAR_AT_POS mov bh , 0 int 10h cmp al , '.' je @_checkNextChar cmp al , '0' jl @_noMoreValid REM -- the number 9 character REM precedes the colon character so REM it is just safe to do this kind REM of comparison cmp al , ':' jle @_checkNextChar cmp al , 'A' jl @_noMoreValid cmp al , 'Z' jle @_checkNextChar cmp al , '_' je @_checkNextChar cmp al , 'a' jl @_noMoreValid cmp al , 'z' jle @_checkNextChar @_checkNextChar: dec cl mov dx , cx mov ah , BIOS_SET_CURSOR_POS mov bh , 0 int 10h jmp @_loopWhileValidChar ;............................................................................ @_noMoreValid: REM -- go to valid character inc cl mov dx , cx mov ah , BIOS_SET_CURSOR_POS mov bh , 0 int 10h REM -- it is customary to use CX as a counter REM but since we use CX as a row and column, REM we had to find another register to store REM the length of the string REM in this case we had to choose DI register REM -- length of string is 0 tentatively mov di , 0 mov si , offset keywordAtCursor mov ah , BIOS_READ_CHAR_AT_POS mov bh , 0 int 10h jmp @_collectNow ;............................................................................ @_collectNow: REM -- collect chararacters mov [byte cs : si ], al REM -- increment keyword length inc di inc si mov ah , BIOS_SET_CURSOR_POS mov bh , 0 inc cl mov dx , cx int 10h mov ah , BIOS_READ_CHAR_AT_POS mov bh , 0 int 10h cmp al , '.' je @_collectNow cmp al , '0' jl @_stopCollecting REM -- the number 9 character REM precedes the colon character so REM it is just safe to do this kind REM of comparison cmp al , ':' jle @_collectNow cmp al , 'A' jl @_stopCollecting cmp al , 'Z' jle @_collectNow cmp al , '_' je @_collectNow cmp al , 'a' jl @_stopCollecting cmp al , 'z' jle @_collectNow jmp @_stopCollecting @_stopCollecting: REM -- finish collecting save the string length REM and restore the previous cursor position mov dx , di mov [ cs :keywordAtCursorLen], dl mov ah , BIOS_SET_CURSOR_POS mov bh , 0 mov dx , [ cs :prevCursorPos] int 10h ste ret ;............................................................................ @_noKeyword: mov ah , BIOS_SET_CURSOR_POS mov bh , 0 mov dx , [ cs :prevCursorPos] int 10h cle ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc preserveBackground REM -- save first the background mov ah , BIOS_GET_CURSOR_POS mov bh , 0 int 10h mov [ cs :prevCursorPos], dx REM -- B800h is the segment address of the REM CGA, VGA system push 0B800h pop ds mov si , 0 push cs pop es mov di , offset helpWinBackSave mov cx , SCREEN_BUFFER_SIZE cld rep movsb ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc restoreBackground push cs pop ds mov si , offset helpWinBackSave push 0B800h pop es mov di , 0 cld mov cx , SCREEN_BUFFER_SIZE rep movsb mov ah , BIOS_SET_CURSOR_POS mov bh , 0 mov dx , [ cs :prevCursorPos] int 10h ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc showWindow push cs pop ds mov ah , BIOS_SCROLL_WIN_UP mov al , WIN_Y2 sub al , WIN_Y1 inc al mov bh , WIN_BGCOLOR shl bh , 4 or bh , WIN_FGCOLOR mov ch , WIN_Y1 mov cl , WIN_X1 mov dh , WIN_Y2 mov dl , WIN_X2 int 10h mov ah , BIOS_SET_CURSOR_POS mov bh , 0 mov dl , WIN_X1 mov dh , WIN_Y1 int 10h mov ah , BIOS_WRITE_CHAR_ATTR mov al , ' ' mov bh , 0 mov bl , WIN_TITLEBGCOLOR shl bl , 4 or bl , WIN_TITLEFGCOLOR mov cx , 0 mov cl , WIN_X2 sub cl , WIN_X1 inc cx int 10h puts ' Augmented Help for C/C++ and Pascal ' mov al , WIN_Y1 inc al mov [ cs :cursorRowLoopVar], al @_loopSide: mov al , WIN_Y2 inc al cmp [ cs :cursorRowLoopVar], al jg @_finishWithSide mov ah , BIOS_SET_CURSOR_POS mov bh , 0 mov dh , [ cs :cursorRowLoopVar] mov dl , WIN_X2 inc dl int 10h mov ah , BIOS_READ_CHAR_ATTR mov bh , 0 int 10h REM -- now let us put a shadow mov bl , SHADOW_COLOR mov ah , BIOS_WRITE_CHAR_ATTR mov bh , 0 mov cx , 1 int 10h mov ah , BIOS_SET_CURSOR_POS mov bh , 0 mov dh , [ cs :cursorRowLoopVar] mov dl , WIN_X2 add dl , 2 int 10h mov ah , BIOS_READ_CHAR_ATTR mov bh , 0 int 10h REM -- now let us put a shadow mov bl , SHADOW_COLOR mov ah , BIOS_WRITE_CHAR_ATTR mov bh , 0 mov cx , 1 int 10h inc [ cs :cursorRowLoopVar] jmp @_loopSide @_finishWithSide: mov al , WIN_X1 add al , 2 mov [ cs :cursorColLoopVar], al @_loopBottom: mov al , WIN_X2 add al , 2 cmp [ cs :cursorColLoopVar], al je @_finishWithBottom mov ah , BIOS_SET_CURSOR_POS mov bh , 0 mov dh , WIN_Y2 inc dh mov dl , [ cs :cursorColLoopVar] int 10h mov ah , BIOS_READ_CHAR_ATTR mov bh , 0 int 10h REM -- now let us put a shadow mov bl , SHADOW_COLOR mov ah , BIOS_WRITE_CHAR_ATTR mov bh , 0 mov cx , 1 int 10h inc [ cs :cursorColLoopVar] jmp @_loopBottom @_finishWithBottom: ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc getCurrentFilePointer REM Input Register(s): REM BX -- file handle REM Output Register(s): REM DX : AX -- new file pointer location ;............................................................................ push bx push cx mov ah , DOS_FILE_MOVE_PTR mov al , DOS_FILE_CURRENT mov cx , 0 mov dx , 0 int 21h pop cx pop bx ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc displayTheChar TAB = 9 push ax push bx push cx push dx cmp [buffer], TAB ohYes @_displayTab mov ah , BIOS_READ_CHAR_ATTR mov bh , 0 int 10h mov bl , ah mov ah , BIOS_WRITE_CHAR_ATTR mov al , [buffer] mov bh , 0 mov cx , 1 int 10h mov ah , BIOS_GET_CURSOR_POS mov bh , 0 int 10h inc dl mov ah , BIOS_SET_CURSOR_POS mov bh , 0 int 10h jmp @_finish @_displayTab: mov cx , 8 @_displaySpace: push cx mov ah , BIOS_READ_CHAR_ATTR mov bh , 0 int 10h mov bl , ah mov ah , BIOS_WRITE_CHAR_ATTR mov al , ' ' mov bh , 0 mov cx , 1 int 10h mov ah , BIOS_GET_CURSOR_POS mov bh , 0 int 10h inc dl mov ah , BIOS_SET_CURSOR_POS mov bh , 0 int 10h pop cx loop @_displaySpace jmp @_finish @_finish: pop dx pop cx pop bx pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- REM Input(s): REM BX = offset of topic link proc unfocusHighlight pusha mov di , bx lea si , [(relatedTopics+ bx ).description] mov ch , 0 mov cl , [(relatedTopics+ bx ).stringLength] mov ah , BIOS_SET_CURSOR_POS mov bh , 0 mov dl , [(relatedTopics+ di ).column] mov dh , [(relatedTopics+ di ).row] int 10h lodsb cld @_displayHighlightedRelated: push cx push bx mov ah , BIOS_WRITE_CHAR_ATTR mov cx , 1 mov bl , WIN_RELATED_BGCOLOR shl bl , 4 or bl , WIN_RELATED_FGCOLOR int 10h mov ah , BIOS_SET_CURSOR_POS mov bh , 0 inc dl int 10h pop bx pop cx lodsb loop @_displayHighlightedRelated popa ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- REM Input(s): REM BX = offset of topic link proc focusHighlight pusha mov di , bx lea si , [(relatedTopics+ bx ).description] mov ch , 0 mov cl , [(relatedTopics+ bx ).stringLength] mov ah , BIOS_SET_CURSOR_POS mov bh , 0 mov dl , [(relatedTopics+ di ).column] mov dh , [(relatedTopics+ di ).row] int 10h lodsb cld @_displayHighlightedRelated: push cx push bx mov ah , BIOS_WRITE_CHAR_ATTR mov cx , 1 mov bl , WIN_RELATED_FGCOLOR shl bl , 4 or bl , WIN_RELATED_BGCOLOR int 10h mov ah , BIOS_SET_CURSOR_POS mov bh , 0 inc dl int 10h pop bx pop cx lodsb loop @_displayHighlightedRelated popa ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc displayTopic REM -- this is letter T TOPIC_MARKER = 20 REM -- this is letter S SAMPLE_MARKER = 19 REM -- this is letter X END_OF_TOPIC_MARKER = 24 REM -- this is letter A RELATED_TOPIC_MARKER = 1 REM -- this is Ctrl+Z EOF_OF_TEXT = 26 REM -- this is the carriage return NEXTLINE_MARKER = 0Dh ;............................................................................ REM -- we will concentrate more on our data segment REM so we must point DS segment to our code REM segment , so we can just avoid REM the numerous segment override prefix, REM just in case you are a beginning assembly REM programmer, segment override prefix is REM like this: mov [ cs :helpFileHandle], where REM you always explicit places a segment REM prefix( cs , ds , es , ss ). at the beginning REM of every variable REM the following two instructions will prevent REM tedious typing of segment prefix push cs pop ds mov ah , DOS_GET_DTA int 21h push es pop [prevDTASeg] push bx pop [prevDTAOffs] mov ah , DOS_SET_DTA mov dx , offset dta int 21h BUG -- this following lines are missing from BUG the distributed diskette causing an BUG a very serious error which when BUG the 'augment.hlp' file is missing, BUG the system will simply hang. BUG now in this code, the system will BUG not hang it will just sound a beep BUG when the help file is not present mov ah , DOS_FILE_FIND_FIRST mov dx , offset helpFilenameFullpath int 21h jnc @_fileExisting mov dx , [prevDTAOffs] push [prevDTASeg] pop ds mov ah , DOS_SET_DTA int 21h mov ah , DOS_DISPLAY_OUTPUT mov dl , BEEP int 21h ret @_fileExisting: push cs pop es mov ah , DOS_FILE_OPEN mov al , READ_ACCESS mov dx , offset helpFilenameFullpath int 21h mov [helpFileHandle], ax @_readFromTop: mov [clipboardLength], 0 mov ah , DOS_FILE_MOVE_PTR mov al , DOS_FILE_BEGIN mov bx , [helpFileHandle] mov cx , 0 mov dx , 0 int 21h REM -- read first character at line mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h jmp @_loopUntilTopicFoundOrEOF @_loopUntilTopicFoundOrEof: @_loopUntilTopicMarkerFound: cmp ax , 0 ohYes @_noTopicFound cmp [buffer], TOPIC_MARKER ohYes @_whatIsTheTopic mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h jmp @_loopUntilTopicMarkerFound @_whatIsTheTopic: REM -- skip marker mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h mov [bytesRead], ax REM -- register DI will be our counter for REM number of characters of keyword from file mov di , 0 mov si , offset keywordFromFile jmp @_loopUntilKeywordEoln @_loopUntilKeywordEoln: cmp [bytesRead], 0 ohYes @_stopReading cmp [buffer], NEXTLINE_MARKER ohYes @_keywordFromFileFinish mov al , [buffer] mov [byte si ], al mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h inc di inc si jmp @_loopUntilKeywordEoln @_keywordFromFileFinish: mov dx , di mov [keywordFromFileLen], dl mov al , [keywordAtCursorLen] mov bl , [keywordFromFileLen] cmp al , bl ohNo @_stringLenNotMatch mov ch , 0 mov cl , [keywordAtCursorLen] mov si , offset keywordAtCursor mov di , offset keywordFromFile cld repe cmpsb ohNo @_loopUntilTopicFoundOrEOF jmp @_topicFound @_stringLenNotMatch: mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h jmp @_loopUntilTopicFoundOrEof ;............................................................................ @_noTopicFound: push ax push dx mov ah , DOS_DISPLAY_OUTPUT mov dl , 07 int 21h pop dx pop ax jmp @_stopReading ;............................................................................ @_topicFound: mov [topicPageCount], 0 REM -- skip NEW LINE character ASCII 0Ah mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h REM -- for the moment let's make this simpler REM -- display immediately the character call preserveBackground call showWindow push cs pop ds push cs pop es mov bx , [helpFileHandle] call getCurrentFilePointer mov [topicFirstPageLoc.dataHiWord], dx mov [topicFirstPageLoc.dataLoWord], ax mov [topicPageLocList.dataHiWord], dx mov [topicPageLocList.dataLoWord], ax mov [topicPageCount], 0 mov [lineCountTheFile], 0 @_savePagesLocation: mov [bytesRead], ax cmp [bytesRead], 0 ohYes @_savePagesLocationFinished cmp [buffer], NEXTLINE_MARKER ohYes @_incrementLine cmp [buffer], SAMPLE_MARKER ohYes @_copySample cmp [buffer], END_OF_TOPIC_MARKER ohYes @_savePagesLocationFinished mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h jmp @_savePagesLocation @_incrementLine: inc [lineCountTheFile] cmp [lineCountTheFile], MAX_LINE_IN_PAGE ohYes @_saveThePageLocation REM -- this will skip the newline character mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h jmp @_savePagesLocation @_saveThePageLocation: mov [lineCountTheFile], 0 inc [topicPageCount] REM -- this will skip the newline character mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h mov bx , [helpFileHandle] call getCurrentFilePointer REM -- this is not a heavy trick, this is very REM common in assembly language routines, REM where if you want to multiply the number REM by increment of twos you can shift left REM it, instead of using the mul instruction. REM Since we want to multiply by 4(size of REM doubleword), we must shift left by 2. mov bx , [topicPageCount] shl bx , 2 mov [(topicPageLocList+ bx ).dataHiWord], dx mov [(topicPageLocList+ bx ).dataLoWord], ax jmp @_savePagesLocation @_copySample: REM -- this will skip the Carriage Return character mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h mov [bytesRead], ax REM -- this will skip the Linefeed character mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h mov [bytesRead], ax mov [clipboardLinesCount], 0 mov [clipboardLength], 0 mov si , offset clipboardBuffer @_collectSample: mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h mov [bytesRead], ax cmp [buffer], NEXTLINE_MARKER ohYes @_incClipboardLinesCount cmp [buffer], END_OF_TOPIC_MARKER ohYes @_finishCopyingClipboard mov al , [buffer] mov [byte si ], al inc si inc [clipboardLength] jmp @_collectSample @_incClipboardLinesCount: mov al , [buffer] mov [byte si ], al inc si REM -- skip the newline character mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h mov [bytesRead], ax inc [clipboardLinesCount] inc [clipboardLength] mov [byte si ], HOME inc si inc [clipboardLength] jmp @_collectSample @_finishCopyingClipboard: mov cx , [clipboardLinesCount] add [clipboardLength], cx @_insertUPS: mov [byte si ], UP inc si loop @_insertUPS jmp @_savePagesLocationFinished @_savePagesLocationFinished: jmp @_dumpInformation ;............................................................................ @_dumpInformation: mov [topicCurrentPage], 0 @_dumpInformationLoop: REM -- 0 as of the moment, we have not yet dumped REM the whole page mov [relatedTopicsCount], 0 call showWindow push cs pop ds push cs pop es REM -- it is customary to use register BX as base REM register for array but since we ran out of REM register variables, we opt use the SI register mov si , [topicCurrentPage] shl si , 2 mov ah , DOS_FILE_MOVE_PTR mov al , DOS_FILE_BEGIN mov bx , [helpFileHandle] mov cx , [(topicPageLocList+ si ).dataHiWord] mov dx , [(topicPageLocList+ si ).dataLoWord] int 21h REM -- dump the character in the window mov [lineCountTheScreen], 0 @_loopRow: mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h mov [bytesRead], ax mov cx , [lineCountTheScreen] add cx , WIN_Y1+1 inc cx mov ah , BIOS_SET_CURSOR_POS mov bh , 0 mov dl , WIN_X1+2 mov dh , cl int 10h cmp [lineCountTheScreen], MAX_LINE_IN_PAGE ohYes @_finishDisplayPage inc [lineCountTheScreen] @_loopUntilEoln: cmp [bytesRead], 0 ohYes @_finishDisplayLine cmp [buffer], NEXTLINE_MARKER ohYes @_finishDisplayLine cmp [buffer], RELATED_TOPIC_MARKER ohYes @_linkTheTopic cmp [buffer], SAMPLE_MARKER ohYes @_sampleFound cmp [buffer], END_OF_TOPIC_MARKER ohYes @_finishDisplayPage call displayTheChar mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h mov [bytesRead], ax jmp @_loopUntilEoln @_finishDisplayLine: REM -- this will skip the new line character mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h mov [bytesRead], ax jmp @_loopRow ;............................................................................ @_sampleFound: push ax push bx push dx mov ah , BIOS_SET_CURSOR_POS mov bh , 0 mov dl , WIN_X2-2 mov dh , WIN_Y1 int 10h mov ah , DOS_DISPLAY_OUTPUT REM -- happy face mov dl , 1 int 21h pop dx pop bx pop ax ;............................................................................ @_finishDisplayPage: REM -- is related topics not available ? cmp [relatedTopicsCount], 0 je @_controlPageByKey REM -- available so highlight all the related topics mov bx , 0 @_highlightRelateds: imul di , bx , size topicLink lea si , [(relatedTopics+ di ).description] mov ch , 0 mov cl , [(relatedTopics+ di ).stringLength] mov ah , BIOS_SET_CURSOR_POS mov bh , 0 mov dl , [(relatedTopics+ di ).column] mov dh , [(relatedTopics+ di ).row] int 10h lodsb cld @_displayHighlightedRelated: push cx push bx mov ah , BIOS_WRITE_CHAR_ATTR mov cx , 1 mov bl , WIN_RELATED_BGCOLOR shl bl , 4 or bl , WIN_RELATED_FGCOLOR int 10h mov ah , BIOS_SET_CURSOR_POS mov bh , 0 inc dl int 10h pop bx pop cx lodsb loop @_displayHighlightedRelated inc bx cmp bx , [relatedTopicsCount] jl @_highlightRelateds mov [relatedTopicIndex], 0 mov ax , [relatedTopicIndex] imul bx , ax , size topicLink call focusHighlight jmp @_controlPageByKey ;............................................................................ @_linkTheTopic: REM -- this will skip the tag marker mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h mov ah , BIOS_GET_CURSOR_POS mov bh , 0 int 10h mov ax , [relatedTopicsCount] imul bx , ax , size topicLink mov [(relatedTopics+ bx ).column], dl mov [(relatedTopics+ bx ).row], dh mov [(relatedTopics+ bx ).stringLength], 0 lea si , [(relatedTopics+ bx ).description] jmp @_displayRelatedTopicChars @_displayRelatedTopicChars: cmp [buffer], RELATED_TOPIC_MARKER ohYes @_finishCollectingRelatedTopicChars mov al , [buffer] mov [byte si ], al call displayTheChar push bx mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h pop bx inc [(relatedTopics+ bx ).stringLength] inc si jmp @_displayRelatedTopicChars @_finishCollectingRelatedTopicChars: mov ah , DOS_FILE_READ mov bx , [helpFileHandle] mov dx , offset buffer mov cx , size buffer int 21h mov [bytesRead], ax inc [relatedTopicsCount] jmp @_loopUntilEoln ;............................................................................ @_controlPageByKey: mov ah , BIOS_OLD_READKEY pushf call [preAHAddr] cmp ax , KB_ESCAPE ohYes @_backToTheEditor cmp ax , KB_PAGE_UP ohYes @_goToPrevPage cmp ax , KB_PAGE_DOWN ohYes @_goToNextPage cmp ax , KB_SHIFT_TAB ohYes @_highlightPrevTopic cmp ax , KB_TAB ohYes @_highlightNextTopic cmp ax , KB_ENTER ohYes @_changeTopic cmp ax , KB_INSERT ohYes @_insertSample jmp @_controlPageByKey ;............................................................................ @_insertSample: cmp [clipboardLength], 0 je @_controlPageByKey mov [ptrToText], offset clipboardBuffer mov bx , [clipboardLength] lea ax , [clipboardBuffer+ bx ] mov [endingInsertOffset], ax jmp @_backToTheEditor ;............................................................................ @_highlightPrevTopic: cmp [relatedTopicsCount], 0 je @_controlPageByKey cmp [relatedTopicIndex], 0 je @_highlightPrevTopicContinue call unfocusHighlight dec [relatedTopicIndex] mov ax , [relatedTopicIndex] imul bx , ax , size topicLink call focusHighlight jmp @_highlightPrevTopicContinue @_highlightPrevTopicContinue: jmp @_controlPageByKey ;............................................................................ @_highlightNextTopic: cmp [relatedTopicsCount], 0 je @_controlPageByKey mov ax , [relatedTopicsCount] dec ax cmp [relatedTopicIndex], ax jnl @_highlightNextTopicContinue call unfocusHighlight inc [relatedTopicIndex] mov ax , [relatedTopicIndex] imul bx , ax , size topicLink call focusHighlight jmp @_highlightNextTopicContinue @_highlightNextTopicContinue: jmp @_controlPageByKey ;............................................................................ @_changeTopic: mov ax , [relatedTopicIndex] imul bx , ax , size topicLink mov cl , [(relatedTopics+ bx ).stringLength] mov [keywordAtCursorLen], cl lea si , [(relatedTopics+ bx ).description] mov di , offset keywordAtCursor mov ch , 0 cld rep movsb call restoreBackground push cs pop es jmp @_readFromTop ;............................................................................ @_goToPrevPage: cmp [topicCurrentPage], 0 je @_goToPrevPageContinue dec [topicCurrentPage] jmp @_dumpInformationLoop @_goToPrevPageContinue: jmp @_controlPageByKey ;............................................................................ @_goToNextPage: mov ax , [topicPageCount] cmp [topicCurrentPage], ax jnl @_goToNextPageContinue inc [topicCurrentPage] jmp @_dumpInformationLoop @_goToNextPageContinue: jmp @_controlPageByKey ;............................................................................ @_backToTheEditor: @_unpopWindow: call restoreBackground @_stopReading: mov dx , [prevDTAOffs] push [prevDTASeg] pop ds mov ah , DOS_SET_DTA int 21h push cs pop ds mov ah , DOS_FILE_CLOSE mov bx , [helpFileHandle] int 21h ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc doHelp pushf push ax push bx push cx push dx push si push ds push di push es call whatIsTheKeyword? ohNo @_noTopicAtCursor jmp @_topicAtCursor @_quiet: pop es pop di pop ds pop si pop dx pop cx pop bx pop ax popf ret @_topicAtCursor: call displayTopic pop es pop di pop ds pop si pop dx pop cx pop bx pop ax popf ret @_noTopicAtCursor: REM -- put a message here, or just beep mov [ cs :keywordAtCursor], 'M' mov [ cs :keywordAtCursor+1], 'L' mov [ cs :keywordAtCursor+2], 'T' mov [ cs :keywordAtCursor+3], 'H' mov [ cs :keywordAtCursorLen], 4 call displayTopic pop es pop di pop ds pop si pop dx pop cx pop bx pop ax popf ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc keyIntercept jmp @_beginning tsrMarker db 'AH-MLTH' @_beginning: pushf push es push di les di , [ cs :dosBusyFlagAddr] cmp [byte ptr es : di ], 0 ohYes @_continueBeginningLanguage @_donotContinueBeginningLanguage: pop di pop es popf jmp [ cs :preAHAddr] @_continueBeginningLanguage: pop di pop es popf call isPascalInMem? ohYes @_continueBeginningPascal call isCCPlusplusInMem? ohYes @_continueBeginningCCPlusplus jmp @_doOld ;............................................................................ @_continueBeginningPascal: jmp @_continueBeginning ;............................................................................ @_continueBeginningCCPlusplus: jmp @_continueBeginning ;............................................................................ @_continueBeginning: cmp ah , BIOS_OLD_READKEY ohYes @_tryKeyread cmp ah , BIOS_NEW_READKEY ohYes @_tryKeyread cmp ah , BIOS_OLD_KEYSTAT ohYes @_tryKeystat cmp ah , BIOS_NEW_KEYSTAT ohYes @_tryKeystat jmp @_doOld ;............................................................................ @_tryKeystat: cmp [ cs :stuffing], TRUE ohYes @_keystatInsert pushf call [ cs :preAHAddr] ;;;; jnz @_keystatTestPasting stz retf 2 @_keystatTestPasting: cmp ax , PASTE_HOTKEY ohYes @_keystatInsertIntro cmp ax , KB_F11 ohYes @_keystatInsertIntroF11 clz retf 2 @_keystatInsertIntro: mov ah , BIOS_OLD_READKEY pushf call [ cs :preAHAddr] mov [ cs :stuffing], TRUE jmp @_keystatInsert @_keystatInsertIntroF11: mov ah , BIOS_NEW_READKEY pushf call [ cs :preAHAddr] mov [ cs :stuffing], TRUE jmp @_keystatInsert @_keystatInsert: push bx mov ah , 00h mov bx , [ cs :ptrToText] mov al , [byte cs : bx ] cmp bx , [ cs :endingInsertOffset] jl @_continueKeystatInsert mov [ cs :stuffing], FALSE pop bx stz retf 2 @_continueKeystatInsert: mov [ cs :stuffing], TRUE cmp al , HOME ohYes @_keystatInsertHome jmp @_keystatInsertOrdinary @_keystatInsertHome: pop bx mov ax , KB_HOME clz retf 2 @_keystatInsertOrdinary: pop bx clz retf 2 ;............................................................................ @_tryKeyread: cmp [ cs :stuffing], TRUE ohYes @_keyreadInsert pushf call [ cs :preAHAddr] cmp ax , SHORTCUT_HOTKEY ohYes @_performHelp cmp ax , PASTE_HOTKEY ohYes @_keyreadPasteExample cmp ax , KB_F11 ohYes @_keyreadPasteExample jmp @_normalKey @_keyreadPasteExample: mov [ cs :stuffing], TRUE jmp @_keyreadInsert @_performHelp: call doHelp iret @_keyreadInsert: push bx mov ah , 00h mov bx , [ cs :ptrToText] mov al , [byte cs : bx ] cmp bx , [ cs :endingInsertOffset] setl [ cs :stuffing] pop bx cmp al , HOME ohYes @_keyreadInsertHome jmp @_keyreadInsertOrdinary @_keyreadInsertHome: mov ax , KB_HOME inc [ cs :ptrToText] dec [ cs :clipboardLength] iret @_keyreadInsertOrdinary: inc [ cs :ptrToText] dec [ cs :clipboardLength] iret ;............................................................................ @_normalKey: iret ;............................................................................ @_doOld: jmp [ cs :preAHAddr] endp tsrSize = ( ( $ - start ) + 256 + 16 ) / 16 ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc freeEnvironment REM Output Register(s): REM ES - segment address of the Environment ;............................................................................ push ax mov ah , DOS_RELEASE_MEM mov es , [ ds :ENVIRONMENT_SEGMENT] int 21h pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isTSRInMem? REM Output Register(s): REM ES - segment address of the TSR REM Zero/Equality Flag: REM Set when TRUE -- z / e REM Clear when FALSE -- nz / ne ;............................................................................ push si push di push ax push cx mov ah , DOS_INTR_GET_VECT mov al , KB_SOFTWARE_INTR int 21h REM -- 8 is an arbitrary value, it can be REM any number greater than one, but for REM the program to surely detect if TS REM signature really match we choose REM more or less 8 mov cx , 8 mov si , offset tsrMarker mov di , bx REM -- we add 3 to DI , the tsrmarker's offset REM from the beginning of jmp instruction is 3 add di , 3 cld repe cmpsb ohYes @_alreadyInMem jmp @_notInMem ;............................................................................ @_notInMem: REM -- the ff. will force clear the equality cle jmp @_finally ;............................................................................ @_alreadyInMem: ste jmp @_finally ;............................................................................ @_finally: pop cx pop ax pop di pop si ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc removeTSRInMem REM Input Register(s): REM ES - segment address of the TSR REM Output Register(s): REM Zero/Equality Flag: REM Set when SUCCESS -- z / e REM Clear when FAILED -- nz / ne REM Carry Flag: REM Set when FAILED -- c REM Clear when SUCCESS -- nc ;............................................................................ push ax ;............................................................................ @_tryRelease: mov ah , DOS_RELEASE_MEM int 21h jc @_clearEqual REM -- success removing ste jmp @_finally ;............................................................................ @_clearEqual: REM -- no success in removing cle jmp @_finally ;............................................................................ @_finally: pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc putCodeInMem REM -- returns nothing. REM this function does not return to the calling function REM instead it directly returns to DOS REM so it is okay not to preserve used registers ;............................................................................ REM -- we have no use for environment strings call freeEnvironment mov ah , DOS_GET_BUSY_FLAG_ADDR int 21h mov [dosBusyFlagOfs], bx mov [dosBusyFlagSeg], es mov ah , DOS_INTR_GET_VECT mov al , KB_SOFTWARE_INTR int 21h mov [preAHOffset], bx mov [preAHSegment], es mov ah , DOS_INTR_SET_VECT mov al , KB_SOFTWARE_INTR mov dx , offset keyIntercept int 21h mov ah , DOS_KEEP_TSR mov dx , tsrSize int 21h endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- REM -- this variable is use to get the exact subdirectory REM path of the program backslashOffset dw ? proc getFullPathOfHelpFile pushf pusha mov es , [ es :ENVIRONMENT_SEGMENT] REM -- this is the marker of the full filename mov al , 1 REM -- 32 kilobytes is the size of the environment REM strings at most mov cx , 32*1024 mov di , 0 cld repne scasb mov si , offset helpfilenameFullpath inc di @_loopThrough: mov al , [byte es : di ] mov [byte si ], al cmp [byte es : di ], 0 je @_finishStrippingFullpath cmp [byte es : di ], '\' je @_rememberLastBackSlash inc di inc si jmp @_loopThrough @_rememberLastBackSlash: mov [backslashOffset], si inc si inc di jmp @_loopThrough @_finishStrippingFullpath: REM -- now concatenate the help filename push cs pop es push cs pop ds mov di , [backslashOffset] inc di mov si , offset helpfilename mov cx , size helpFilename + 1 cld rep movsb ;; mov cx, 67 ;; mov si, offset helpfilenameFullpath ;;@_loop: ;; mov ah, 02 ;; mov dl, [si] ;; int 21h ;; inc si ;; loop @_loop popa popf ;;; mov ah, 4Ch ;;; int 21h ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isCommandLineEmpty? REM -- returns equal(e/z) when true otherwise not equal(ne/nz) ;............................................................................ REM -- do we have a command line? test the length pusha cmp [byte es :COMMAND_LINE_LEN_OFFSET], 00h jz @_noCommandLine mov di , 81h mov ch , 0 mov cl , [byte es :80h] mov al , ' ' cld repe scasb je @_noCommandLine clz jmp @_finally @_noCommandLine: ste jmp @_finally @_finally: popa ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isCommandLineSlashU? REM Output Register(s): REM Zero/Equality Flag: REM Set when TRUE -- z / e REM Clear when FALSE -- nz / ne ;............................................................................ push ax push cx push dx push di push si REM -- scan for slash character mov al , '/' mov ch , 0 mov cl , [byte es :80h] mov di , 81h cld repne scasb ohNo @_notAU REM -- convert the next character to uppercase mov ax , DOS_CHAR_UP_CASE mov dl , [byte es : di ] int 21h mov [byte es : di ], dl cmp [byte es : di ], 'U' ohNo @_notAU jmp @_aU ;............................................................................ @_aU: ste jmp @_finally ;............................................................................ @_notAU: cle jmp @_finally ;............................................................................ @_finally: pop si pop di pop dx pop cx pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc restoreOldRoutine REM Input Register(s): REM ES - segment address of the TSR REM Output Register(s): REM None ;............................................................................ push ax push dx push ds mov ax , [ es :preAHSegment] mov ds , ax mov ah , DOS_INTR_SET_VECT mov al , KB_SOFTWARE_INTR mov dx , [ es :preAHOffset] int 21h pop ds pop dx pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc getInitialMCBSegment REM Purpose: REM Get initial MCB Segment, which is very useful REM in traversing memory links, to see if a particular REM program is in memory REM In our program this is use for inquiring the REM language loaded in memory (Pascal or C/C++?) REM Input(s): REM None REM Output Variables: REM initialMCBSegment: data type = word ;............................................................................ push ax push es push bx mov ah , DOS_GET_INITIAL_MCB int 21h mov ax , [word es : bx -2] mov [ cs :initialMCBSegment], ax pop bx pop es pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc motd newLine jmp @_motdj @_michael db 'Vrxsz~w;Yn~u' @_terminator db '$' @_motdj: mov cx , offset @_terminator - offset @_michael mov si , offset @_michael @_motdjloop: xor [byte ptr si ], 27 inc si loop @_motdjloop mov ah , 09h mov dx , offset @_michael int 21h newLine newLine puts '"The cure for boredom is curiosity.' newLine puts ' There is no cure for curiosity."' newLine newLine puts ' -- Dorothy Parker' newLine ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc isHelpFileExisting? push ax push cx push dx mov ah , DOS_FILE_FIND_FIRST mov cx , 00h mov dx , offset helpfilenameFullpath int 21h jc @_notOkay jmp @_okay @_notOkay: cle jmp @_finally @_okay: ste jmp @_finally @_finally: pop dx pop cx pop ax ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc setDiskTransferArea mov ah , DOS_SET_DTA mov dx , offset dta int 21h ret endp ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- proc main call setDiskTransferArea call getFullPathOfHelpFile call isHelpFileExisting? ohNo @_noHelpFileFound call getInitialMCBSegment @_tryCommandLine: call isCommandLineEmpty? ohYes @_tryInstall call isCommandLineSlashU? ohYes @_tryUninstall puts 'Unknown Option' jmp @_finally ;............................................................................ @_tryUninstall: call isTSRInMem? ohNo @_tsrNotYetInMem call removeTSRInMem ohNo @_cantRemoveTSRInMem call restoreOldRoutine puts 'Augmented Help Unloaded' jmp @_finally ;............................................................................ @_cantRemoveTSRInMem: puts 'Cant' 't remove TSR in Mem' jmp @_finally ;............................................................................ @_tryInstall: call isTSRInMem? ohYes @_tsrAlreadyInMem puts 'Augmented Help Loaded' call motd call putCodeInMem jmp @_finally ;............................................................................ @_tsrNotYetInMem: puts 'Augmented Help not yet in memory' jmp @_finally ;............................................................................ @_tsrAlreadyInMem: puts 'Augmented Help already in memory' jmp @_finally ;............................................................................ @_noHelpFileFound: puts 'Not found: ' mov si , offset helpfilenameFullpath @_displayChars: cmp [byte si ], 0 ohYes @_finishDisplayChars mov ah , 02 mov dl , [byte si ] int 21h inc si jmp @_displayChars @_finishDisplayChars: newLine jmp @_finally ;............................................................................ @_finally: call motd mov ah , DOS_EXIT int 21h ;............................................................................ endp ends end start ; MICHAEL BUEN |
The program library. The old school .NET framework, heheh :D
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 | ; FILENAME: USEFUL.INC ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- macro REM endm ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- macro BUG endm ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- DOS_MAXPATHLEN = 67 REM -- DOS interrupt 0x21 DOS_DISPLAY_OUTPUT = 02h REM Input(s): REM DL - 8 bit character data ;............................................................................ REM -- DOS interrupt 0x21 DOS_FILE_CREATE = 3Ch REM Input(s): REM CX - File Attribute REM 0000h Normal REM 0002h Hidden REM 0004h System REM 0006h Hidden+System REM DS : DX - Pointer to ASCIIZ filename REM Output(s): REM Carry Flag Clear if Successful REM AX - File Handle REM Carry Flag Set if Error REM AX - Error Code PATH_NOT_FOUND = 03h NO_HANDLES_AVAILABLE = 04h ACCESS_DENIED = 05h ;............................................................................ REM -- DOS Interrupt 21h DOS_FILE_CREATE_SAFE = 5Bh REM Input(s): REM CX - File Attribute REM 0000h Normal REM 0002h Hidden REM 0004h System REM 0006h Hidden+System REM DS : DX - Pointer to ASCIIZ filename REM Output(s): REM Carry Flag Clear if Successful REM AX - File Handle REM Carry Flag Set if Error REM AX - Error Code PATH_NOT_FOUND = 03h NO_HANDLES_AVAILABLE = 04h ACCESS_DENIED = 05h FILE_ALREADY_EXIST = 50h ;............................................................................ REM -- DOS Interrupt 21h DOS_FILE_CLOSE = 3Eh REM Input(s): REM BX - File Handle REM Output(s): REM Carry Flag Clear if Successful REM Carry Flag Set if Error REM AX - Error Code INVALID_HANDLE = 06h ;............................................................................ REM -- DOS Interrupt 21h DOS_FILE_OPEN = 3Dh REM Input(s): REM AL - Access Mode REM Bit REM 76543210 REM .....000 Read Access REM .....001 Write Access REM .....010 Read/Write Access READ_ACCESS = 0h WRITE_ACCESS = 1h READ_WRITE_ACCESS = 2h REM DS : DX - ASCIIZ Filename REM Output(s): REM AX - File Handle REM Carry Flag Clear if Successful REM Carry Flag Set if Error REM Error Codes in AX : INVALID_FUNCTION = 01h FILE_NOT_FOUND = 02h PATH_NOT_FOUND = 03h NO_HANDLES_AVAILABLE = 04h ACCESS_DENIED = 05h INVALID_ACCESS_CODE = 0Ch ;............................................................................ REM -- DOS interrupt 21h DOS_FILE_WRITE = 40h REM Input(s): REM BX - File Handle REM CX - Number of Bytes REM DS : DX - Pointer to Buffer REM Output(s): REM AX - number of bytes rad REM Carry Flag Clear if Successful REM Carry Flag Set if error REM Error Code in AX : ACCESS_DENIED = 05h INVALID_HANDLE = 06h ;............................................................................ REM -- DOS interrupt 21h DOS_FILE_READ = 3Fh REM Input(s): REM BX - File Handle REM CX - Number of Bytes REM DS : DX - Pointer to Buffer REM Output(s): REM AX - number of bytes rad REM Carry Flag Clear if Successful REM Carry Flag Set if error REM Error Code in AX : REM 05h - Access Denied REM 06h - Invalid Handle ;............................................................................ REM -- DOS interrupt 21h DOS_FILE_MOVE_PTR = 42h REM Input(s): REM BX - File Handle REM AL - METHOD CODE DOS_FILE_BEGIN = 00h DOS_FILE_CURRENT = 01h DOS_FILE_END = 02h REM CX - Most Significant Part of Offset REM DX - Least Significant Part of Offset REM Output(s): REM DX : AX - New File Pointer Location REM Carry Flag Clear if Successful REM Carry Flag Set if Error REM Error Code in AX : REM 01h - Invalid Function REM 06h - Invalid Handle ;............................................................................ DOS_NORMAL_FILE = 0000h ;............................................................................ REM -- DOS interrupt 21h DOS_FILE_FIND_FIRST = 4Eh REM Input(s): REM CX - Attribute to use in search REM DS : DX - pointer to ASCIIZ file specification REM Output(s): REM Carry Flag Clear if Successful REM Carry Flag Set if Error REM Error Code in AX : DOS_FILE_NOT_FOUND = 0002h DOS_INVALID_PATH = 0003h DOS_NO_MORE_FILES = 0012h ;............................................................................ REM -- DOS interrupt 21h DOS_CHAR_UP_CASE = 6520h REM Input(s): REM DL - character to be uppercased REM Output(s): REM DL - uppercased character REM Carry Flag Clear if Successful REM Carry Flag Set if Error ;............................................................................ REM -- DOS interrupt 21h DOS_INTR_GET_VECT = 35h REM Input(s): REM AL - Interrupt Number REM Output(s): REM ES : BX - Pointer to Handler ;............................................................................ REM -- DOS interrupt 21h DOS_INTR_SET_VECT = 25h REM Input(s): REM AL - Interrupt Handler REM DS : DX - Pointer to Interrupt Handler ;............................................................................ REM -- DOS interrupt 21h DOS_KEEP_TSR = 31h REM Input(s): REM AL - Return Code REM DX - Memory size to reserve in paragraph ;............................................................................ REM -- DOS interrupt 21h DOS_FILE_DELETE = 41h REM Input(s): REM DS : DX - Pointer to ASCIIZ file specification REM Output(s): REM Carry Flag Clear if Successful REM Carry Flag Set if Error REM AX - Error Code FILE_NOT_FOUND = 0002h ACCESS_DENIED = 0005h ;............................................................................ REM -- DOS interrupt 21h DOS_FILE_RENAME = 56h REM Input(s): REM DS : DX - Pointer to ASCIIZ current file name REM ES : DI - Pointer to ASCIIZ new filename REM Output(s): REM Carry Flag Clear if Successful REM Carry Flag Set if Error REM AX - Error Code PATH_NOT_FOUND = 0003h NO_HANDLES_AVAILABLE = 0004h ACCESS_DENIED = 0005h NOT_THE_SAME_DEVICE = 0011h ;............................................................................ REM -- DOS interrupt 21h DOS_CREATE_DIRECTORY = 39h REM Input(s): REM DS : DX - Pointer to ASCIIZ path specification REM Output(s): REM Carry Flag Clear if Successful REM Carry Flag Set if Error PATH_NOT_FOUND = 0003h ACCESS_DENIED = 0005h ;............................................................................ REM -- DOS interrupt 21h DOS_GET_INITIAL_MCB = 52h REM Output(s): REM ES : BX - Pointer to first MCB ;............................................................................ REM -- DOS interrupt 21h DOS_GET_BUSY_FLAG_ADDR = 34h REM Output(s): REM ES : BX - Pointer to InDOS Flag REM value is 0 if not busy ;............................................................................ REM -- DOS interrupt 21h DOS_EXIT = 4Ch REM Input(s): REM AL - Return Code ;............................................................................ REM -- DOS interrupt 21 DOS_RELEASE_MEM = 49h REM Input(s): REM ES - Segment Address of Block to Freed REM Output(s): REM Carry Flag clear if Successful REM AX - Error Code MCB_DESTROYED = 0007h MCB_INVALID = 0009h ;............................................................................ REM -- DOS interrupt 16h DOS_SET_DTA = 1Ah REM Input(s): REM DS : DX - pointer to a new DTA ;............................................................................ REM -- DOS interrupt 16h DOS_GET_DTA = 1Ah REM Output(s): REM ES : BX - pointer to DTA ;............................................................................ REM -- BIOS interrupt 16h BIOS_OLD_KEYSTAT = 01h REM Output(s): REM AL - ASCII Code REM AH - Scan Code REM Zero Flag Clear if there is a key available REM Zero Flag Set if there is no key available ;............................................................................ REM -- BIOS interrupt 16h BIOS_NEW_KEYSTAT = 11h REM Output(s): REM AL - ASCII Code REM AH - Scan Code REM Zero Flag Clear if there is a key available REM Zero Flag Set if there is no key available ;............................................................................ REM -- BIOS interrupt 16h BIOS_OLD_READKEY = 00h REM Output(s): REM AL - ASCII Code REM AH - Scan Code ;............................................................................ REM -- BIOS interrupt 16h BIOS_NEW_READKEY = 10h REM Output(s): REM AL - ASCII Code REM AH - Scan Code ;............................................................................ REM -- BIOS interrupt 10h BIOS_TELETYPE_WRITE = 0Eh REM Input(s): REM AL - Character REM BH - Display Page REM BL - Foreground Color ;............................................................................ REM -- BIOS interrupt 10h BIOS_GET_CURSOR_POS = 03h REM Input(s): REM BH - page number REM Output(s): REM DL - column REM DH - row ;............................................................................ REM -- BIOS interrupt 10h BIOS_SET_CURSOR_POS = 02h REM Input(s): REM BH - page number REM DL - column REM DH - row ;............................................................................ REM -- BIOS interrupt 10h BIOS_READ_CHAR_AT_POS = 08h REM Input(s): REM BH - page number REM Output(s): REM AL - the character ;............................................................................ REM -- BIOS interrupt 10h BIOS_SCROLL_WIN_UP = 06h REM Input(s): REM AL - Number of lines to scroll REM BH - Attribute use for blank area REM CH - Row, upper left corner REM CL - Column, upper lef corner REM DH - Row, lower right corner REM DL - Column, lower right corner ;............................................................................ REM -- BIOS interrupt 10h BIOS_READ_CHAR_ATTR = 08h REM Input(s): REM BH - Display Page REM Output(s): REM AH - Attribute Byte REM AL - Ascii Character ;............................................................................ REM -- BIOS interrupt 10h BIOS_WRITE_CHAR_ATTR = 09h REM Input(s): REM AL - Character REM BH - Display Page REM BL - Attribute bye of character in AL REM CX - Number of Characters to write ;............................................................................ REM - COLORS - REM -- dark colors BLACK = 00h BLUE = 01h GREEN = 02h CYAN = 03h RED = 04h MAGENTA = 05h BROWN = 06h LIGHTGRAY = 07h DARKGRAY = 08h REM -- light colors LIGHTBLUE = 09h LIGHTGREEN = 0Ah LIGHTCYAN = 0Bh LIGHTRED = 0Ch LIGHTMAGENTA = 0Dh YELLOW = 0Eh WHITE = 0Fh ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- macro ohNo addr jne addr endm ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- macro ohYes addr je addr endm ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- macro cle push ax mov ax , 0 cmp ax , 1 pop ax endm ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- macro ste push ax mov ax , 1 cmp ax , 1 pop ax endm ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- macro clz push ax mov ax , 0 cmp ax , 1 pop ax endm ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- macro stz push ax mov ax , 1 cmp ax , 1 pop ax endm ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- macro puts str local disp local s jmp disp s db str, '$' disp: mov ah , 09 mov dx , offset s int 21h endm ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- macro newLine push ax push dx mov ah , DOS_DISPLAY_OUTPUT mov dl , 0Dh int 21h mov dl , 0Ah int 21h pop dx pop ax endm ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- REM -- VARIOUS DATA STRUCTURES GOES HERE ;--)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)---)- struc mcb REM -- 'M' more to follow 'Z' zero to follow linkIndicator db ? segOfOwner dw ? paragraphLen dw ? db 3 dup(?) asciiName db 8 dup(?) ends COMMAND_LINE_LEN_OFFSET = 80h COMMAND_LINE_OFFSET = 81h ENVIRONMENT_SEGMENT = 2Ch FALSE = 0 TRUE = 1 NULL = 0 ; MICHAEL BUEN |