home *** CD-ROM | disk | FTP | other *** search
/ Carousel / CAROUSEL.cdr / mactosh / lang / io.asm < prev    next >
Assembly Source File  |  1984-12-21  |  15KB  |  478 lines

  1.  ; io.asm
  2.  ;  "Frame" program and I/O subroutines for general purpose assembly language
  3.  ;  programs.  To use this package:
  4.  ;  1. The first line in your file should be "include iodefs.txt".
  5.  ;  2. Your main program must begin with the label "main" and end with rts.
  6.  ;  3. Your .ld file should look like this, if your source file is called
  7.  ;     myprog.asm:
  8.  ;            !start
  9.  ;            io
  10.  ;            myprog
  11.  ;            $
  12.  ;  4. Pass arguments to subroutines in this package, and receive return
  13.  ;     values, in D0 or A0 as specified.  All registers are preserved (but
  14.  ;     subroutine rdchar does not preserve A0).
  15.  ;  5. Always call subroutine makewindow at the beginning of your main
  16.  ;     program, passing the address of your title string in A0.
  17.  
  18.  ; Include all necessary traps files
  19.  
  20.  include    m68klib.d
  21.  include systraps.txt
  22.  include quicktraps.txt
  23.  include tooltraps.txt
  24.  
  25.  WINDWIDTH equ 492    ; window dimensions
  26.  WINDHEIGHT equ 280    
  27.  X1    equ 8        ; upper-left and lower-right coordinates
  28.  Y1    equ 48        ; for bounds rectangle for window
  29.  X2    equ X1+WINDWIDTH
  30.  Y2    equ Y1+WINDHEIGHT
  31.  LMARG    equ 6          ; text margins - left,
  32.  RMARG    equ WINDWIDTH-10  ; right,
  33.  TMARG    equ 15          ; top,
  34.  BMARG    equ WINDHEIGHT-15 ; bottom
  35.  CR    equ 13        ; ascii carriage return
  36.  BS    equ 8        ; ascii backspace
  37.  DASH    equ 45        ; ascii minus sign
  38.  ZERO    equ 48        ; ascii character for digit zero
  39.  NINE    equ 57        ; ascii character for digit nine
  40.  PROGFONT equ 4        ; Monaco font code
  41.  ASCENT    equ 0        ; offsets of fields in fontinfo record
  42.  DESCENT    equ 2
  43.  WIDMAX    equ 4
  44.  LEADING    equ 6
  45.  BUFSIZE equ 256        ; size of input buffer
  46.  
  47.  xdef    start
  48.  xref    main
  49.  
  50.  ;  Preserve registers in safe place; initialize graphics, font manager,
  51.  ;  windows, cursor, and textedit; call main program; restore registers
  52.  ;  and exit.
  53.  
  54.  start:    movem.l    D0-D7/A0-A6, -(SP)    ; save all registers
  55.      lea    saveregs, A0
  56.      move.l    A6, (A0)
  57.      move.l    A7, 4(A0)
  58.      
  59.      move.l    A5, D0            ; set up quickdraw
  60.      sub.l    #4, D0
  61.      move.l    D0, -(SP)
  62.      _INITGRAF
  63.      _INITFONT
  64.      _INITWINDOW
  65.      _INITCURSOR
  66.      _TEINIT
  67.      
  68.      bsr main            ; call the main program
  69.      
  70.      lea    saveregs, A0
  71.      move.l    (A0), A6
  72.      move.l    4(A0), A7
  73.      movem.l    (SP)+, D0-D7/A0-A6
  74.      _EXITTOSHELL
  75.      
  76.  
  77.  ; Subroutine makewindow ( StringAddress )
  78.  ;  Receives argument in A0
  79.  ;    Creates and displays a desk-accessory style window with title
  80.  ;    specified by string whose address is passed; flushes event queue
  81.  ;    and initializes cursor position for text I/O
  82.  
  83.  xdef    makewindow
  84.  
  85.  makewindow:
  86.      movem.l    D0-D2/A0-A1, -(SP)    ; save registers
  87.      clr.l    -(SP)            ; space for return window pointer
  88.      clr.l    -(SP)            ; nil wstorage pointer - window 
  89.                      ;  record storage will be allocated
  90.                      ;  on heap
  91.      pea    boundsrect        ; determines window size and loc
  92.      move.l    A0, -(SP)        ; window title
  93.      st    -(SP)            ; visible flag true - draw window
  94.      move    #16, -(SP)        ; procid - desk accessory type window
  95.      move.l    #-1, -(SP)        ; behind pointer -1 means in front
  96.                      ;  of all other windows
  97.      sf    -(SP)            ; goaway flag false - no goaway box
  98.      clr.l    -(SP)            ; refcon (not used)
  99.      _NEWWINDOW
  100.      move.l    (SP), window(A5)
  101.      _SETPORT
  102.      clr.l    -(SP)
  103.      _NEWRGN                ; create a region
  104.      lea    scrollrgnh, A0
  105.      move.l    (SP), (A0)
  106.      pea    scrollrect        ; with same bounds as boundsrect
  107.      _RECTRGN            ; (required later for scrolling)
  108.      move.w    #PROGFONT, -(SP)    ; set font to Geneva (monofont)
  109.      _TEXTFONT
  110.      pea    fontinfo        ; get information on font
  111.      _GETFONTINFO            ;  dimension parameters
  112.      clr.w    D0            ; accumulate line height in D0
  113.      add.w    fontinfo+ASCENT, D0
  114.      add.w    fontinfo+DESCENT, D0
  115.      add.w    fontinfo+LEADING, D0
  116.      lea    lnht, A0
  117.      move.w    D0, (A0)        ; store in lnht
  118.      move.l    D0, -(SP)        ; flush event queue
  119.      move.l    #$0000FFFF, D0
  120.      _FLUSHEVENTS
  121.      move.l    (SP)+, D0
  122.      move    #LMARG, -(SP)        ; initialize cursor position
  123.      move    #TMARG, -(SP)
  124.      _MOVETO
  125.      movem.l    (SP)+, D0-D2/A0-A1    ; restore registers
  126.      rts
  127.      
  128.  ; Subroutine clearwindow
  129.  ;    Erases contents of window and 'homes' pen to original position in
  130.  ;    upper left corner.
  131.  
  132.  xdef    clearwindow
  133.  
  134.  clearwindow:
  135.      movem.l    D0-D2/A0-A1, -(SP)    ; save registers
  136.      pea    scrollrect        ; erase window contents
  137.      _ERASERECT
  138.      move.w    #LMARG, -(SP)        ; home pen
  139.      move.w    #TMARG, -(SP)
  140.      _MOVETO
  141.      movem.l    (SP)+, D0-D2/A0-A1    ; restore registers
  142.      rts
  143.      
  144.  ; Subroutine rdchar 
  145.  ;   Returns single character result in D0.
  146.  ;    Waits for next keyboard character from event queue, echoes it on
  147.  ;    screen and returns it in D0.  If character is CR or right margin has
  148.  ;    been reached, moves cursor to left margin one line down.
  149.  
  150.  xdef    rdchar
  151.  
  152.  rdchar: lea    regbufe, A0
  153.      movem.l    D1-D2/A1, -(A0)        ; save registers (but not A0)
  154.      move.w    #40, -(SP)        ; mask for key-down or auto-key event
  155.      pea    evbuf            ; pass address of event buffer
  156.      _GETNEXTEVENT
  157.      lea    evbuf, A0        ; any characters?
  158.      tst.w    (A0)
  159.      beq    rdchar            ; if not, keep waiting
  160.      clr.l    D0
  161.      move.b    5(A0), D0        ; pass character to wrtchar
  162.      jsr    wrtchar
  163.      lea    regbuf, A0
  164.      movem.l    (A0)+, D1-D2/A1        ; restore registers
  165.      rts
  166.      
  167.  ; Subroutine wrtchar ( character )
  168.  ;   Receives single character argument in D0
  169.  ;    Draws character on screen; if character is CR or right margin has
  170.  ;    been reached, moves pen to left margin one line down; if bottom
  171.  ;    has been reached, scrolls up one line.
  172.  
  173.  xdef    wrtchar
  174.  
  175.  wrtchar:
  176.      movem.l    D1-D2/D5-D7/A0-A1, -(SP) ; save registers
  177.      move.l    D0, D5            ; store character in D5
  178.      pea    penloc            ; check pen location
  179.      _GETPEN
  180.      move.w    penloc+2, D7        ; store x value of pen in D7
  181.      move.w    penloc, D6        ; store y value of pen in D6
  182.      cmp.b    #BS, D5            ; backspace typed?
  183.      bne    wrtchar1        ; if not, skip code to erase char.
  184.      cmp.w    #LMARG, D7        ; already at left margin?
  185.      beq    wrtchar4        ; if so, skip code to erase char.
  186.      lea    fontinfo, A0        ; compute and push inverse of
  187.      move.w    WIDMAX(A0), D0        ; character width
  188.      neg.w    D0
  189.      move.w    D0, -(SP)
  190.      move.w    #0, -(SP)        ; don't change pen's y coord
  191.      _MOVE                ; move pen back one character pos.
  192.      move.w    D7, -(SP)        ; push x coord for lower right corner
  193.      move.w    D6, D0            ; add descent amount to y coord
  194.      add.w    fontinfo+DESCENT, D0    ;  of lower right corner
  195.      move.w    D0, -(SP)        ; of erase rect.
  196.      sub.w    fontinfo+ASCENT, D6    ; compute coords for upper left
  197.      sub.w    fontinfo+WIDMAX, D7    ; corner of erase rect
  198.      move.w    D7, -(SP)        ; and push them
  199.      move.w    D6, -(SP)        
  200.      move.l    SP, A0            ; push addr of erase rect
  201.      move.l    A0, -(SP)
  202.      _ERASERECT            ; erase deleted character
  203.      add    #8, SP            ; remove rectangle coords from stack
  204.      bra    wrtchar4        ; skip ahead to return backspace
  205.  wrtchar1:
  206.      cmp.b    #CR, D5            ; carriage return?
  207.      beq    wrtchar2            ; if so, skip to new-line generation
  208.      cmp.w    #RMARG, D7        ; past right margin?
  209.      blt    wrtchar3            ; if not, skip new-line generation
  210.  wrtchar2:                 ; generate new line
  211.      sub.w    #LMARG, D7        ; compute delta x
  212.      neg.w    D7
  213.      move.w    D7, -(SP)
  214.      lea    lnht, A0
  215.      move.w    (A0), -(SP)
  216.      _MOVE                ; position cursor for new line
  217.      cmp.w    #BMARG, D6        ; past bottom margin?
  218.      blt    wrtchar3            ; if not, skip past code for scroll
  219.      pea    scrollrect
  220.      move.w    #0, -(SP)
  221.      lea    lnht, A0
  222.      move.w    (A0), -(SP)
  223.      neg.w    (SP)
  224.      lea    scrollrgnh, A0
  225.      move.l    (A0), -(SP)        ; else, scroll up by one
  226.      _SCROLLRECT            ; line height
  227.      move.w    #0, -(SP)
  228.      lea    lnht, A0
  229.      move.w    (A0), -(SP)        ; move pen up accordingly
  230.      neg.w    (SP)
  231.      _MOVE
  232.  wrtchar3:
  233.      move.w    D5, -(SP)
  234.      _DRAWCHAR            ; display character
  235.  wrtchar4:
  236.      move.l    D5, D0            ; return character in D0
  237.      movem.l (SP)+, D1-D2/D5-D7/A0-A1 ; restore registers
  238.      rts
  239.      
  240.  ; Subroutine wrtdec ( num: integer )
  241.  ;   Receives integer argument in D0.
  242.  ;    If argument is negative, negates it and outputs a minus sign; calls
  243.  ;    subroutine prtdec to output digits of number
  244.  
  245.  xdef    wrtdec
  246.  
  247.  wrtdec:    movem.l D0-D2/A0-A1, -(SP)    ; save registers
  248.      tst.w    D0            ; negative?
  249.      bge    wrtdec1            
  250.      neg.w    D0            ; if so, negate num
  251.      move.w    D0, -(SP)        ; save num
  252.      ;clr.w    D0
  253.      move.b    #DASH, D0        ; output minus sign
  254.      jsr    wrtchar
  255.      move.w    (SP)+, D0        ; restore num to D0
  256.  wrtdec1:
  257.      swap    D0
  258.      clr.w    D0
  259.      swap    D0
  260.      bsr    prtdec            ; output num
  261.      movem.l (SP)+, D0-D2/A0-A1    ; restore registers
  262.      rts
  263.      
  264.  ; Subroutine prtdec (num: integer)
  265.  ;   Receives integer argument in D0.
  266.  ;    Recursively outputs digits of integer in decimal to terminal.
  267.  
  268.  prtdec:    divs    #10, D0            ; num <- num DIV 10
  269.      tst.w    D0            ; result equals zero?
  270.      beq    prtdec1
  271.      move.l    D0, -(SP)        ; if not, call prtdec recursively
  272.      swap    D0
  273.      clr.w    D0            ; (first getting rid of remainder)
  274.      swap    D0
  275.      bsr    prtdec            ; with num DIV 10
  276.      move.l    (SP)+, D0
  277.  prtdec1:
  278.      swap    D0            ; num MOD 10
  279.      add.b    #ZERO, D0        ; compute ascii code for digit
  280.      jsr    wrtchar            ; output digit
  281.      rts
  282.      
  283.  ; Subroutine rddec 
  284.  ;   Returns integer result in D0.
  285.  ;    Inputs signed word integer value (decimal), ignores all non-numeric
  286.  ;    characters except for minus sign, returns result on encountering
  287.  ;    CR.
  288.  
  289.  xdef    rddec
  290.  
  291.  rddec:    movem.l D1-D5/A0-A1, -(SP)    ; save registers
  292.      lea    inbuf, A0
  293.      jsr    rdstrz            ; input line to buffer
  294.      clr.w    D0            ; sum = 0
  295.      clr.w    D3            ; character holder = 0
  296.      clr.b    D4            ; digits read = false
  297.      move.w    #1, D5            ; sign = +
  298.  rddec1: move.b    (A0)+, D3        ; end of input line?
  299.      beq     rddec3            ; if so, return result
  300.      cmp.b    #DASH, D3        ; minus sign?
  301.      bne    rddec2
  302.      tst.b    D4            ; if so, any digits read yet?
  303.      bne    rddec1            ; if so, ignore minus sign
  304.      neg.w    D5            ; else, sign = -
  305.      bra    rddec1
  306.  rddec2: cmp.b    #ZERO, D3        ; less than '0'?
  307.      blt    rddec1            ; if so, ignore
  308.      cmp.b    #NINE, D3        ; greater than '9'?
  309.      bgt    rddec1            ; if so, ignore
  310.      move.b    #1, D4            ; digits read = true
  311.      muls    #10, D0            ; sum = sum * 10
  312.      sub.w    #ZERO, D3        ; subtract ascii code for 0 from char
  313.                      ;  to get digit value
  314.      add.w    D3, D0            ; sum = sum + digit
  315.      bra    rddec1            ; get next character
  316.  rddec3:    muls    D5, D0            ; sum = sum * sign
  317.      movem.l (SP)+, D1-D5/A0-A1    ; restore registers
  318.      rts
  319.      
  320.  ; Subroutine rdstrz ( BufferAddress )
  321.  ;   Receives address of destination buffer in A0.
  322.  ;    Inputs characters to buffer specified by destination address
  323.  ;    until CR is read; terminates string with zero byte; if backspace
  324.  ;    encountered, deletes last character in buffer, backspace not stored.
  325.  ;    Inputs maximum of 255 characters to buffer (plus zero byte), flushes
  326.  ;    excessive input until next CR encountered (for buffers less than
  327.  ;    256 bytes long, buffer overflow is a possibility).
  328.  
  329.  xdef    rdstrz
  330.  
  331.  rdstrz:    movem.l D0-D3/A0-A2, -(SP)    ; save registers
  332.      clr.w    D3            ; initialize counter
  333.      movea.l    A0, A2            ; save addr of buffer in A2
  334.  rdstrz1:
  335.      jsr    rdchar            ; input next character
  336.      cmp.b    #CR, D0            ; CR?
  337.      beq    rdstrz5            ; if so, terminate string
  338.      cmp.b    #BS, D0            ; backspace?
  339.      bne    rdstrz2    
  340.      tst.w    D3            ; if so, is buffer empty?
  341.      beq    rdstrz1            ; if so, get next character
  342.      clr.b    -(A2)            ; else, delete last character
  343.      sub.w    #1, D3            ; decrement counter
  344.      bra    rdstrz1            ; input another character
  345.  rdstrz2:
  346.      cmp.w    #BUFSIZE-1, D3        ; buffer full?
  347.      bne    rdstrz4
  348.  rdstrz3:
  349.      jsr    rdchar            ; if so,
  350.      cmp.b    #CR, D0            ; discard input characters till
  351.      bne    rdstrz3            ; CR found
  352.      bra    rdstrz5            ; and terminate string
  353.  rdstrz4:
  354.      add.w    #1, D3            ; else, increment character count
  355.      move.b    D0, (A2)+        ; and move input character to
  356.                      ;  next buffer position
  357.      bra    rdstrz1            ; input another character
  358.  rdstrz5:
  359.      clr.b    (A2)            ; zero terminate
  360.      movem.l (SP)+, D0-D3/A0-A2    ; restore registers
  361.      rts
  362.      
  363.  ; Subroutine wrtstrz ( BufferAddress )
  364.  ;   Receives address of zero-terminated string in A0.
  365.  ;    Outputs characters of string on screen until zero byte is reached.
  366.  
  367.  xdef    wrtstrz
  368.  
  369.  wrtstrz:
  370.      movem.l D0/A0, -(SP)        ; save registers
  371.  wrtstrz1:
  372.      move.b    (A0)+, D0        ; pass char to wrtchar
  373.      beq    wrtstrz2        ; return when zero byte reached
  374.      jsr    wrtchar            ; output character
  375.      bra    wrtstrz1        ; get next byte
  376.  wrtstrz2:
  377.      movem.l (SP)+, D0/A0        ; restore registers
  378.      rts
  379.      
  380.  ; Subroutine rdstrc ( BufferAddress )
  381.  ;   Receives address of destination buffer in A0.
  382.  ;    Inputs characters to buffer specified by destination address
  383.  ;    until CR is read; places count byte at start of string; if backspace
  384.  ;    encountered, deletes last character in buffer, backspace not stored.
  385.  ;    Inputs maximum of 255 characters to buffer (plus count byte), flushes
  386.  ;    excessive input until next CR encountered (for buffers less than
  387.  ;    256 bytes long, buffer overflow is a possibility).
  388.  
  389.  xdef    rdstrc
  390.  
  391.  rdstrc:    movem.l D0-D3/A0-A3, -(SP)    ; save registers
  392.      movea.l    A0, A2            ; save addr of buffer in A2
  393.      movea.l    A0, A3            ; and A3
  394.      tst.b    (A2)+            ; increment pointer past count byte
  395.      clr.b    D3            ; initialize counter
  396.  rdstrc1:
  397.      jsr    rdchar            ; input next character
  398.      cmp.b    #CR, D0            ; CR?
  399.      beq    rdstrc5            ; if so, terminate string
  400.      cmp.b    #BS, D0            ; backspace?
  401.      bne    rdstrc2    
  402.      tst.b    D3            ; if so, is buffer empty?
  403.      beq    rdstrc1            ; if so, get next character
  404.      clr.b    -(A2)            ; else, delete last character
  405.      sub.b    #1, D3            ; decrement counter
  406.      bra    rdstrc1            ; input another character
  407.  rdstrc2:
  408.      cmp.b    #BUFSIZE-1, D3        ; buffer full?
  409.      bne    rdstrc4
  410.  rdstrc3:
  411.      jsr    rdchar            ; if so,
  412.      cmp.b    #CR, D0            ; discard input characters till
  413.      bne    rdstrc3            ; CR found
  414.      bra    rdstrc5            ; and terminate string
  415.  rdstrc4:
  416.      add.b    #1, D3            ; else, increment character count
  417.      move.b    D0, (A2)+        ; and move input character to
  418.                      ;  next buffer position
  419.      bra    rdstrc1            ; input another character
  420.  rdstrc5:
  421.      move.b    D3, (A3)        ; insert count byte
  422.      movem.l (SP)+, D0-D3/A0-A3    ; restore registers
  423.      rts
  424.      
  425.  ; Subroutine wrtstrc ( BufferAddress )
  426.  ;   Receives address of count string in A0.
  427.  ;    Outputs number of characters specified by count-byte.
  428.  
  429.  xdef    wrtstrc
  430.  
  431.  wrtstrc:
  432.      movem.l D0/D3/A0, -(SP)        ; save registers
  433.      move.b    (A0)+, D3        ; store count in D3
  434.  wrtstrc1:
  435.      tst.b    D3            ; all characters output?
  436.      beq    wrtstrc2        ; then quit
  437.      move.b    (A0)+, D0        ; pass char to wrtchar
  438.      jsr    wrtchar            ; output character
  439.      sub.b    #1, D3            ; decrement counter
  440.      bra    wrtstrc1        ; get next byte
  441.  wrtstrc2:
  442.      movem.l (SP)+, D0/D3/A0        ; restore registers
  443.      rts
  444.      
  445.  
  446.  ; data for shell program
  447.  
  448.  saveregs: dcb.l    2, 0    ; space for storing saved registers
  449.  evbuf:    dcb.l    4, 0    ; event buffer
  450.  
  451.  ; data for subroutine makewindow
  452.  
  453.  boundsrect:    dc.w    Y1, X1, Y2, X2        ; the window rectangle in
  454.                          ;  global coordinates
  455.  scrollrect:    dc.w    0, 0, WINDHEIGHT, WINDWIDTH ; the window rectangle
  456.                          ;  in local coordinates
  457.  scrollrgnh:    dc.l    0            ; handle for scroll region
  458.  fontinfo:    dcb.w    4, 0            ; buffer for record returned
  459.                          ;  by _GETFONTINFO
  460.  lnht:        dc.w    0            ; buffer for height of line
  461.                          ;  of text
  462.  ; data for subroutine rdchar
  463.  
  464.  penloc:    dc.l    0        ; storage for pen location coordinates
  465.  regbuf:    dcb.l    3, 0        ; storage for saved registers
  466.  regbufe:
  467.  
  468.  ; data for subroutine rddec
  469.  
  470.  inbuf:    dcb.b    BUFSIZE, 0    ; input buffer
  471.  
  472.  ; global storage
  473.  
  474.  window:    ds.l    1
  475.  
  476.      end
  477.  
  478.