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