home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / D86BIOS4.ZIP / BIOS.8 next >
Text File  |  1989-04-30  |  22KB  |  462 lines

  1. ;---------------
  2. ;   BIOS module for the D86 debugger
  3. ;---------------
  4.  
  5. ; Copyright 1987,88 Eric Isaacson.  All rights reserved.  Permission to
  6. ; copy and use this module is granted ONLY for machines registered for both
  7. ; the A86 assembler and the D86 debugger.
  8.  
  9. ; Current support: IBM-PC, Wang PC, TI-PC, Sanyo 555, Tandy 2000,
  10. ;     and Sirius/Victor 9000, DEC RAINBOW, and Zenith Z-100.
  11.  
  12. ; This module defines the BIOS interface for my D86 debugger.  I am publishing
  13. ; it to assist those who wish to assist me in implementing D86 on machines not
  14. ; BIOS-compatible with the IBM-PC.  To support a non-standard BIOS, we must
  15. ; provide new keyboard codes, new action routines, and several other data
  16. ; quantities.  This module provides a routine BIOS_INIT that sets everything
  17. ; up according to the machine being used.  BIOS_INIT must do four things:
  18. ;
  19. ; 1. The routine must figure out what machine we are running on.  The best
  20. ;    way to do this is to find a machine-specific identifier in a fixed
  21. ;    area of memory (ROM or the BIOS).  If you can locate such an identifier,
  22. ;    you can simply create an entry in the BIOS_SIGS structure below.
  23. ;
  24. ; 2. The routine must point SI to a special data structure (which I'll
  25. ;    describe shortly), then call the routine NEW_KEYS, to propagate the
  26. ;    items in the structure to the necessary places throughout the debugger.
  27. ;
  28. ; 3. The routine must perform any initializations necessary for this BIOS.
  29. ;    For example, WANG_CONFIG locates and stores the port number for hardware
  30. ;    that enables video access on the Wang.
  31. ;
  32. ; 4. The routine must decide if the debugger is running on the same screen as
  33. ;    the user program.  If it is, it must move the user's cursor to the lower
  34. ;    left corner of the screen.
  35. ;
  36. ; The structure fed to NEW_KEYS contains all the data necessary for ongoing
  37. ; debugger execution under the new BIOS.  See the structure WANG_KEYS for a
  38. ; prototype.  The structure consists of the following:
  39. ;
  40. ;  * a byte giving the keyboard code for the debugger's HELP key.
  41. ;
  42. ;  * a byte declaring the difference between your BIOS's key codes for
  43. ;    function keys, and the IBM BIOS's key codes.  Your BIOS_KEY must return
  44. ;    consecutive values for the function keys F1 through F10.  You should
  45. ;    declare this byte to be X - FUNC, where X is one less than the code
  46. ;    returned by the F1 key.  For example, since the Wang F1 key returns hex
  47. ;    080, the byte is declared 07F - FUNC.
  48.  
  49. ;  * a number of bytes giving code values for all the other control keys
  50. ;    used by the debugger.  This list will be expanding with new versions;
  51. ;    see WANG_KEYS for the current version's list.  You should precede the list
  52. ;    with the L1 label, and follow it with the declaration N_CONTROL_KEYS EQU
  53. ;    $-L1, exactly as shown.  Don't change the name N_CONTROL_KEYS; the
  54. ;    redeclaration of the same name insures that you've gotten the right number
  55. ;    of codes into the table.
  56. ;
  57. ;  * a word pointing to a message string with the name of the help-key.  If your
  58. ;    keyboard has a key labelled HELP, use the name HELP_HELP as in WANG_KEYS.
  59. ;    If there is another key nonexistent on the IBM-PC (e.g. F11), then put
  60. ;    a new name (e.g. F11_HELP) following DW; I'll supply the definition for
  61. ;    the new name.  If there is no extra key and no HELP key, use Alt-F10 as
  62. ;    on the IBM-PC, and declare DW ALTF10_HELP here.
  63. ;
  64. ;  * the label L2: to be used to verify the number of following bytes.
  65. ;
  66. ;  * pointers to your BIOS's versions of the procedures VID_COPY, VID_ATTR,
  67. ;    VID_FIX, BIOS_BELL, and BIOS_KEY, described shortly. Substitute the name
  68. ;    of your machine for VID and BIOS in the generic names; e.g. the WANG_KEYS
  69. ;    structure has WANG_COPY, WANG_ATTR, WANG_BELL, and WANG_KEY.
  70. ;
  71. ;  * a word giving the segment register value for video memory on your machine.
  72. ;    The debugger will supply this value in the ES register when it calls
  73. ;    VID_COPY and VID_ATTR.  That is all the debugger does with it; so this
  74. ;    value can really be anything that the BIOS's versions of VID_COPY and
  75. ;    VID_ATTR want.
  76. ;
  77. ;  * a byte giving the attribute value for normal video.  This attribute will
  78. ;    be in effect for the entire debugger screen, except for the location of
  79. ;    the debugger's cursor.
  80. ;
  81. ;  * a byte giving the attribute value for reverse video.  This attribute will
  82. ;    be used to mark the debugger cursor.
  83. ;
  84. ;  * the declaration N_BIOS_CALLS EQU ($-L2)/2  Again, don't change the name;
  85. ;    the redeclaration of the name insures you didn't leave anything out.
  86. ;
  87. ; This completes the description of the structure fed to NEW_KEYS.  After
  88. ; BIOS_INIT is called, the debugger will keep calling 7 action routines to
  89. ; perform its interactive I/O.    The routines must perform actions as
  90. ; follows:
  91.  
  92. ; VID_COPY copies CL bytes of characters from DS:SI to the video memory whose
  93. ;   location is given by ES:DI.  The characters should have the attribute
  94. ;   NORM_ATTR, which the caller will place into AH for VID_COPY's convenience.
  95. ;   VID_COPY must place the character byte and the attribute byte into each
  96. ;   output video word.    VID_COPY must return with BL preserved, the high byte
  97. ;   of SI preserved (it will be if you leave SI pointing beyond the bytes
  98. ;   copied), and DI advanced beyond the video memory just output.  The caller
  99. ;   assumes that video memory can be found at the value of VIDEO_SEG set by
  100. ;   BIOS_INIT, starting at offset 0, and proceeding consecutively, one 16-bit
  101. ;   memory word for every character.  The caller will set CH=0 for its first
  102. ;   call, so that VID_COPY can use CX as the count; but if it does, it must
  103. ;   return CH=0 for subsequent calls.
  104.  
  105. ; VID_ATTR places the attribute byte AL into the video word whose location is
  106. ;   given by ES:DI.  The character byte of the video word must not be disturbed.
  107.  
  108. ; VID_FIX restores a video screen that might have been clobbered by programs
  109. ;   external to the debugger.  If VID_COPY copies all characters to video memory
  110. ;   every time, then VID_FIX should RET without doing anything.  If, however,
  111. ;   VID_COPY tries to keep track of which characters are already on the screen,
  112. ;   and suppress video output for those that are, then VID_FIX should disable
  113. ;   the suppression feature, call the debugger's routine REFRESH to update the
  114. ;   whole screen, then re-enable the suppression feature.
  115.  
  116. ; BIOS_BELL rings the bell.  NOTE that it is not acceptible for BIOS_BELL to
  117. ;   use the MS-DOS write routine to send a bell control-code to standard output;
  118. ;   if it did, then the debugger couldn't debug programs that have redirected
  119. ;   their standard output-- the bell code would go to the user program's output
  120. ;   file, and not be translated into a beep.
  121.  
  122. ; BIOS_KEY returns in AL a code for a single keystroke.  The code should be
  123. ;   compatible with the values placed into the debugger's function tables by
  124. ;   BIOS_INIT.    If there is no keystroke available, BIOS_KEY should wait until
  125. ;   there is one.  BIOS_KEY should return on each individual key, and not wait
  126. ;   for any line-editing to take place.
  127.  
  128. ; BIOS_SAVE saves whatever there is about the user program's BIOS state that
  129. ;   might be clobbered by the debugger.  Currently, the only such thing is
  130. ;   the user's cursor position on the Sanyo.  So on all machines but the Sanyo,
  131. ;   this is a "do-nothing" routine.
  132.  
  133. ; BIOS_RESTORE restores the BIOS state saved by BIOS_SAVE.  Again, this routine
  134. ;   does nothing except on the Sanyo, on which it restores the user cursor
  135. ;   position, clobbered because D86 must use BIOS calls to write to the Sanyo
  136. ;   screen.
  137.  
  138.  
  139. BIOS_SIGNATURE  MACRO
  140.   DB #1       ; case number for the machine being sought
  141.   DB #NL-2    ; number of far pointers to look at
  142.   DB >M2      ; length byte for the following string
  143. M1:
  144.   DB #2       ; BIOS signature string we are looking for
  145. M2 EQU $-M1   ; we calculate the forward-reference length byte here
  146. #RX3L         ; loop for remaining macro operands
  147.   DD #X       ; far pointers to each place where the string might be found
  148. #ER
  149. #EM
  150.  
  151. BIOS_SIGS:
  152.   BIOS_SIGNATURE  6,'Texas I',0F400:0A022
  153.   BIOS_SIGNATURE  7,'Tandy'  ,0FC00:002F ,0FC00:0032
  154.   BIOS_SIGNATURE 10,'Rainbow',0FE00:0166 ,0FC00:03F2, 0FE00:0163
  155.   BIOS_SIGNATURE 12, 0E9     ,040:0
  156.   DB 0FF         ; terminator byte
  157.  
  158. L0:                     ; jump table for each type of machine
  159.   DW IBM_MONO_CONFIG    ; 1
  160.   DW IBM_CGA_CONFIG     ; 2
  161.   DW IBM_EGA_CONFIG     ; 3
  162.   DW IBM_CONFIG         ; 4
  163.   DW WANG_CONFIG        ; 5
  164.   DW TIPC_CONFIG        ; 6
  165.   DW TANDY_CONFIG       ; 7
  166.   DW SANYO_CONFIG       ; 8
  167.   DW SIRIUS_CONFIG      ; 9
  168.   DW DEC_CONFIG         ; 10
  169.   dw ibm_mono_config
  170. ;  DW HP_CONFIG          ; 11
  171.   DW Z100_CONFIG        ; 12
  172. L6 EQU ($-L0)/2
  173.  
  174. L2:            ; machine type AL is not 1
  175.   CMP AL,0FF        ; is it 0FF?
  176.   JNZ >L7        ; jump if not -- we are on an IBM-PC
  177.   MOV ES,AX,0FFFF   ; it was-- address the end of ROM
  178.   ES CMP AX,[6]     ; are there FFFF's beyond the boot-JMP?
  179.   MOV AL,8          ; load Sanyo index, in case there were
  180.   JE >L1            ; jump if there were-- it is a Sanyo
  181. L7:                 ; all non-IBM tests fail: let's assume IBM compatibility
  182.   MOV ES,CS         ; point ES to CS, where IBM_CONFIG wants it
  183.   MOV DH,0          ; the case number is zero-- no EGA vs. CGA decided yet
  184.   JMP IBM_CONFIG    ; jump to IBM-compatible configuration code
  185.  
  186. BIOS_INIT:
  187.   MOV DS,CS         ; insure that DS points to our code segment
  188.   MOV AL,SWITCH'B'  ; fetch the BIOS switch setting if there was one
  189.   DEC AX            ; eliminate 0 setting from consideration
  190.   CMP AL,L6         ; was there an explicit BIOS switch setting?
  191.   JB >L5            ; jump if there was, to the matching case
  192.   MOV SI,BIOS_SIGS  ; point to the BIOS-signatures data structure
  193.   LODSW             ; fetch the first case number and far-pointer-count
  194. L3:                 ; loop here for each subsequent machine's record
  195.   XCHG DX,AX        ; swap the case number to DL, pointers count to DH
  196.   LODSB             ; fetch the length byte
  197.   CBW               ; extend the length AL to AX
  198.   XCHG CX,AX        ; swap the length into CX
  199.   MOV BX,SI         ; save the string pointer in BX
  200.   ADD SI,CX         ; advance SI beyond the string, to the far pointers
  201. L8:                 ; loop here for each far pointer
  202.   LODSW             ; fetch the offset of the pointer
  203.   XCHG DI,AX        ; swap the offset into DI
  204.   LODSW             ; fetch the segment of the pointer
  205.   MOV ES,AX         ; move the segment into ES
  206.   XCHG BX,SI        ; swap the string pointer into SI
  207.   PUSH CX,SI        ; save the count
  208.   REPE CMPSB        ; see if the string is at this far pointer
  209.   POP SI,CX         ; restore the count
  210.   XCHG SI,BX        ; swap string pointer to BX, template pointer to SI
  211.   MOV AL,DL         ; fetch the case number in case the string matched
  212.   JE >L1            ; jump if the string matched to act upon the case
  213.   DEC DH            ; count down far pointers
  214.   JNZ L8            ; loop if there is another far pointer
  215.   LODSW             ; fetch the next record's case number and pointers count
  216.   CMP AL,0FF        ; did we load the terminator byte instead?
  217.   JNE L3            ; loop if not, to process the next machine record
  218.   MOV AL,0          ; no string match: load the machine type, already plugged in
  219. MACHINE_TYPE EQU B[$-1]
  220.   CMP AL,1          ; is it a Wang?
  221.   JNE L2        ; jump if not
  222.   MOV AL,5          ; load index for Wang                    
  223. L1:                 ; we will jump to case number AL
  224.   DEC AX            ; decrement so the first case is 0 not 1
  225. L5:
  226.   CBW               ; extend the case number from AL into AX
  227.   MOV DH,AL         ; save the case number in DH
  228.   ADD AX,AX         ; double the case number, to address a word pointer
  229.   XCHG BX,AX        ; swap the index into BX, for addressing
  230.   MOV ES,CS         ; restore ES=CS, for the benefit of the case code
  231.   JMP L0[BX]        ; jump to the appropriate case for this machine
  232.  
  233.  
  234. ; IBM_CONFIG is the BIOS_INIT routine for the IBM-PC.  Since its NEW_KEY
  235. ;   values are the defaults, we do not need to call NEW_KEY.
  236.  
  237. IBM_MONO_CONFIG:
  238. IBM_CGA_CONFIG:
  239. IBM_EGA_CONFIG:
  240. IBM_CONFIG:
  241.   MOV AH,15          ; function number for GET_VIDEO_MODE
  242.   INT 16          ; call the BIOS to get the mode
  243.   CMP AL,7          ; are we in monochrome mode?
  244.   MOV AX,0B000          ; load monochrome map location in case yes
  245.   IF B MOV AH,0B8     ; if not then load color map location
  246.   MOV BL,0            ; initial BL set for non-screen-swapping
  247.   TEST B SWITCH'V',1  ; is the V flag set?
  248.   IF NZ MOV BL,8      ; if it is then we will swap screens
  249.   XOR AH,BL          ; switch interfaces if we saw a +V in invocation
  250.   MOV VIDEO_SEG,AX    ; store the location of physical video
  251.   TEST AH,8          ; are we on a CGA or EGA video board?
  252.   JZ >L1          ; skip if not
  253.   CMP DH,1            ; have we already selected which, via the B case?
  254.   JAE >L5             ; skip if we have
  255.   PUSH BX             ; we haven't selected CGA vs. EGA: save BX
  256.   MOV AH,012          ; BIOS function code for GET_EGA_STATUS
  257.   MOV BL,010          ; load an impossible status
  258.   INT 16              ; set BL to the EGA status
  259.   CMP BL,010          ; was there an EGA status?
  260.   POP BX              ; restore clobbered register
  261. L5:                   ; NE is set if we have an EGA
  262.   MOV AX,EGA_ATTRS    ; load EGA attributes in case we do have an EGA
  263.   JNE >L2             ; jump if we do have an EGA
  264.   MOV AX,CGA_ATTRS    ; not an EGA: load CGA attributes
  265.   TEST B SWITCH'F',1             ; is the FAST switch set?
  266.   JNZ >L2                        ; skip if it is
  267.   MOV VID_COPY,COLOR_COPY        ; CGA and no FAST switch: change copy routine
  268.   MOV BIOS_RESTORE,COLOR_RESTORE ; activate the screen-restore function
  269. L2:
  270.   MOV ATTR_BYTES,AX   ; set the attribute bytes to AL and AH
  271. L1:
  272.   TEST BL          ; are we the same screen as the user program?
  273.   JNZ RET          ; return if we are not-- no need to move cursor
  274. SET_IBM_LOW_LEFT:
  275.   MOV BH,0          ; page number is zero
  276.   MOV DX,24 BY 0      ; we will move the cursor to row 24, column 0
  277. SET_IBM_CURSOR:
  278.   MOV AH,2          ; video BIOS function number for SET CURSOR POSITION
  279.   INT 16          ; call the BIOS to put user cursor in lower left corner
  280.   RET
  281.  
  282.  
  283. ; IBM_FIX performs a fixup of a trashed screen on an IBM machine.
  284.  
  285. ; COLOR_RESTORE checks to see if the debugger screen has been trashed.    If it
  286. ;   has, we restore the screen.
  287.  
  288. COLOR_RESTORE:
  289.   PUSH DS           ; save register across call
  290.   MOV DS,AX,0B800   ; point DS to the video screen
  291.   MOV DX,03DA        ; load the port number for reading the video status
  292. L2:            ; loop here to wait for vertical retrace
  293.   IN AL,DX        ; input the status
  294.   TEST AL,1        ; mask the retrace bit
  295.   JZ L2         ; loop if we are not in vertical retrace
  296.   CMP B[2400],'A'   ; check the "A" of the fixed "AX" display
  297.   POP DS            ; restore clobbered register
  298.   JE RET            ; return if the "A" has not rolled away or been trashed
  299. IBM_FIX:
  300.   CS PUSH VID_COPY         ; save the old VID_COPY value
  301.   CS MOV VID_COPY,MONO_COPY  ; coerce it to MONO_COPY, to blindly copy all
  302.   CALL REFRESH             ; refresh the screen; let the snow scatter!
  303.   CS POP VID_COPY         ; restore the old VID_COPY value
  304. IBM_SAVE:
  305. IBM_RESTORE:
  306.   RET
  307.  
  308.  
  309. ; MONO_COPY is the VID_COPY routine for an IBM monochrome video board.    The
  310. ;   characters occupy the lower byte of the DI-pointed words.  We can afford
  311. ;   to rewrite the entire screen on each refresh; so no special action needs to
  312. ;   be taken.  We do complicated looping to make the routine as fast as
  313. ;   possible.
  314.  
  315. MONO_COPY:
  316.   SHR CX,1        ; is the character count odd?
  317.   JC >L5        ; jump if yes, to special code
  318. L1:
  319.   SHR CX,1        ; is the character count a multiple of 4?
  320.   JC >L6        ; jump if not, to special code
  321. L2:            ; loop here to copy every 4 bytes
  322.   LODSB         ; load the character from the source
  323.   STOSW         ; output the character, with the standard attribute byte
  324.   LODSB         ; char # 2
  325.   STOSW
  326.   LODSB         ; char # 3
  327.   STOSW
  328.   LODSB         ; char # 4
  329.   STOSW
  330.   LOOP L2        ; loop for the next 4 characters
  331.   RET
  332.  
  333. L5:            ; the character count was odd
  334.   MOVSB         ; copy the odd character to the video buffer
  335.   INC DI        ; advance beyond the attribute byte
  336.   JCXZ RET        ; return if count is depleted
  337.   JMP L1        ; join even code
  338.  
  339. L6:            ; the character count is 2 mod 4
  340.   LODSB         ; load one character
  341.   STOSW         ; output it and the attribute-- count now 1 mod 4
  342.   LODSB         ; load second character
  343.   STOSW         ; output it-- count now 0 mod 4
  344.   JCXZ RET        ; return if count is depleted
  345.   JMP L2        ; join multiple-of-4 code
  346.  
  347.  
  348. ; COLOR_COPY is the VID_COPY routine for an IBM Color Graphics Adapter board.
  349. ;   The characters occupy the lower byte of the DI-pointed words. We must wait
  350. ;   for vertical retrace to output our data, to avoid annying "snow" on the
  351. ;   screen.  So we can't afford to output the entire buffer every time.  So we
  352. ;   maintain at [SI+81] a copy of what's already on the screen for [SI], and we
  353. ;   output only if the buffer is new.
  354.  
  355. COLOR_COPY:
  356.   PUSH BX        ; preserve BX across the call
  357.   MOV DX,03DA        ; load the port number for reading the video status
  358.   SKIP2         ; skip to the LODSB instruction
  359. L0:            ; loop here for every character that is already out there
  360.   INC DI        ; advance the output pointer beyond the character
  361. L1:            ; loop here after a non-matching character was stored
  362.   INC DI        ; advance beyond the following attribute byte
  363.   LODSB         ; fetch the next character
  364.   MOV BL,AL        ; save the character in BL
  365.   XCHG AL,[SI+79]   ; swap it with the already-out-there value
  366.   CMP AL,BL        ; is the character already out there?
  367.   LOOPE L0        ; loop if it is
  368.   JE >L4        ; jump if the characters are exhausted
  369. L2:            ; loop here to wait for vertical retrace
  370.   IN AL,DX        ; input the status
  371.   TEST AL,1        ; mask the retrace bit
  372.   JZ L2         ; loop if we are not in vertical retrace
  373.   MOV AL,BL        ; re-fetch the character to be output
  374.   STOSB         ; output the character
  375.   INC CX            ; undo the previous LOOPE's decrement of CX
  376.   LOOP L1        ; loop to check for another output character
  377.   INC DI        ; advance beyond the attribute byte of the last character
  378.   POP BX        ; restore clobbered register
  379.   RET
  380.  
  381. L4:            ; matching character was the last in the buffer
  382.   INC DI,2        ; advance beyond the output video word
  383.   POP BX        ; restore clobbered register
  384.   RET
  385.  
  386.  
  387. ; IBM_ATTR is the VID_ATTR routine for IBM-PC compatible computers.  The
  388. ;   attribute byte is the high byte of the DI-pointed video word.
  389.  
  390. IBM_ATTR:
  391.   INC DI        ; advance to the high, attribute byte
  392.   STOSB         ; output the attribute code AL to the byte
  393.   RET
  394.  
  395.  
  396. ; IBM_KEY is the BIOS_KEY routine for IBM_PC compatible computers.  We must
  397. ;   transform the two-byte code returned by the IBM BIOS into the single
  398. ;   code AL expected by the rest of the debugger.
  399.  
  400. IBM_KEY:
  401.   MOV AH,0        ; function code for GET KEY
  402.   INT 016        ; get the keystroke from the IBM BIOS
  403.   TEST AL        ; is the return AL nonzero?
  404.   JNZ RET        ; if yes then AL is our return code
  405.   MOV AL,AH        ; AL is zero, so AH determines the return code
  406.   ADD AL,080-16     ; shift the values into a range not seen directly in AL
  407.   RET
  408.  
  409.  
  410. ; IBM_BELL is the BIOS_BELL routine for IBM-PC compatible computers.  We
  411. ;   output the code 07 to the BIOS's console output routine.
  412.  
  413. IBM_BELL:
  414.   MOV AX,0E07       ; AH= console out function number; AL="BELL" control code
  415.   INT 010        ; output BELL to the console
  416.   RET
  417.  
  418.  
  419. ; NEW_KEYS reassigns the keyboard codes and the action routines for a non-
  420. ;   IBM-compatible BIOS.  We are called with CS:SI pointing to a table of
  421. ;   various new values, whose format is identical to the one given by
  422. ;   WANG_KEYS below.  The new values are plugged into the various tables
  423. ;   in the debugger, so that correct actions are taken for the non-compatible
  424. ;   machine.
  425.  
  426. NEW_KEYS:
  427.   LODSB         ; load the first byte of the table
  428.   MOV HELP_KEY,AL    ; first byte is the code for HELP_KEY
  429.   LODSB         ; load the second byte
  430.   ADD SWITCH_KEY,AL    ; byte 2 is (new-IBM) function-key-codes-difference
  431.   MOV DI,CTRL_JUMPS+2    ; point to the control-jumps table
  432.   MOV CX,N_FUNCS    ; load the number of function-keys in that table
  433. L1:            ; loop here to adjust each function-key code
  434.   ADD [DI],AL        ; add the code into the table entry
  435.   ADD DI,3        ; advance to the next table entry
  436.   LOOP L1        ; loop to adjust the next table entry
  437.   MOV CL,N_CONTROL_KEYS ; load the number of subsequent keys in the table
  438. L2:            ; loop here to plug in the new value for each key
  439.   MOVSB         ; copy the new key code to the function table
  440.   INC DI,2        ; advance output pointer to the next key code
  441.   LOOP L2        ; loop to plug in the next key code
  442.   LODSW         ; fetch the message-pointer to the name of HELP key
  443.   MOV HELP_MSG,AX    ; plug the pointer into the messages-string
  444.   MOV DI,BIOS_CALLS    ; point to the table of action routines
  445.   MOV CX,N_BIOS_CALLS    ; load the count of words in action-routine-table
  446.   REP MOVSW        ; copy the new pointers to the table
  447.   RET
  448.  
  449.  
  450. ; GET_MACHINE_TYPE sets the variables MACHINE_TYPE and SUBDIR_CHAR.
  451.  
  452. GET_MACHINE_TYPE:
  453.   MOV AH,030          ; MS-DOS function number for GET_DOS_VERSION
  454.   INT 33          ; we call this to get the machine number in BH
  455.   MOV MACHINE_TYPE,BH
  456.   DEC BH          ; are we on a Wang PC?
  457.   IF Z MOV SUBDIR_CHAR,'/'; if yes then switch the subdirectory character
  458.   RET
  459.  
  460.  
  461.  
  462.