assembly i/o package
Posted: January 16th, 1985, 12:44 am
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Posting-Version: version B 2.10.2 9/18/84; site uw-beaver
Path: utzoo!watmath!clyde!cbosgd!ulysses!mhuxr!mhuxt!mhuxj!houxm!vax135!cornell!uw-beaver!info-mac
From: info-mac@uw-beaver
Newsgroups: fa.info-mac
Subject: assembly i/o package
Message-ID:
Date: Fri, 21-Dec-84 18:46:20 EST
Article-I.D.: uw-beave.279
Posted: Fri Dec 21 18:46:20 1984
Date-Received: Sat, 22-Dec-84 07:38:00 EST
Sender: daemon@uw-beaver
Organization: U of Washington Computer Science
Lines: 490
From: [email protected] (Dan Winkler)
Here is a little assembly language i/o package developed for our
assembly language courses that use the Mac. It was written by Jeff
Miller and is used by his QuickPrint and MacMelody programs.
We were using an early version of the assembler then, but this should
work just fine with the newer versions. The only difference I know of
is that the new assembler names its linker files .link but the old one
named them .ld.
Dan. (winkler@harvard)
; 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
Posting-Version: version B 2.10.2 9/18/84; site uw-beaver
Path: utzoo!watmath!clyde!cbosgd!ulysses!mhuxr!mhuxt!mhuxj!houxm!vax135!cornell!uw-beaver!info-mac
From: info-mac@uw-beaver
Newsgroups: fa.info-mac
Subject: assembly i/o package
Message-ID:
Date: Fri, 21-Dec-84 18:46:20 EST
Article-I.D.: uw-beave.279
Posted: Fri Dec 21 18:46:20 1984
Date-Received: Sat, 22-Dec-84 07:38:00 EST
Sender: daemon@uw-beaver
Organization: U of Washington Computer Science
Lines: 490
From: [email protected] (Dan Winkler)
Here is a little assembly language i/o package developed for our
assembly language courses that use the Mac. It was written by Jeff
Miller and is used by his QuickPrint and MacMelody programs.
We were using an early version of the assembler then, but this should
work just fine with the newer versions. The only difference I know of
is that the new assembler names its linker files .link but the old one
named them .ld.
Dan. (winkler@harvard)
; 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