home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / books / 68k_book / arp_src / prg_6jc.s < prev    next >
Text File  |  1985-11-20  |  13KB  |  279 lines

  1.  ; PROGRAM NAME: PRG_6JC.S
  2.  ;      VERSION: 1.001
  3.  
  4.  ; Assembly Instructions:
  5.  
  6.  ;    Assemble in Relocatable mode and save with a TOS suffix.
  7.  
  8.  ; Execution Instructions:
  9.  
  10.  ;    Execute from the desktop.  Some versions of the ST operating system
  11.  ; may require the printer to be turned on for proper operation of this
  12.  ; trap handler.
  13.  
  14.  ; Program Function:
  15.  
  16.  ;    This program establishes itself in memory as a trap #13 handler.  While
  17.  ; the program is resident, it intercepts all trap #13 calls.  If an
  18.  ; intercepted call's function is $3, and if the device involved is the video
  19.  ; screen, then the custom trap handler redirects the call to include output
  20.  ; to the printer as well as to the video screen.  In this manner all text
  21.  ; output to the screen, which is accomplished by BIOS function $3 calls
  22.  ; (GEMDOS calls $2 and $9 are included because these functions rely on
  23.  ; BIOS function $3.) is sent to both the printer and the video screen.
  24.  
  25.  ;    All redirected ASCII codes below $1B, except those for a carriage
  26.  ; return and a linefeed, are filtered out of the data sent to the printer.
  27.  ; This prevents certain ASCII codes that are suitable for the screen but
  28.  ; which are undesirable for the printer from reaching the printer.
  29.  
  30.  ; MAJOR NOTE:
  31.  
  32.  ;    If this program is to be used when a software print buffer is to be
  33.  ; simultaneously resident, then the software print buffer program MUST be
  34.  ; executed first.  That is, the software print buffer must already be
  35.  ; resident when this program is executed.
  36.  
  37.  ; Program Features:
  38.  
  39.  ; 1. Produces a hardcopy of program input and output that is sent to the  
  40.  ;    screen.  This program eliminates the necessity of providing statements
  41.  ;    in the program to accomplish that task.  It permits the printer listing
  42.  ;    of a program to be followed by a printer listing of user/program
  43.  ;    interaction.  Especially useful for providing the results of an 
  44.  ;    execution for homework problems, or for programs under development.
  45.  
  46.  ; 2. When compiling, compiler output to the screen will be sent to the
  47.  ;    printer.   Especially useful when debugging the error messages
  48.  ;    that appear on the screen.  The printer output lets you go back to
  49.  ;    the editor with the error list hardcopy.  
  50.  
  51.  ; 3. If the Show button is selected from the Show/Print/Cancel Desktop
  52.  ;    dialog box, when this program is resident, the data which appears
  53.  ;    on the video screen will also be sent to the printer.
  54.  
  55. program_start:                     ; Calculate program size and retain result.
  56.  lea        program_end(pc), a3    ; Fetch program end address.
  57.  movea.l    4(a7), a4              ; Fetch basepage address.
  58.  suba.l     a4, a3                 ; Program size is in A3.
  59.  lea        stack(pc), a7          ; Provide a user stack.
  60.  
  61. install_new_trap_13_vector:
  62.  pea       custom_trap_handler(pc) ; Push new trap handler address onto stack.
  63.  move.w    #$2D, -(sp)             ; Push trap 13 vector number.
  64.  move.w    #5, -(sp)               ; Function = setexec = BIOS $5.
  65.  trap      #13                     ; Current trap handler vector returned in D0.
  66.  addq.l    #8, sp
  67.  move.l    d0, preempted_handler_address
  68.  
  69. relinquish_processor_control:      ; Maintain memory residency.
  70.  move.w    #0, -(sp)               ; See page 121 of Internals book.
  71.  move.l    a3, -(sp)               ; Program size.
  72.  move.w    #$31, -(sp)             ; Function = ptermres = GEMDOS $31.
  73.  trap      #1
  74.  
  75.  ; NOTE:
  76.  
  77.  ;      The custom trap #13 handler is entered each time an application invokes
  78.  ; the trap #13 call.  If the call does not involve printing a character to the
  79.  ; screen, then a jump is performed to the preempted trap #13 handler.
  80.  
  81.  ;      If the call involves printing an escape sequence (An escape sequence
  82.  ; is a two-character code, the first of which is $1B or 27 decimal.  Escape
  83.  ; sequences provide screen control--see section 3.6 "The Atari VT52 Emulator",
  84.  ; pages 245-249 of the Internals book.) for screen control, then the sequence
  85.  ; is sent to the screen via the preempted trap #13 handler.
  86.  
  87.  ;      Otherwise, for each trap #13 call that is also a bconout invocation
  88.  ; with device code #2, the custom_trap_13 routine is entered three times.
  89.  ; The first time that the handler is entered, a variable is initialized, then,
  90.  ; when it is entered subsequently, a jump, over the initialization sequence,
  91.  ; to the preempted trap handler is performed.  The custom trap handler is
  92.  ; entered three times because the custom handler prints to both the screen
  93.  ; and the printer by invoking its own trap #13 calls; those calls are also
  94.  ; intercepted by the custom handler.
  95.  
  96.  ;      The custom handler must be able to handle trap #13 calls made while
  97.  ; the processor is in supervisor mode or user mode.
  98.  
  99. custom_trap_handler:
  100.  tst.b     initialization_flag
  101.  bne       skip_initialization
  102.  
  103.  ; Processing the stack data:
  104.  
  105.  ;      The location of the stack data that must be processed by this subroutine
  106.  ; depends on the state of the processor when the exception occurs.  If it was
  107.  ; in the supervisor state, then the data will be stacked, as indicated, at the
  108.  ; following relative locations:
  109.  
  110.  ;                    location - 11 = character to be printed, byte length
  111.  ; Old Top of Stack:  location - 10 = character to be printed, word length
  112.  ;                    location -  8 = device to which character is to sent
  113.  ;                    location -  6 = bios command to be executed
  114.  ;                    location -  4 = program counter low word
  115.  ;                    location -  2 = program counter high word
  116.  ; SSP ->             location -  0 = invoking program's status register content
  117.  
  118.  ; In each case, above, the location listed is the location of the most
  119.  ; significant byte of the data listed.  For example, relative location 10
  120.  ; contains the most significant byte of the word which specifies the
  121.  ; character to be printed.  Relative location 11 contains the least
  122.  ; significant byte of that word.  Actually, relative location 11 is
  123.  ; "the least significant byte" in computer vernacular, but, in fact, it
  124.  ; is that byte which contains the character code.  The byte at relative
  125.  ; location 10 contains only zeroes.
  126.  
  127.  ; The supervisor stack pointer (SSP) will be pointing to the new top of
  128.  ; stack; the data there will be the content of the most significant byte
  129.  ; of the status register, as it was when the exception occurred.  Now, as
  130.  ; it turns out, this byte will be the one of significance, as far as the
  131.  ; trap handler is concerned.
  132.  
  133.  ; If the processor was in the user state, then the data will be stacked,
  134.  ; as indicated, at the following relative locations:
  135.  
  136.  ; Old Top of Stack:  location -  4 = character to be printed
  137.  ;                    location -  2 = device to which character is to sent
  138.  ; USP ->             location -  0 = bios command to be executed
  139.  
  140.  ; The user stack pointer (USP) will be pointing to the top of the stack;
  141.  ; the data there will be the bios command to be executed.
  142.  
  143.  ; In order to process the stack data without regard to the processor state
  144.  ; before invocation, if the processor was in user mode, then the offsets used
  145.  ; to access the stack data with the USP as reference must be adjusted so that
  146.  ; they match the offsets used to access the stack data with the SSP as
  147.  ; reference.  Therefore, if the processor was in user mode when the trap #13
  148.  ; call was made, the value six is subtracted from the register that is used
  149.  ; to access the data.
  150.  
  151.  ; Then, common offset values, which will access the data correctly regardless
  152.  ; of the stack pointer used as reference can be used.
  153.  
  154.  ; When we begin, we know that the processor is now is supervisor mode,
  155.  ; however, we must determine its state at the time of the exception.  That
  156.  ; processor state must be checked by testing bit 13 of the status register.
  157.  ; We know that the SSP is now pointing to the content of the status register
  158.  ; as it was at exception time.  In fact, it is pointing to the most significant
  159.  ; byte of the status register word.
  160.  
  161.  ; There are two ways a bit can be tested with the 68000 BTST instruction.
  162.  
  163.  ; 1 - If the destination operand is a data register, then any of 32 bits
  164.  ;     may be tested.
  165.  
  166.  ; 2 - If the destination operand is not a data register, then only 1 of
  167.  ;     8 bits may be tested.
  168.  
  169.  ; In either case, the bit to be tested may be specified in a source data
  170.  ; register or as immediate data.
  171.  
  172.  ; Since the bit we want to test is on the stack, we can only test a bit
  173.  ; of a single memory byte.  The bit we must test (status register bit 13) is
  174.  ; bit 5 of the byte that is being addressed by the SSP.
  175.  
  176. get_processor_status:
  177.  movea.l   sp, a0               ; Fetch address of current top of stack.
  178.  btst      #5, (sp)             ; Supervisor mode test.
  179.  bne.s     supervisor_mode      ; No adjustment is necessary if the
  180.                                 ; processor was in supervisor mode.
  181.  move.l    usp, a0              ; Fetch address of current top of user stack.
  182.  subq.l    #6, a0               ; Adjust user data access address.
  183.  
  184. user_mode:
  185. supervisor_mode:                ; Processing for either mode follows.
  186.  cmpi.w    #3, 6(a0)            ; Writing a character to a device?
  187.  bne       not_bconout_call
  188.  cmpi.w    #2, 8(a0)            ; Is device the screen?
  189.  bne.s     not_screen
  190.  
  191.  ; NOTE:
  192.  
  193.  ;      The information desired, at this point, is the ON/OFF status of the
  194.  ; printer.  My printer, the star NX-10 provides this information on pin 13
  195.  ; of its parallel interface.  Unfortunately, the ST does not permit the
  196.  ; utilization of this data.  This is an example of hardware/hardware
  197.  ; incompatibility.
  198.  
  199.  ;      Because of this ST deficiency, the printers BUSY/NOT BUSY signal,
  200.  ; on pin 11 of the interface is forced into double duty.  In addition to its
  201.  ; normal function, this signal is used by the ST to determine if the printer
  202.  ; is ON or OFF.
  203.  
  204.  ;      We would like to be able to direct output to the printer, at will,
  205.  ; simply by manually turning the printer ON or OFF.
  206.  
  207.  ;      The problem here is this: because the response of the printer interface
  208.  ; is so much slower than the video screen interface, we can't use the bcostat
  209.  ; function (BIOS #8) to determine the printer status (before attempting to
  210.  ; write to the printer) in between outputs to the screen.  When we attempt to
  211.  ; do that, we find that pin 11 indicates that the printer is busy (same as OFF
  212.  ; signal) most of the time, even when the printer is turned on.  Thus, the
  213.  ; printer receives only some of the data sent to the screen.
  214.  
  215.  ;      Therefore, the trap handler must just assume that the printer is on.
  216.  ; This is no problem with some versions of the ST operating system.  If the
  217.  ; printer is off, nothing will be sent to it.  But some versions of the 
  218.  ; operating system will wait (forever, it seems) for someone to turn on the
  219.  ; printer.  If this happens, then you must turn on the printer while this
  220.  ; trap handler is resident.
  221.  
  222. esc_sequence_test:
  223.  tst.b     esc_sequence_flag
  224.  bne.s     reset_esc_sequence_flag
  225.  cmpi.w    #$1B, 10(a0)           
  226.  bne.s     not_esc_sequence
  227.  move.b    #1, esc_sequence_flag
  228.  bra.s     use_preempted_handler
  229. reset_esc_sequence_flag:
  230.  move.b    #0, esc_sequence_flag
  231. use_preempted_handler:
  232.  movea.l   preempted_handler_address(pc), a0
  233.  jmp       (a0)                 ; JUMP TO PREEMPTED TRAP #13 HANDLER.
  234.  
  235. not_esc_sequence:
  236.  move.b    #1, initialization_flag
  237.  move.w    10(a0), character    ; Store character for printer.
  238. write_character_to_screen:
  239.  move.w    10(a0), -(sp)        ; Push character onto stack.
  240.  move.w    #2, -(sp)            ; Device = screen.
  241.  move.w    #3, -(sp)            ; Function = bconout = BIOS $3.
  242.  trap      #13
  243.  addq.l    #6, sp
  244.  
  245. ascii_code_test:                ; Filter out undesirable codes.
  246.  move.w    character(pc), d0
  247.  cmpi.w    #$1B, d0
  248.  bgt.s     write_character_to_printer
  249.  cmpi.w    #$A, d0
  250.  beq.s     write_character_to_printer
  251.  cmpi.w    #$D, d0
  252.  bne.s     undesirable_ascii
  253. write_character_to_printer:
  254.  move.w    d0, -(sp)            ; Push character onto stack.
  255.  move.w    #0, -(sp)            ; Device = printer.
  256.  move.w    #3, -(sp)
  257.  trap      #13
  258.  addq.l    #6, sp
  259. undesirable_ascii:
  260.  move.b    #0, initialization_flag
  261.  rte
  262.  
  263. not_screen:
  264. not_bconout_call:
  265. skip_initialization:
  266.  movea.l   preempted_handler_address(pc), a0
  267.  jmp       (a0)                 ; JUMP TO PREEMPTED TRAP #13 HANDLER.
  268.  
  269.  bss
  270. character:                  ds.w    1
  271. preempted_handler_address:  ds.l    1
  272. esc_sequence_flag:          ds.b    1
  273. initialization_flag:        ds.b    1
  274.  align
  275.                             ds.l   48    ; Stack
  276. stack:                      ds.l    1    ; Address of stack.
  277. program_end:                ds.l    0
  278.  end
  279.