home *** CD-ROM | disk | FTP | other *** search
- ; io.asm
- ; "Frame" program and I/O subroutines for general purpose assembly language
- ; programs. To use this package:
- ; 1. The first line in your file should be "include iodefs.txt".
- ; 2. Your main program must begin with the label "main" and end with rts.
- ; 3. Your .ld file should look like this, if your source file is called
- ; myprog.asm:
- ; !start
- ; io
- ; myprog
- ; $
- ; 4. Pass arguments to subroutines in this package, and receive return
- ; values, in D0 or A0 as specified. All registers are preserved (but
- ; subroutine rdchar does not preserve A0).
- ; 5. Always call subroutine makewindow at the beginning of your main
- ; program, passing the address of your title string in A0.
-
- ; Include all necessary traps files
-
- include m68klib.d
- include systraps.txt
- include quicktraps.txt
- include tooltraps.txt
-
- WINDWIDTH equ 492 ; window dimensions
- WINDHEIGHT equ 280
- X1 equ 8 ; upper-left and lower-right coordinates
- Y1 equ 48 ; for bounds rectangle for window
- X2 equ X1+WINDWIDTH
- Y2 equ Y1+WINDHEIGHT
- LMARG equ 6 ; text margins - left,
- RMARG equ WINDWIDTH-10 ; right,
- TMARG equ 15 ; top,
- BMARG equ WINDHEIGHT-15 ; bottom
- CR equ 13 ; ascii carriage return
- BS equ 8 ; ascii backspace
- DASH equ 45 ; ascii minus sign
- ZERO equ 48 ; ascii character for digit zero
- NINE equ 57 ; ascii character for digit nine
- PROGFONT equ 4 ; Monaco font code
- ASCENT equ 0 ; offsets of fields in fontinfo record
- DESCENT equ 2
- WIDMAX equ 4
- LEADING equ 6
- BUFSIZE equ 256 ; size of input buffer
-
- xdef start
- xref main
-
- ; Preserve registers in safe place; initialize graphics, font manager,
- ; windows, cursor, and textedit; call main program; restore registers
- ; and exit.
-
- start: movem.l D0-D7/A0-A6, -(SP) ; save all registers
- lea saveregs, A0
- move.l A6, (A0)
- move.l A7, 4(A0)
-
- move.l A5, D0 ; set up quickdraw
- sub.l #4, D0
- move.l D0, -(SP)
- _INITGRAF
- _INITFONT
- _INITWINDOW
- _INITCURSOR
- _TEINIT
-
- bsr main ; call the main program
-
- lea saveregs, A0
- move.l (A0), A6
- move.l 4(A0), A7
- movem.l (SP)+, D0-D7/A0-A6
- _EXITTOSHELL
-
-
- ; Subroutine makewindow ( StringAddress )
- ; Receives argument in A0
- ; Creates and displays a desk-accessory style window with title
- ; specified by string whose address is passed; flushes event queue
- ; and initializes cursor position for text I/O
-
- xdef makewindow
-
- makewindow:
- movem.l D0-D2/A0-A1, -(SP) ; save registers
- clr.l -(SP) ; space for return window pointer
- clr.l -(SP) ; nil wstorage pointer - window
- ; record storage will be allocated
- ; on heap
- pea boundsrect ; determines window size and loc
- move.l A0, -(SP) ; window title
- st -(SP) ; visible flag true - draw window
- move #16, -(SP) ; procid - desk accessory type window
- move.l #-1, -(SP) ; behind pointer -1 means in front
- ; of all other windows
- sf -(SP) ; goaway flag false - no goaway box
- clr.l -(SP) ; refcon (not used)
- _NEWWINDOW
- move.l (SP), window(A5)
- _SETPORT
- clr.l -(SP)
- _NEWRGN ; create a region
- lea scrollrgnh, A0
- move.l (SP), (A0)
- pea scrollrect ; with same bounds as boundsrect
- _RECTRGN ; (required later for scrolling)
- move.w #PROGFONT, -(SP) ; set font to Geneva (monofont)
- _TEXTFONT
- pea fontinfo ; get information on font
- _GETFONTINFO ; dimension parameters
- clr.w D0 ; accumulate line height in D0
- add.w fontinfo+ASCENT, D0
- add.w fontinfo+DESCENT, D0
- add.w fontinfo+LEADING, D0
- lea lnht, A0
- move.w D0, (A0) ; store in lnht
- move.l D0, -(SP) ; flush event queue
- move.l #$0000FFFF, D0
- _FLUSHEVENTS
- move.l (SP)+, D0
- move #LMARG, -(SP) ; initialize cursor position
- move #TMARG, -(SP)
- _MOVETO
- movem.l (SP)+, D0-D2/A0-A1 ; restore registers
- rts
-
- ; Subroutine clearwindow
- ; Erases contents of window and 'homes' pen to original position in
- ; upper left corner.
-
- xdef clearwindow
-
- clearwindow:
- movem.l D0-D2/A0-A1, -(SP) ; save registers
- pea scrollrect ; erase window contents
- _ERASERECT
- move.w #LMARG, -(SP) ; home pen
- move.w #TMARG, -(SP)
- _MOVETO
- movem.l (SP)+, D0-D2/A0-A1 ; restore registers
- rts
-
- ; Subroutine rdchar
- ; Returns single character result in D0.
- ; Waits for next keyboard character from event queue, echoes it on
- ; screen and returns it in D0. If character is CR or right margin has
- ; been reached, moves cursor to left margin one line down.
-
- xdef rdchar
-
- rdchar: lea regbufe, A0
- movem.l D1-D2/A1, -(A0) ; save registers (but not A0)
- move.w #40, -(SP) ; mask for key-down or auto-key event
- pea evbuf ; pass address of event buffer
- _GETNEXTEVENT
- lea evbuf, A0 ; any characters?
- tst.w (A0)
- beq rdchar ; if not, keep waiting
- clr.l D0
- move.b 5(A0), D0 ; pass character to wrtchar
- jsr wrtchar
- lea regbuf, A0
- movem.l (A0)+, D1-D2/A1 ; restore registers
- rts
-
- ; Subroutine wrtchar ( character )
- ; Receives single character argument in D0
- ; Draws character on screen; if character is CR or right margin has
- ; been reached, moves pen to left margin one line down; if bottom
- ; has been reached, scrolls up one line.
-
- xdef wrtchar
-
- wrtchar:
- movem.l D1-D2/D5-D7/A0-A1, -(SP) ; save registers
- move.l D0, D5 ; store character in D5
- pea penloc ; check pen location
- _GETPEN
- move.w penloc+2, D7 ; store x value of pen in D7
- move.w penloc, D6 ; store y value of pen in D6
- cmp.b #BS, D5 ; backspace typed?
- bne wrtchar1 ; if not, skip code to erase char.
- cmp.w #LMARG, D7 ; already at left margin?
- beq wrtchar4 ; if so, skip code to erase char.
- lea fontinfo, A0 ; compute and push inverse of
- move.w WIDMAX(A0), D0 ; character width
- neg.w D0
- move.w D0, -(SP)
- move.w #0, -(SP) ; don't change pen's y coord
- _MOVE ; move pen back one character pos.
- move.w D7, -(SP) ; push x coord for lower right corner
- move.w D6, D0 ; add descent amount to y coord
- add.w fontinfo+DESCENT, D0 ; of lower right corner
- move.w D0, -(SP) ; of erase rect.
- sub.w fontinfo+ASCENT, D6 ; compute coords for upper left
- sub.w fontinfo+WIDMAX, D7 ; corner of erase rect
- move.w D7, -(SP) ; and push them
- move.w D6, -(SP)
- move.l SP, A0 ; push addr of erase rect
- move.l A0, -(SP)
- _ERASERECT ; erase deleted character
- add #8, SP ; remove rectangle coords from stack
- bra wrtchar4 ; skip ahead to return backspace
- wrtchar1:
- cmp.b #CR, D5 ; carriage return?
- beq wrtchar2 ; if so, skip to new-line generation
- cmp.w #RMARG, D7 ; past right margin?
- blt wrtchar3 ; if not, skip new-line generation
- wrtchar2: ; generate new line
- sub.w #LMARG, D7 ; compute delta x
- neg.w D7
- move.w D7, -(SP)
- lea lnht, A0
- move.w (A0), -(SP)
- _MOVE ; position cursor for new line
- cmp.w #BMARG, D6 ; past bottom margin?
- blt wrtchar3 ; if not, skip past code for scroll
- pea scrollrect
- move.w #0, -(SP)
- lea lnht, A0
- move.w (A0), -(SP)
- neg.w (SP)
- lea scrollrgnh, A0
- move.l (A0), -(SP) ; else, scroll up by one
- _SCROLLRECT ; line height
- move.w #0, -(SP)
- lea lnht, A0
- move.w (A0), -(SP) ; move pen up accordingly
- neg.w (SP)
- _MOVE
- wrtchar3:
- move.w D5, -(SP)
- _DRAWCHAR ; display character
- wrtchar4:
- move.l D5, D0 ; return character in D0
- movem.l (SP)+, D1-D2/D5-D7/A0-A1 ; restore registers
- rts
-
- ; Subroutine wrtdec ( num: integer )
- ; Receives integer argument in D0.
- ; If argument is negative, negates it and outputs a minus sign; calls
- ; subroutine prtdec to output digits of number
-
- xdef wrtdec
-
- wrtdec: movem.l D0-D2/A0-A1, -(SP) ; save registers
- tst.w D0 ; negative?
- bge wrtdec1
- neg.w D0 ; if so, negate num
- move.w D0, -(SP) ; save num
- ;clr.w D0
- move.b #DASH, D0 ; output minus sign
- jsr wrtchar
- move.w (SP)+, D0 ; restore num to D0
- wrtdec1:
- swap D0
- clr.w D0
- swap D0
- bsr prtdec ; output num
- movem.l (SP)+, D0-D2/A0-A1 ; restore registers
- rts
-
- ; Subroutine prtdec (num: integer)
- ; Receives integer argument in D0.
- ; Recursively outputs digits of integer in decimal to terminal.
-
- prtdec: divs #10, D0 ; num <- num DIV 10
- tst.w D0 ; result equals zero?
- beq prtdec1
- move.l D0, -(SP) ; if not, call prtdec recursively
- swap D0
- clr.w D0 ; (first getting rid of remainder)
- swap D0
- bsr prtdec ; with num DIV 10
- move.l (SP)+, D0
- prtdec1:
- swap D0 ; num MOD 10
- add.b #ZERO, D0 ; compute ascii code for digit
- jsr wrtchar ; output digit
- rts
-
- ; Subroutine rddec
- ; Returns integer result in D0.
- ; Inputs signed word integer value (decimal), ignores all non-numeric
- ; characters except for minus sign, returns result on encountering
- ; CR.
-
- xdef rddec
-
- rddec: movem.l D1-D5/A0-A1, -(SP) ; save registers
- lea inbuf, A0
- jsr rdstrz ; input line to buffer
- clr.w D0 ; sum = 0
- clr.w D3 ; character holder = 0
- clr.b D4 ; digits read = false
- move.w #1, D5 ; sign = +
- rddec1: move.b (A0)+, D3 ; end of input line?
- beq rddec3 ; if so, return result
- cmp.b #DASH, D3 ; minus sign?
- bne rddec2
- tst.b D4 ; if so, any digits read yet?
- bne rddec1 ; if so, ignore minus sign
- neg.w D5 ; else, sign = -
- bra rddec1
- rddec2: cmp.b #ZERO, D3 ; less than '0'?
- blt rddec1 ; if so, ignore
- cmp.b #NINE, D3 ; greater than '9'?
- bgt rddec1 ; if so, ignore
- move.b #1, D4 ; digits read = true
- muls #10, D0 ; sum = sum * 10
- sub.w #ZERO, D3 ; subtract ascii code for 0 from char
- ; to get digit value
- add.w D3, D0 ; sum = sum + digit
- bra rddec1 ; get next character
- rddec3: muls D5, D0 ; sum = sum * sign
- movem.l (SP)+, D1-D5/A0-A1 ; restore registers
- rts
-
- ; Subroutine rdstrz ( BufferAddress )
- ; Receives address of destination buffer in A0.
- ; Inputs characters to buffer specified by destination address
- ; until CR is read; terminates string with zero byte; if backspace
- ; encountered, deletes last character in buffer, backspace not stored.
- ; Inputs maximum of 255 characters to buffer (plus zero byte), flushes
- ; excessive input until next CR encountered (for buffers less than
- ; 256 bytes long, buffer overflow is a possibility).
-
- xdef rdstrz
-
- rdstrz: movem.l D0-D3/A0-A2, -(SP) ; save registers
- clr.w D3 ; initialize counter
- movea.l A0, A2 ; save addr of buffer in A2
- rdstrz1:
- jsr rdchar ; input next character
- cmp.b #CR, D0 ; CR?
- beq rdstrz5 ; if so, terminate string
- cmp.b #BS, D0 ; backspace?
- bne rdstrz2
- tst.w D3 ; if so, is buffer empty?
- beq rdstrz1 ; if so, get next character
- clr.b -(A2) ; else, delete last character
- sub.w #1, D3 ; decrement counter
- bra rdstrz1 ; input another character
- rdstrz2:
- cmp.w #BUFSIZE-1, D3 ; buffer full?
- bne rdstrz4
- rdstrz3:
- jsr rdchar ; if so,
- cmp.b #CR, D0 ; discard input characters till
- bne rdstrz3 ; CR found
- bra rdstrz5 ; and terminate string
- rdstrz4:
- add.w #1, D3 ; else, increment character count
- move.b D0, (A2)+ ; and move input character to
- ; next buffer position
- bra rdstrz1 ; input another character
- rdstrz5:
- clr.b (A2) ; zero terminate
- movem.l (SP)+, D0-D3/A0-A2 ; restore registers
- rts
-
- ; Subroutine wrtstrz ( BufferAddress )
- ; Receives address of zero-terminated string in A0.
- ; Outputs characters of string on screen until zero byte is reached.
-
- xdef wrtstrz
-
- wrtstrz:
- movem.l D0/A0, -(SP) ; save registers
- wrtstrz1:
- move.b (A0)+, D0 ; pass char to wrtchar
- beq wrtstrz2 ; return when zero byte reached
- jsr wrtchar ; output character
- bra wrtstrz1 ; get next byte
- wrtstrz2:
- movem.l (SP)+, D0/A0 ; restore registers
- rts
-
- ; Subroutine rdstrc ( BufferAddress )
- ; Receives address of destination buffer in A0.
- ; Inputs characters to buffer specified by destination address
- ; until CR is read; places count byte at start of string; if backspace
- ; encountered, deletes last character in buffer, backspace not stored.
- ; Inputs maximum of 255 characters to buffer (plus count byte), flushes
- ; excessive input until next CR encountered (for buffers less than
- ; 256 bytes long, buffer overflow is a possibility).
-
- xdef rdstrc
-
- rdstrc: movem.l D0-D3/A0-A3, -(SP) ; save registers
- movea.l A0, A2 ; save addr of buffer in A2
- movea.l A0, A3 ; and A3
- tst.b (A2)+ ; increment pointer past count byte
- clr.b D3 ; initialize counter
- rdstrc1:
- jsr rdchar ; input next character
- cmp.b #CR, D0 ; CR?
- beq rdstrc5 ; if so, terminate string
- cmp.b #BS, D0 ; backspace?
- bne rdstrc2
- tst.b D3 ; if so, is buffer empty?
- beq rdstrc1 ; if so, get next character
- clr.b -(A2) ; else, delete last character
- sub.b #1, D3 ; decrement counter
- bra rdstrc1 ; input another character
- rdstrc2:
- cmp.b #BUFSIZE-1, D3 ; buffer full?
- bne rdstrc4
- rdstrc3:
- jsr rdchar ; if so,
- cmp.b #CR, D0 ; discard input characters till
- bne rdstrc3 ; CR found
- bra rdstrc5 ; and terminate string
- rdstrc4:
- add.b #1, D3 ; else, increment character count
- move.b D0, (A2)+ ; and move input character to
- ; next buffer position
- bra rdstrc1 ; input another character
- rdstrc5:
- move.b D3, (A3) ; insert count byte
- movem.l (SP)+, D0-D3/A0-A3 ; restore registers
- rts
-
- ; Subroutine wrtstrc ( BufferAddress )
- ; Receives address of count string in A0.
- ; Outputs number of characters specified by count-byte.
-
- xdef wrtstrc
-
- wrtstrc:
- movem.l D0/D3/A0, -(SP) ; save registers
- move.b (A0)+, D3 ; store count in D3
- wrtstrc1:
- tst.b D3 ; all characters output?
- beq wrtstrc2 ; then quit
- move.b (A0)+, D0 ; pass char to wrtchar
- jsr wrtchar ; output character
- sub.b #1, D3 ; decrement counter
- bra wrtstrc1 ; get next byte
- wrtstrc2:
- movem.l (SP)+, D0/D3/A0 ; restore registers
- rts
-
-
- ; data for shell program
-
- saveregs: dcb.l 2, 0 ; space for storing saved registers
- evbuf: dcb.l 4, 0 ; event buffer
-
- ; data for subroutine makewindow
-
- boundsrect: dc.w Y1, X1, Y2, X2 ; the window rectangle in
- ; global coordinates
- scrollrect: dc.w 0, 0, WINDHEIGHT, WINDWIDTH ; the window rectangle
- ; in local coordinates
- scrollrgnh: dc.l 0 ; handle for scroll region
- fontinfo: dcb.w 4, 0 ; buffer for record returned
- ; by _GETFONTINFO
- lnht: dc.w 0 ; buffer for height of line
- ; of text
- ; data for subroutine rdchar
-
- penloc: dc.l 0 ; storage for pen location coordinates
- regbuf: dcb.l 3, 0 ; storage for saved registers
- regbufe:
-
- ; data for subroutine rddec
-
- inbuf: dcb.b BUFSIZE, 0 ; input buffer
-
- ; global storage
-
- window: ds.l 1
-
- end
-
-