home *** CD-ROM | disk | FTP | other *** search
/ PC Open 18 / pcopen18_giallo.iso / Msdos / Keybit6 / SOURCE.ZIP / AMIS.MAC < prev    next >
Encoding:
Text File  |  1996-02-22  |  17.7 KB  |  676 lines

  1. .XLIST
  2. ;-----------------------------------------------------------------------
  3. ; Alternate Multiplex Interrupt Specification Library
  4. ; AMIS.MAC    Public Domain 1992 Ralf Brown
  5. ;        You may do with this software whatever you want, but
  6. ;        common courtesy dictates that you not remove my name
  7. ;        from it.
  8. ;
  9. ; Version 0.91.K6 (custom version by Pino Navato for KEYBIT Lite v6)
  10. ;-----------------------------------------------------------------------
  11.  
  12. AMIS_VERSION    =  350    ;(version 3.5 of the Alternate Multiplex Interrupt Spec)
  13. AMISLIB_VERSION =  091    ;(version 0.91 of this library)
  14.  
  15. ;-----------------------------------------------------------------------
  16. ;
  17. ; installation flags (see INSTALL_TSR below)
  18. ;
  19. BEST_FIT    =  1    ; use best-fit rather than first-fit
  20. UMB_ONLY    =  2    ; don't load into low memory, only into a UMB
  21. LOW_ONLY    =  4    ; don't use UMB even if high memory available
  22.             ; (note: can't set both UMB_ONLY and LOW_ONLY)
  23. USE_TOPMEM    =  8    ; use the top of low memory if no high memory
  24.             ; (this is not always the best place to load)
  25. NO_TOPMEM    =  0    ; do not use the top of low memory if no UMB (default)
  26. PATCH_RESIDENT    =  80h    ; patch resident code with actual memory block address
  27.  
  28. ;-----------------------------------------------------------------------
  29. ;
  30. ; Set up a shorthand for the segment containing all the resident code and
  31. ; data.
  32. ; Note: the alignment must be PARA for the code to be properly relocatable
  33. ; in small-code memory models.
  34. ;
  35. TSRcode@ MACRO
  36. TGROUP GROUP RESIDENT_CODE
  37. RESIDENT_CODE SEGMENT PUBLIC PARA 'TSRCODE'
  38.     ASSUME    DS:NOTHING,ES:NOTHING,SS:NOTHING
  39.     ASSUME    CS:TGROUP
  40.     ENDM
  41. TSRcodeEnd@ MACRO
  42. RESIDENT_CODE ENDS
  43.     ENDM
  44.  
  45. ;-----------------------------------------------------------------------
  46. ;
  47. ; Set up shorthands for the segments containing all the resident data,
  48. ; initialized and uninitialized.
  49. ;
  50. TSRdata@ MACRO
  51. RESIDENT_DATA SEGMENT PUBLIC BYTE 'TSRCODE'
  52.     ENDM
  53. TSRdataEnd@ MACRO
  54. RESIDENT_DATA ENDS
  55.     ENDM
  56.  
  57. TSRbss@ MACRO
  58. RESIDENT_BSS SEGMENT PUBLIC BYTE 'TSRCODE'
  59.     ENDM
  60. TSRbssEnd@ MACRO
  61. RESIDENT_BSS ENDS
  62.     ENDM
  63.  
  64. ;-----------------------------------------------------------------------
  65. ;
  66. ; dummy segment for determining the size of the resident code in the
  67. ; executable
  68. ;
  69. TSRlast@ MACRO
  70. RESIDENT_END SEGMENT PUBLIC BYTE 'TSRCODE'
  71.     ENDM
  72. TSRlastEnd@ MACRO
  73. RESIDENT_END ENDS
  74.     ENDM
  75.  
  76. ;-----------------------------------------------------------------------
  77. ;
  78. ; Set up a shorthand for declaring all three resident segments and a group
  79. ; TGROUP for those segments.
  80. ;
  81. TSRgroup@ MACRO
  82. TSRcode@
  83. TSRcodeEnd@
  84. TSRdata@
  85. TSRdataEnd@
  86. TSRbss@
  87. TSRbssEnd@
  88. TSRlast@
  89. TSRlastEnd@
  90. TGROUP GROUP RESIDENT_CODE,RESIDENT_DATA,RESIDENT_BSS,RESIDENT_END
  91.     ENDM
  92.  
  93. ;-----------------------------------------------------------------------
  94. ;
  95. ; Some of the code in AMIS.ASM uses conditional assembly to handle
  96. ; segment registers differently in Tiny model than in other models, so
  97. ; we need to ensure that __TINY__ is defined in tiny model.
  98. ;
  99. IFDEF @Model        ; simplified memory models being used?
  100.   IF @Model eq 1    ; tiny model
  101.      IFNDEF __TINY__
  102.        __TINY__ equ 1
  103.      ENDIF ;NDEF
  104.   ENDIF
  105.   IF (@Model eq 1) or (@Model eq 2) or (@Model eq 3) ; Tiny, Small, or Compact?
  106.      DIST equ NEAR
  107.   ELSE
  108.      DIST equ FAR
  109.   ENDIF
  110. ELSE ;DEF @Model    ; else assume TCC/BCC memory-model #defines
  111.    IFDEF __TINY__
  112.       DIST equ NEAR
  113.    ELSEIFDEF __SMALL__
  114.       DIST equ NEAR
  115.    ELSEIFDEF __COMPACT__
  116.       DIST equ NEAR
  117.    ELSE
  118.       DIST equ FAR
  119.    ENDIF
  120. ENDIF
  121.  
  122. IFNDEF __TINY__
  123.    TGROUP@ equ TGROUP
  124. ENDIF
  125.  
  126. ;-----------------------------------------------------------------------
  127. ;
  128. ; first half of startup code (invoke right after INCLUDE AMIS.MAC in main module)
  129. ;
  130. ; arguments:    major,minor,stksize
  131. ;        [opt] major,minor   major/minor version of min supported DOS ver
  132. ;        [opt] stksize        size of initial stack for non-Tiny models
  133. ;
  134. @Startup MACRO major,minor,stksize
  135.   ;----------------------------------
  136.   ; Declare our segments in the order
  137.   ; we want them in the executable.
  138.   ;
  139.   _INIT    SEGMENT PUBLIC PARA 'INIT'
  140.   _INIT    ENDS
  141.   TSRgroup@
  142.   _TEXT    SEGMENT PUBLIC PARA 'CODE' ; must be aligned PARA to work properly
  143.   _TEXT    ENDS
  144. IFNDEF __TINY__
  145.   _STACK SEGMENT STACK 'STACK'
  146.   IFNB <stksize>
  147.       db <stksize> dup (?)
  148.   ELSE
  149.     db 100h dup (?)
  150.   ENDIF
  151.   _STACK ENDS
  152. ENDIF ;ndef __TINY__
  153.  
  154.   ;----------------------------------
  155.   ; set up labels for start and end of
  156.   ; resident code
  157.   ;
  158.   TSRcode@
  159.   $AMIS$start_TSRcode label byte    ; find address of beginning of segment
  160.   TSRcodeEnd@
  161.  
  162.   TSRlast@
  163.   $AMIS$end_TSRcode label byte    ; marker for end of resident code in executable
  164.   TSRlastEnd@
  165.  
  166. IFDEF __TINY__
  167. _INIT SEGMENT 'INIT'
  168.     ASSUME    CS:_INIT,DS:_INIT,ES:_INIT,SS:_INIT
  169.     ORG    100h
  170. ELSE
  171. _TEXT SEGMENT 'CODE'
  172.     ASSUME    CS:_TEXT,DS:NOTHING,ES:NOTHING,SS:NOTHING
  173. ENDIF ;def __TINY__
  174.  
  175. INIT    proc far
  176. IFNB <major>
  177.   IFNB <minor>
  178.       CHECK_DOS_VER major,minor
  179.   ENDIF
  180. ENDIF
  181. IFNDEF __TINY__
  182.     mov    dx,TGROUP
  183.     mov    es,dx
  184.     ASSUME    ES:TGROUP
  185.     jmp    $AMIS$PROGRAM_START
  186. ELSE
  187.     mov    ax,offset _INIT:$AMIS$start_TSRcode
  188.     mov    cl,4
  189.     shr    ax,cl
  190.     mov    dx,es
  191.     add    dx,ax
  192.     mov    es,dx
  193.     ASSUME    ES:TGROUP
  194.     ;
  195.     ; compute normalized address of actual program entry point
  196.     ;
  197.     mov    dx,offset _INIT:$AMIS$PROGRAM_START
  198.     mov    ax,offset _TEXT:$AMIS$PROGRAM_START
  199.     sub    dx,ax
  200.     shr    dx,cl            ; CL still 4
  201.     mov    cx,cs
  202.     add    dx,cx
  203.     push    dx            ; simulate far jump to computed address
  204.     push    ax
  205.     ret
  206. ENDIF ;ndef __TINY__
  207.  
  208. INIT    endp
  209.  
  210.     ASSUME    DS:NOTHING,ES:NOTHING,SS:NOTHING
  211. IFDEF __TINY__
  212.  _INIT    ENDS
  213. ELSE
  214.  _TEXT    ENDS
  215. ENDIF ;def __TINY__
  216.  
  217.     ENDM
  218.  
  219. ;-----------------------------------------------------------------------
  220. ;
  221. ; additional startup code (invoke at start of main program)
  222. ;
  223. ; arguments: need_psp    non-blank to allocate __psp variable, blank if provided
  224. ;            by some other module (such as the C runtime library)
  225. ;
  226. @Startup2 MACRO need_psp
  227.  
  228. IFDEF __TINY__
  229.   TGROUP@    dw ?
  230. ENDIF ;__TINY__
  231. IFNB <need_psp>
  232.   public __psp
  233.   __psp        dw ?
  234. ENDIF ;need_psp
  235.  
  236. $AMIS$PROGRAM_START:
  237.     ASSUME    DS:NOTHING,ES:TGROUP
  238.     mov    __psp,ds
  239. IFDEF __TINY__
  240.     mov    TGROUP@,es
  241. ENDIF
  242.     ENDM
  243.  
  244. ;-----------------------------------------------------------------------
  245. ;
  246. ; DISPLAY_STRING    output a '$'-terminated string to standard output
  247. ; arguments:    string    the label of the string to be displayed
  248. ;        dataseg [opt] the segment of the string
  249. ;
  250. DISPLAY_STRING MACRO string,dataseg
  251. IFNB <dataseg>
  252.     push    ds
  253.     mov    ax,dataseg
  254.     mov    ds,ax
  255. ENDIF
  256.     mov    dx,offset string
  257.     mov    ah,9
  258.     int    21h
  259. IFNB <dataseg>
  260.     pop    ds
  261. ENDIF
  262.     ENDM
  263.  
  264. ;-----------------------------------------------------------------------
  265. ;
  266. ; CHECK_DOS_VER        ensure that the program is running under the proper
  267. ;            version of DOS, and terminate with an error message
  268. ;            specifying the minimum required version if not.
  269. ;
  270. CHECK_DOS_VER MACRO major,minor
  271.     LOCAL    bad_version_msg,version_OK
  272. IF major GE 5
  273.     mov    ax,3306h        ; get true DOS version
  274. ELSE
  275.     mov    ax,3000h
  276. ENDIF
  277.     int    21h
  278.     xchg    al,ah
  279.     cmp    ax,256*major + minor
  280.     jae    version_OK
  281. IFNDEF __TINY__
  282.     push    cs
  283.     pop    ds
  284. ENDIF
  285.     DISPLAY_STRING bad_version_msg
  286.     int    20h            ; terminate program
  287.  
  288. bad_version_msg label byte
  289.     db    "This program requires DOS "
  290.     db    major+'0',".",(minor/10)+'0',(minor mod 10)+'0'
  291.     db    " or higher.",13,10,"$"
  292.  
  293. version_OK:
  294.     ENDM
  295.  
  296. ;-----------------------------------------------------------------------
  297. ;
  298. ; IF_INSTALLED    conditionally branch somewhere if TSR is already installed
  299. ; arguments:
  300. ;    dest    label to branch to if already installed
  301. ; at exit:
  302. ;    CF set if installed
  303. ;        AH = multiplex number
  304. ;        CX = version number
  305. ;    CF clear if not installed
  306. ;
  307. IF_INSTALLED MACRO dest
  308.     LOCAL    not_installed
  309.     mov    dx,TGROUP@
  310.     mov    ax,offset RESIDENT_CODE:ALTMPX_SIGNATURE
  311.     extrn check_if_installed:DIST
  312.     call    check_if_installed
  313.     jnc    not_installed
  314.     jmp    dest
  315. not_installed:
  316.     ENDM
  317.  
  318. ;-----------------------------------------------------------------------
  319. ;
  320. ; *** NOTA: Questa macro è stata modificata.
  321. ; ***        Ora accetta anche il parametro tsr_code_len che permette di
  322. ; ***        rendere opzionale l'installazione di una parte del codice.
  323. ;
  324. ; INSTALL_TSR
  325. ; arguments:
  326. ;    tsr_code_len [opt] length of resident code in bytes
  327. ;    extra    [opt] number of additional paragraphs needed in resident part
  328. ;    fit    [opt] FIRST (default) or BEST fit allocation
  329. ;    high    [opt] HIGHONLY to only use UMBs, TOPMEM to allocate block at
  330. ;            high end of conventional memory if no UMBs available,
  331. ;            LOWONLY to ignore UMBs, and TOPLOW to allocate at high
  332. ;            end of conventional memory whether or not UMBs are
  333. ;            available
  334. ;    init    [opt] function to call after installing TSR but before exiting
  335. ;    if_inst [opt] label to branch to if already installed
  336. ;    on_err    [opt] label to branch to if unable to install
  337. ;    more_flags [opt] label of byte containing additional flags to OR into
  338. ;           flags setup by <fit> and <high>
  339. ;
  340. ; if 'init' is specified, the indicated function will be called with
  341. ;    AX = segment at which TSR was loaded
  342. ; if 'if_inst' is specified, the indicated function will be jumped at with
  343. ;    AH = multiplex number
  344. ;    CX = version number
  345. ;
  346. INSTALL_TSR MACRO tsr_code_len,extra,fit,high,init,if_inst,on_err,more_flags
  347.     LOCAL not_installed,install_failed,iflags,install_error_msg
  348.     mov    bx,TGROUP@
  349.     push    bx            ; remember location of resident code
  350.     mov    dx,bx
  351.     mov    ax,offset RESIDENT_CODE:ALTMPX_SIGNATURE
  352.     extrn    check_if_installed:DIST
  353.     call    check_if_installed
  354.     pop    bx            ; retrieve location of resident code
  355.     jnc    not_installed
  356. install_failure:
  357. IFNB <if_inst>
  358.     jmp    if_inst
  359. ELSE
  360.     jmp short install_failed
  361. ENDIF
  362. not_installed:
  363.     cmp    al,1
  364.     je    install_failure
  365. IFNB <tsr_code_len>
  366.     mov    dx,tsr_code_len
  367.     add    dx,15
  368. ELSE
  369.     mov    dx,offset TGROUP:$AMIS$end_TSRcode+15
  370. ENDIF
  371.     mov    cl,4            ; convert bytes to paragraphs
  372.     shr    dx,cl
  373.     mov    cx,dx
  374. IFNB <extra>
  375.     mov    dx,extra
  376. ELSE
  377.     xor    dx,dx            ; no extra memory required
  378. ENDIF
  379.     iflags = 0
  380. IFDIFI <fit>,<FIRST>
  381.     iflags = iflags OR BEST_FIT
  382. ENDIF
  383. IFIDNI <high>,<HIGHONLY>
  384.     iflags = iflags OR UMB_ONLY
  385. ENDIF
  386. IFIDNI <high>,<LOWONLY>
  387.     iflags = iflags OR LOW_ONLY
  388. ENDIF
  389. IFIDNI <high>,<TOPMEM>
  390.     iflags = iflags OR USE_TOPMEM
  391. ENDIF
  392. IFIDNI <high>,<TOPLOW>
  393.     iflags = iflags OR USE_TOPMEM OR LOW_ONLY
  394. ENDIF
  395. IFDEF ALTMPX$PSP
  396.     iflags = iflags OR PATCH_RESIDENT
  397. ENDIF
  398.     mov    al,iflags
  399. IFNB <more_flags>
  400.     or    al,more_flags
  401. ENDIF
  402.     extrn $install_TSR:DIST
  403.     call    $install_TSR
  404.     ; if success, returns CF clear, AX=segment at which TSR was installed
  405.     jc    install_failed
  406. IFNB <&init>
  407.     call    init
  408. ENDIF
  409.     extrn $go_TSR:DIST
  410.     call    $go_TSR            ; never returns
  411.  
  412. install_failed:
  413. IFNB <on_err>
  414.     jmp    on_err
  415. ELSE
  416.     push    cs
  417.     pop    ds
  418.     DISPLAY_STRING cs:install_error_msg
  419.     mov    ax,4CFFh        ; exit with ERRORLEVEL 255
  420.     int    21h
  421.  
  422. install_error_msg db "Unable to go resident.",13,10,"$"
  423. ENDIF
  424.     ENDM
  425.  
  426.  
  427. ;-----------------------------------------------------------------------
  428. ;
  429. ; UNINSTALL    remove the TSR from memory
  430. ; arguments:
  431. ;    on_err    [opt] label to branch to if unable to remove from memory
  432. ;
  433. ; If 'on_err' is omitted, check CF after this macro to determine whether
  434. ; the removal was successful (CF clear if successful, set on error)
  435. ;
  436. UNINSTALL MACRO on_err
  437.     LOCAL    success
  438.     mov    dx,TGROUP@
  439.     mov    ax,offset RESIDENT_CODE:ALTMPX_SIGNATURE
  440.     extrn $uninstall_TSR:DIST
  441.     call    $uninstall_TSR
  442. IFNB <on_err>
  443.     jnc    success
  444.     jmp    on_err
  445. ENDIF
  446. success:
  447.     ENDM
  448.  
  449. ;-----------------------------------------------------------------------
  450. ;
  451. ;             I M P O R T A N T ! ! !
  452. ; Note: in order to work properly with the code in AMIS.ASM, all of
  453. ; the following macros must be used inside TSRcode@
  454. ;
  455.  
  456. ;-----------------------------------------------------------------------
  457. ;
  458. ; ISP_HEADER    set up Interrupt Sharing Protocol header for an interrupt
  459. ; arguments:
  460. ;    intr    interrupt number
  461. ;    reset    [opt] name of routine to perform hardware reset
  462. ;    eoi    [opt] if nonzero, this is the primary handler for a hardware int
  463. ; exported labels: (for example "ISP_HEADER 00h,reset_func,0")
  464. ;    INT00h_handler (public), ORIG_INT00h (public), HWRESET_00h,
  465. ;    EOI_FLAG_00h
  466. ;    [in addition, hw_reset_00h would be present for ISP_HEADER 00h,,0]
  467. ;
  468. ISP_HEADER MACRO intr,reset,eoi
  469. public INT&intr&_handler,ORIG_INT&intr
  470.     ASSUME    DS:NOTHING,ES:NOTHING,SS:NOTHING
  471. IFB <reset>
  472. hw_reset_&intr:
  473.     db    0CBh            ; RETF
  474. ENDIF ;reset
  475.  
  476. INT&intr&_handler:
  477.     db    0EBh,10h        ; short JMP to skip the header
  478. ORIG_INT&intr dd ?            ; previous handler in chain
  479.     dw   424Bh            ; ISP signature
  480. EOI_FLAG_&intr label byte
  481. IFB <eoi>
  482.     db   0                ; software int or secondary hardware int
  483. ELSE
  484. IF eoi eq 0
  485.     db   0                ; software int or secondary hardware int
  486. ELSE
  487.     db   80h            ; primary hardware int handler
  488. ENDIF ;eoi eq 0
  489. ENDIF ;B eoi
  490. IFB <reset>
  491. HWRESET_&intr: jmp short hw_reset_&intr
  492. ELSE
  493. HWRESET_&intr: jmp short reset
  494. ENDIF ;B reset
  495.     db   7 dup (0)
  496.     ENDM
  497.  
  498. ;-----------------------------------------------------------------------
  499. ;
  500. ; HOOKED_INTS        declare the interrupts this TSR hooks
  501. ; arguments:        up to 32 interrupt numbers
  502. ; exported labels:    $AMIS$HOOKED_INT_LIST (public)
  503. ;
  504. HOOKED_INTS MACRO a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,aa,ab,ac,ad,ae,af,over
  505. public $AMIS$HOOKED_INT_LIST
  506. $AMIS$HOOKED_INT_LIST label byte
  507. IFNB <over>
  508.     %out Too many interrupts hooked!
  509.     .err
  510. ENDIF ;NB over
  511.     IRP    intrpt,<a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,aa,ab,ac,ad,ae,af>
  512.         IFNB <intrpt>
  513.         IF intrpt ne 2Dh   ; ignore INT 2Dh if in the list
  514.             DB 0&&intrpt
  515.             DW INT&&intrpt&&_handler
  516.         ENDIF ;DIFI
  517.         ENDIF ;NB
  518.     ENDM
  519.     ;
  520.     ; the list terminator is INT 2Dh, since we know that one will always
  521.     ; be hooked; thus, all interrupts from 00h to FFh may be hooked
  522.     ;
  523.             DB 2Dh
  524.             DW INT2Dh_handler
  525.     ENDM
  526.  
  527. ;-----------------------------------------------------------------------
  528. ;
  529. ; *** NOTA: Questa macro è stata modificata.
  530. ; ***        Ora include anche l'API di KEYBIT Lite (mettendola qui si
  531. ; ***        risparmia qualche byte).
  532. ;
  533. ; ALTMPX    define the alternate multiplex interrupt handler for the program
  534. ; arguments:
  535. ;    manuf       one- to eight-character manufacturer's name
  536. ;    prodname   one- to eight-character product name
  537. ;    version       four-digit hex version number (hi byte = major, lo = minor)
  538. ;    descrip       [opt] string (max 63 char) describing the product
  539. ;    remover       [opt] name of function to call to remove TSR from memory
  540. ;    psp       [opt] if nonblank, set up patch word for memblk segment to
  541. ;             be returned if <remover> omitted; returns CS if both
  542. ;             <remover> and <psp> blank
  543. ; limitations on routines:
  544. ;    all: must be located inside TSRcode@
  545. ;    <remover>
  546. ;        input:    DX:BX = return address if uninstall successful
  547. ;        return: AL = status
  548. ;                01h unable to remove from memory
  549. ;                02h can't remove now, will do so when able
  550. ;                03h safe to remove, but no resident uninstaller
  551. ;                    (TSR still enabled)
  552. ;                    BX = segment of memory block
  553. ;                04h safe to remove, but no resident uninstaller
  554. ;                    (TSR now disabled)
  555. ;                    BX = segment of memory block
  556. ;                05h not safe to remove now, try again later
  557. ;                FFh successful (DX:BX were ignored)
  558. ;        return at DX:BX with AX destroyed if successful and <remover>
  559. ;            honors specific return address
  560. ;        if <remover> omitted, ALTMPX returns AL=03h
  561. ; exported labels:
  562. ;    INT2Dh_handler (public), ORIG_INT2Dh (public), HWRESET_2Dh,
  563. ;    EOI_FLAG_2Dh, hw_reset_2Dh, $AMIS$MULTIPLEX_NUMBER (public),
  564. ;    ALTMPX_SIGNATURE (public), ALTMPX$PSP [patch word]
  565. ;
  566. ALTMPX MACRO manuf,prodname,version,descrip,remover,psp
  567.     LOCAL our_int_2Dh,int2D_func_00,int2D_func_02
  568.     LOCAL int2D_func_04,int2D_func_10
  569.     LOCAL func_not_supported,return_segDX
  570.     PUBLIC $AMIS$MULTIPLEX_NUMBER,ALTMPX_SIGNATURE,ALTMPX$PSP
  571.  
  572. ALTMPX_SIGNATURE label byte
  573.     db    manuf
  574. IF ($-ALTMPX_SIGNATURE) gt 8
  575.     ERR "Manufacturer name >8 chars"
  576. ELSEIF ($-ALTMPX_SIGNATURE) lt 8
  577.     db    (ALTMPX_SIGNATURE+8-$) dup (' ')
  578. ENDIF
  579.     db    prodname
  580. IF ($-ALTMPX_SIGNATURE) gt 16
  581.     ERR "Product name >8 chars"
  582. ELSEIF ($-ALTMPX_SIGNATURE) lt 16
  583.     db    (ALTMPX_SIGNATURE+16-$) dup (' ')
  584. ENDIF
  585. IFNB <descrip>
  586.     db    descrip
  587. ENDIF
  588.     db    0
  589. IF ($-ALTMPX_SIGNATURE) gt 80
  590.     ERR "Description >63 chars"
  591. ENDIF
  592.  
  593. ; save an additional byte by overlaying the null hardware reset handler over
  594. ; other code, if possible
  595. IFNB <remover>
  596. hw_reset_2Dh:                ; <remover> not blank
  597.     db    0CBh            ; RETF
  598. IFNDEF ALTMPX$PSP
  599. ALTMPX$PSP equ word ptr ($+12)        ; point harmlessly into the ISP header
  600. ENDIF
  601. ELSE
  602.    IFB <psp>
  603.       ALTMPX$PSP equ word ptr ($+12)    ; point harmlessly into the ISP header
  604.    ENDIF
  605. ENDIF
  606. IFNB <psp>
  607.    IFB <remover>
  608. hw_reset_2Dh:                ; <remover> blank but <psp> not
  609.     db    0CBh            ; RETF
  610.    ENDIF
  611. ENDIF
  612.                     ; if both <remover> and <psp> blank,
  613.                     ;   hw_reset_2Dh is defined below
  614.                     ; if <remover> is blank and <psp> not,
  615.                     ;   ALTMPX$PSP is defined below
  616.  
  617.     ISP_HEADER 2Dh,hw_reset_2Dh
  618.     cmp    ah,0            ; will be patched with multiplex number
  619. $AMIS$MULTIPLEX_NUMBER equ byte ptr ($-1)
  620.     je    our_int_2Dh
  621.     jmp    ORIG_INT2Dh
  622. our_int_2Dh:
  623.     sti                ; OK to interrupt from now on
  624.     cmp    al,0
  625.     je    int2D_func_00
  626.     cmp    al,2
  627.     je    int2D_func_02
  628.     cmp    al,4
  629.     je    int2D_func_04
  630.     cmp    al,10h
  631.     je    int2D_func_10
  632. func_not_supported:
  633.     mov    al,0
  634.     iret
  635.  
  636. int2D_func_00:
  637.     mov    al,0FFh
  638.     mov    cx,version
  639.     mov    di,offset ALTMPX_SIGNATURE
  640. return_segDX:
  641.     mov    dx,cs
  642.     iret
  643.  
  644. int2D_func_02:
  645. IFNB <remover>
  646.     call    remover
  647. ELSE
  648. ;    mov    al,3            ; safe to remove, no resident uninstaller
  649.     inc    ax            ; AL was 02h, now 03h
  650. IFNB <psp>
  651.     mov    bx,0            ; will be patched at installation time
  652. ALTMPX$PSP equ word ptr ($-2)
  653. ELSE
  654.     mov    bx,cs
  655. hw_reset_2Dh equ near ptr ($-1) ; prev instruction happens to expand to 8Ch CBh
  656. ENDIF ;psp
  657. ENDIF ;remover
  658.     iret
  659.  
  660. int2D_func_04:
  661.     ;mov    al,4 ;not needed since AL=04h anyway
  662.     mov    dx,cs
  663.     mov    bx,offset cs:$AMIS$HOOKED_INT_LIST
  664.     iret
  665.  
  666. ;KEYBIT Lite API
  667. int2D_func_10:
  668.     mov    bx,offset TGROUP:flags
  669.     jmp    return_segDX
  670.  
  671.     ENDM
  672.  
  673. ;-----------------------------------------------------------------------
  674.  
  675. .LIST
  676.