[comp.sys.cbm] C-ASSM Sources - Part 01/02

mark@unisec.usi.com (Mark Rinfret) (05/14/87)

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	array.a
#	char.i
#	clock.a
#	disk.a
#	imath.a
#	kernal.i
#	lib1.fo
#	lib2.fo
# This archive created: Thu May 14 06:56:12 1987
export PATH; PATH=/bin:$PATH
if test -f 'array.a'
then
	echo shar: will not over-write existing file "'array.a'"
else
cat << \SHAR_EOF > 'array.a'
;
; Array Manipulation Routines 
; Filename: array.a         
;

#include "mem.i"

mvelen .word 0 ;length of move
;
;
; move a block of memory      
; called with:            
;   ptr1 = source address           
;   ptr2 = destination address  
;   X,Y = length of move
;
 .def blkmov

blkmov
 stx mvelen
 sty mvelen+1
;
;determine type of move
;
 sec
 lda ptr2
 sbc ptr1
 tax
 lda ptr2+1
 sbc ptr1+1
 tay
;
 txa ;compare with nbr bytes
 cmp mvelen
 tya
 sbc mvelen+1
 bcs doleft ;no overlap problem
;
;destination is above source but
;overlaps it.  move from highest
;address to avoid destruction.
;
 jsr mverht
 rts
;
;ordinary lowest to highest move
;
doleft
 jsr mvelft
 rts
;
;
; move source to destination 
; starting from low address  
; entry:                     
;   ptr1 = source address  
;   ptr2 = dest. address   
;   mvelen = byte count      
;
mvelft
 ldy #0
 ldx mvelen+1 ;x = nbr of full pages
 beq mlpart ;partial page
mlpage
 lda (ptr1),y
 sta (ptr2),y
 iny
 bne mlpage
 inc ptr1+1 ;next page of source
 inc ptr2+1 ;nest page of dest
 dex
 bne mlpage ;more pages?
;
;do partial page
mlpart
 ldx mvelen
 beq mlexit ;zero?
mllast
 lda (ptr1),y
 sta (ptr2),y
 iny
 dex
 bne mllast
mlexit
 rts
;
;
; move starting from highest   
; address (move right).        
; entry:                       
;   ptr1   =  source address     
;   ptr2   =  dest. address      
;   mvelen =  byte count         
;
mverht
 clc ;partial page first
 lda mvelen+1
 adc ptr1+1
 sta ptr1+1
;
 clc
 lda mvelen+1
 adc ptr2+1
 sta ptr2+1
;
 ldy mvelen ;length of last page
 beq mrpage ;zero?
mr0
 dey
 lda (ptr1),y
 sta (ptr2),y
 cpy #0
 bne mr0
;
mrpage
 ldx mvelen+1
 beq mrexit ;no full pages?
mr1
 dec ptr1+1
 dec ptr2+1
mr2
 dey
 lda (ptr1),y
 sta (ptr2),y
 cpy #0
 bne mr2
 dex ;decrement page counter
 bne mr1 ;more pages?
mrexit
 rts
;
;
; fill an area of memory with a 
; value.                        
; called with:                
;   A    = value to be stored
;   ptr1 = starting address
;   ptr2 = length
;
;
mfill$sz = ptr2 ;alias
value .byte 0  ;value to store
;
 .def mfill

mfill
;
 sta value

;
 lda value
 ldx mfill$sz+1 ;number of pages
 beq mfill1 ;no full pages?
 ldy #0
mfill0
 sta (ptr1),y
 iny
 bne mfill0
 inc ptr1+1
 dex
 bne mfill0
;
mfill1
 ldx mfill$sz ;get remaining bytes
 beq mfillx ;in partial page
 ldy #0
mfill2
 sta (ptr1),y
 iny
 dex
 bne mfill2
mfillx
 rts
;
SHAR_EOF
fi # end of overwriting check
if test -f 'char.i'
then
	echo shar: will not over-write existing file "'char.i'"
else
cat << \SHAR_EOF > 'char.i'
;
; Character code definitions
; Filename: char.i
;
clrscrn = 147
csrdn = 17
csrlt = 157
csrrt = 29
csrup = 145
del = 20
f1 = 133
f2 = 137
f3 = 134
f4 = 138
f5 = 135
f6 = 139
f7 = 136
f8 = 140
home = 19
inst = 148
lowercase = 14
uppercase = 142
SHAR_EOF
fi # end of overwriting check
if test -f 'clock.a'
then
	echo shar: will not over-write existing file "'clock.a'"
else
cat << \SHAR_EOF > 'clock.a'
;
; Clock Support Routines
; Filename: clock.a
;

#include "mem.i"

 .ref imul

;Sleep for a number of clock ticks (0-65535)
;Called with:
;  Count in X,Y
;Note: This routine depends upon and
;      modifies the jiffy clock.
;      Interrupts must be enabled when
;      calling this routine.

ticks .word 0

 .def tsleep
tsleep
  stx ticks
  sty ticks+1
  lda #0
  sta jclock+2 ;remember - jiffy clock is
  sta jclock+1 ;in reverse order - jclock+2
  sta jclock ;is low order byte
tsleep1
  sec
  lda ticks
  sbc jclock+2
  lda ticks+1
  sbc jclock+1
  bcs tsleep1
  rts

;
;Sleep a number of seconds
;Called with:
;  Seconds in ACC (0-255)

 .def sleep
sleep
 tax ;X = multiplicand
 lda #60 ;ACC = multiplier
 jsr imul
 jmp tsleep ;share code above
SHAR_EOF
fi # end of overwriting check
if test -f 'disk.a'
then
	echo shar: will not over-write existing file "'disk.a'"
else
cat << \SHAR_EOF > 'disk.a'
;Disk and File Routines
;Filename: disk.a
;History:
; 08/30/86 - add .def to getdir

; Description:

;This package is a collection of general
;purpose disk and file management routines.
;At the heart of this package is an external
;table of file numbers, fil$num, from
;which all file numbers are allocated.
;The routine fclose must be called to 
;release a file number for future use.
;Likewise, filenumbers may be permanently
;reserved by storing a zero in the
;appropriate file table slot.  Routine
;fclose should not be called with reserved
;file numbers.

;File number zero (0) is never used.  Once
;the file number is allocated, the caller
;may add 128 for automatic line feeds,
;if required.
;
;Another external variable, disk$dvc,
;determines which device is to be
;accessed.

#include "kernal.i"
#include "mem.i"

maxfn = 10 ;max allocable file number

 .ref atoi ;(imath) ascii to integer
 .ref crwait ;(screen)
 .ref errmsg ;(screen) flash error message
 .ref println ;(termio)
 .ref strcat,strcpy,strlen ;(string)
 .ref string$1,string$2 ;(string)

;Package data

;disk command channel file numbers
 .def disk$cmd
disk$cmd .byte 0,0,0,0

 .def disk$dvc
disk$dvc .byte 8 ;default disk device

 .def fil$num
fil$num .byte 0,0,2,3,4,5,6,7,8,9,10

actual .word 0
dfn .byte 0 ;disk file number
filcnt .byte 0 ;file count
fname .bss 32 ;temp file name
wanted .word 0 ;desired word count


;The following data group constitutes a
;disk directory entry.

 .def disk$blks
disk$blks .word 0
 .def disk$fnam
disk$fnam .bss 17
 .def disk$ftyp
disk$ftyp .bss 4

 .def disk$status
disk$status .bss 40

;
;Allocate a file number from the file
;number table.
;Returns:
;    0 => failed
;  <>0 => file number allocated
;  Zero flag in status reg is valid

 .def getfnbr
getfnbr
 ldx #maxfn
getfnbr1
 lda fil$num,x
 bne getfnbrx ;non-zero => available
 dex
 bne getfnbr1 ;try next slot
getfnbrx
 pha ;save value
 lda #0 ;zero the slot
 sta fil$num,x
 pla ;return value (0 or X)
 rts

;Compute command channel file number
;given current device.
;Called with:
;  disk$dvc = current device number
;Returns:
;  X = command channel file number

 .def gdk$ccf
gdk$ccf
 lda disk$dvc ;use device as index
 and #3 ;extract lower bits
 tax
 lda disk$cmd,x ;into cmd/file table
 tax
 rts


;
;Close file and deallocate file number.
;Called with:
;  ACC = file number

 .def fclose
fclose
 pha
 jsr close
 pla
 and #$0f ;discard upper bits
 cmp #maxfn+1 ;in range of valid numbers?
 bcs fclosex ;invalid
 tax ;use as index, also
 sta fil$num,x
fclosex
 rts

;
;Open a sequential disk file
;Called with:
;  ACC = Access code ('R' or 'W')
;  X,Y = file name string address
;Returns:
;  ACC = 0 => failure
;  ACC <>0 => file number

 .def open$seq
open$seq
 pha ;access code to stack
 lda #'s ;sequential file type
open1
 pha ;filetype to stack
 stx string$2 ;set up for copy
 sty string$2+1 
 ldx #<fname
 stx string$1
 stx fnadr ;put it in zero page, also
 ldx #>fname
 stx string$1+1
 stx fnadr+1
 jsr strcpy ;copy to temp area

 ldx fnadr ;compute current length
 ldy fnadr+1
 jsr strlen ;get current name length
 tay ;Y = length
 lda #', ;comma
 sta (fnadr),y
 iny
 pla ;retrieve file type code
 sta (fnadr),y
 iny
 lda #', ;another comma
 sta (fnadr),y
 iny
 pla ;retrieve access code
 sta (fnadr),y
 iny
 sty fnlen ;save new name length
 jsr getfnbr ;get file number
 sta dfn ;save file number
 beq openok ;failed if zero
 ldx disk$dvc ;device number
 tay ;secondary address same as file number
 jsr setlfs
 jsr open ;attempt to open the file
 jsr ckdisk
 bne openfail
openok
 lda dfn ;return file number
 rts

openfail
 lda dfn
 jsr fclose ;release file number
 lda #0 ;failure code
 rts

;**************************************
;Open a program file.  Parameters are
;the same as 'open$seq'.
;
 .def open$prg

open$prg
 pha ;save access code on stack
 lda #'p
 jmp open1 ;share code above
;
;**************************************
;Open a disk command channel.
;Called with:
;  disk$dvc set to device number
;Returns:
;  file number or zero
;
disk$init .byte "i0" ;initialize disk

 .def open$cmd
open$cmd
 jsr getfnbr ;allocate file number
 sta dfn
 beq openfail ;share fail exit above
 ldx disk$dvc ;device number to X
 ldy #15 ;secondary always 15
 jsr setlfs
 
 lda #2 ;filename length ('i0')
 ldx #<disk$init ;'filename' is initialize command
 ldy #>disk$init
 jsr setnam

 jsr open

;Store command channel file number in table

 lda disk$dvc ;get device number
 and #3 ;lower 2 bits (0-3)
 tax
 lda dfn
 sta disk$cmd,x
 jsr ckdisk
 beq openok ;normal exit
 jmp openfail ;failure exit

;
;Open a disk directory
;Called with:
;  device number in disk#dvc
;  file name specification in X,Y
;    if null, must point to zero byte
;Returns:
;  status in ACC
;Note:
;  file number used is always 1

 .def open$dir
open$dir
 stx string$2 ;prepare for copy
 sty string$2+1
 ldx #<fname
 stx string$1
 stx fnadr
 ldx #>fname
 stx string$1+1
 stx fnadr+1
 lda #'$ ;precede spec with dollar sign
 sta fname
 lda #0 ;null terminator
 sta fname+1
 jsr strcat ;concatenate strings
 ldx #<fname ;get final length
 ldy #>fname
 jsr strlen
 sta fnlen

 jsr getfnbr ;get file number
 sta dfn
 beq opendirf ;no file numbers?
opendir1
 ldx disk$dvc ;device number
 ldy #0 ;secondary address
 jsr setlfs
 jsr open
 jsr ckdisk
 bne opendirf
 jmp openok ;success exit
opendirf
 jmp openfail ;failure exit
 

;Check disk status
;Called with:
;  disk$dvc = device number
;Returns:
;  status code in A, condition code set
;  to 'equal' if good status
;
;Assumes:
;  Disk command channel file numbers are
;  current in disk$cmd table.

 .def ckdisk
ckdisk
 jsr gdk$ccf ;get cmd chan fn
 jsr chkin ;select as input channel
 lda #<disk$status
 sta ptr1
 lda #>disk$status
 sta ptr1+1
 ldy #0
ckdisk1
 jsr getin ;get status message char
 cmp #13 ;carriage return?
 beq ckdisk2
 sta (ptr1),y
 iny
 lda status ;end of input?
 beq ckdisk1
ckdisk2
 lda #0 ;store null at end of string
 sta (ptr1),y
 jsr clrchn
 ldx #<disk$status
 ldy #>disk$status
 jsr atoi ;convert ascii to integer
 txa ;return low byte
 pha
 jsr clrchn
 pla
 rts 

;
;Check file's existence
;Called with:
;  device number in disk$dvc
;  Filename in X,Y
;Returns
;  Type code ('s','p','r','u') in ACC
;  or zero if no such file.

 .def ckfile
ckfile
 jsr open$dir
 sta dfn
 bne ckfile1
 ldx #<disk$status ;report status
 ldx #>disk$status
 jsr errmsg

ckfilef ;failure exit
 jmp openfail ;take common failure exit
 rts

ckfile1
 lda dfn
 jsr chkin
 jsr getin ;discard load address
 jsr getin ;(two bytes)
 lda #0
 sta filcnt
ckfile2
 jsr getdir
 bne ckfilef ;bad status - abort
 inc filcnt
 lda filcnt
 cmp #2 ;second entry?
 bne ckfile2
 lda dfn ;close directory
 jsr fclose
 lda disk$ftyp ;return filetype
 rts

;
;Get one directory entry
;Called with:
;  dfn = directory file number
;Returns:
;  status code

 .def getdir
getdir
 ldx dfn
 jsr chkin
 jsr getin ;1st 2 bytes are size
 sta disk$blks
 jsr getin
 sta disk$blks+1
 lda #0
 sta fnlen
 lda #<disk$fnam
 sta fnadr
 lda #>disk$fnam
 sta fnadr+1

getdir0 ;skip up to, including 1st quote
 jsr getin
 cmp #'"
 beq getdir1
 lda status ;end of file?
 beq getdir0
 bne getdirf

getdir1
 jsr getin ;read to last double quote
 cmp #'" ;double quote?
 beq getdir2
 ldy fnlen
 sta (fnadr),y ;append to filename
 inc fnlen
 lda status
 beq getdir1

getdirf
 rts ;failure exit

getdir2
 ldy fnlen ;terminate filename with null
 lda #0
 sta (fnadr),y
 sta fnlen ;prepare file type string
 lda #<disk$ftyp
 sta fnadr
 lda #>disk$ftyp
 sta fnadr+1 

getdir3
 jsr getin ;skip spaces
 and #$7f ;discard high order bit
 cmp #$20 ;space?
 beq getdir3

getdir4
 ldy fnlen
 cpy #3 ;longer than expected?
 beq getdir5
 sta (fnadr),y
 inc fnlen

getdir5
 jsr getin ;read up to null
 cmp #0
 bne getdir4
 jsr clrchn
 lda status ;should be zero, but be honest?
 rts


;Scratch a file
scrcmd .byte "s0:",0
scrnam .word 0

 .def scratch
scratch
 stx scrnam
 sty scrnam+1

 lda #<fname ;prepare destination
 sta string$1
 lda #>fname
 sta string$1+1

 lda #<scrcmd ;prepare source
 sta string$2
 lda #>scrcmd
 sta string$2+1
 jsr strcpy

 lda scrnam
 sta string$2
 lda scrnam+1
 sta string$2+1
 jsr strcat

 jsr gdk$ccf ;get cmd chan fn
 jsr chkout
 ldx #<fname
 ldy #>fname
 jsr println ;print scratch command
 jsr clrchn
 rts

;
;Block read from disk
;Called with:
;  ACC  = file number
;  PTR1 = data address
;  X,Y  = number of bytes wanted
;Returns:
;  ACC  = status
;  X,Y  = actual number of bytes read

 .def bkrd
bkrd
 stx wanted
 sty wanted+1
 sta dfn
 tax
 jsr chkin
 lda #0 ;reset read count
 sta actual
 sta actual+1
bkrd1
 lda wanted ;more to read?
 ora wanted+1
 beq bkrdx ;no
 dec wanted ;wanted = wanted-1
 lda wanted
 cmp #$ff
 bne bkrd2
 dec wanted+1
bkrd2
 jsr getin
 ldy #0
 sta (ptr1),y
 jsr readst
 bne bkrdx
 inc ptr1 ;address = address+1
 bne bkrd3
 inc ptr1+1
bkrd3
 inc actual ;actual = actual+1
 bne bkrd4
 inc actual+1
bkrd4
 bne bkrd1 ;shouldn't wrap through 0
bkrdx
 pha ;save status
 jsr clrchn ;reset i/o channels
 ldx actual ;return actual number of
 ldy actual+1 ;bytes read in X,Y
 pla ;status in ACC
 rts

;
;Block write to file
;Called with:
;  ACC  = file number
;  PTR1 = data address
;  X,Y  = number of bytes to write
;Returns:
;  ACC  = status
;  Carry
;    set   = error
;    clear = ok

 .def bkwt
bkwt
 stx wanted
 sty wanted+1
 sta dfn
 tax
 jsr chkout
 lda #0
 sta status

bkwt1
 jsr readst ;end of file (or error)?
 beq bkwt10
 pha
 jsr clrchn
 pla
 sec ;error exit
 rts

bkwt10
 lda wanted ;more to read?
 ora wanted+1
 beq bkwtx ;no
 dec wanted ;wanted = wanted-1
 lda wanted
 cmp #$ff ;transitioned negative?
 bne bkwt2
 dec wanted+1

bkwt2
 ldy #0
 lda (ptr1),y
 jsr chrout
 inc ptr1 ;address = address+1
 bne bkwt3
 inc ptr1+1

bkwt3
 bne bkwt1 ;shouldn't wrap through 0

bkwtx
 jsr clrchn ;reset i/o channels
 clc
 lda #0
 rts 
SHAR_EOF
fi # end of overwriting check
if test -f 'imath.a'
then
	echo shar: will not over-write existing file "'imath.a'"
else
cat << \SHAR_EOF > 'imath.a'
;
; Integer Math Routines
; Filename: imath.a
;
imath$ptr = 251 ;page zero pointer


 .def imath$val
imath$val .word 0 ;working value

dgbuf .bss 7 ;digit buffer
dgcnt .byte 0 ;digit count
index .byte 0 ;index
mod .word 0 ;remainder
sign .byte 0 ;sign flag
str$addr .word 0 ;string parameter address
;
; binary to decimal ascii
;entry:
;   imath$val = value to convert
;   X,Y = address of output string
; exit:
;   null terminated string
;
 .def itoa
itoa
 ;save parameters
 stx imath$ptr
 sty imath$ptr+1
 lda imath$val+1
 sta sign ;save msb in sign
 bpl itoa1 ;positive?
 lda #0 ;get absolute value
 sec
 sbc imath$val
 sta imath$val
 lda #0
 sbc imath$val+1
 sta imath$val+1
itoa1
;
 lda #0
 sta dgcnt
;
;convert value to string
itoa2
 ;imath$val := imath$val div 10
 ;mod := imath$val mod 10
 lda #0
 sta mod
 sta mod+1
 ldx #16
 clc
itoa3
 rol imath$val ;shift carry to dvdnd bit 0
 rol imath$val+1 ;which will be quotient
 rol mod ;and shift dividend at same time
 rol mod+1
;
;a,y = dividend,divisor
 sec
 lda mod
 sbc #10
 tay ;save lo byte in y
 lda mod+1
 sbc #0 ;subtract carry
 bcc itoa4 ;dividend < divisor?
 sty mod ;no
 sta mod+1 ; next bit of quot. is 1,
 ; dividend := dividend-quotient
;
itoa4
 dex
 bne itoa3
;
 rol imath$val ;shift in last carry
 rol imath$val+1

;
itoa5 ;store the new digit
 lda mod
 clc
 adc #'0 ;make it ascii
 jsr putdgt
;
;if imath$val <> 0 then continue
 lda imath$val
 ora imath$val+1
 bne itoa2 ;imath$val <> 0?
;
 lda sign
 bpl itoa6
 lda #'- ;minus sign
 jsr putdgt
;
itoa6 ;copy digit buffer to string
 ldx dgcnt
 ldy #0
;
itoa7
 dex
 bmi itoa$exit ;no more digits?
 lda dgbuf,x ;get next digit
 sta (imath$ptr),y
 iny
 bne itoa7
;
itoa$exit
 lda #0 ;terminate with a null
 sta (imath$ptr),y
 rts
;
;put the character in A into the digit
;buffer
;
putdgt
 ldx dgcnt
 sta dgbuf,x
 inc dgcnt
 rts
;
;
;decimal ascii to binary integer
;entry:
;  X,Y = string address
;exit:
;  X,Y = value
;
 .def atoi
atoi
 stx imath$ptr ;store string address
 sty imath$ptr+1 ;in zero page pointer

 lda #0
 sta imath$val
 sta imath$val+1
 sta sign

 ldy #0
atoi$0 ;skip leading blanks
 lda (imath$ptr),y
 beq atoi$done ;end of string?
 cmp #$20 ;space?
 bne atoi$01
 iny
 bne atoi$0
atoi$01
 sty index ;save starting point
;
atoi$1
 ldy index
 lda (imath$ptr),y
 cmp #'- ;minus?
 bne atoi$plus
 lda #$ff
 sta sign
 inc index
 jmp atoi$cvt

atoi$plus
 cmp #'+
 bne atoi$chk
 inc index

atoi$cvt
 ldy index
 lda (imath$ptr),y ;next char
 beq atoi$done ;end of string?

atoi$chk
 cmp #'0
 bmi atoi$done ;terminate on non-digit
 cmp #'9 + 1
 bpl atoi$done
 pha ;save digit on stack
;
;imath$val:=imath$val*10
; = imath$val * (8+2)
; = (imath$val*8)+(imath$val*2)
;
 asl imath$val
 rol imath$val+1
 lda imath$val
 ldy imath$val+1
 asl imath$val
 rol imath$val+1
 asl imath$val
 rol imath$val+1
 clc
 adc imath$val ;add *8 to *2
 sta imath$val
 tya
 adc imath$val+1
 sta imath$val+1
 pla ;add next digit
 sec
 sbc #'0
 clc
 adc imath$val
 sta imath$val
 bcc atoi1
 inc imath$val+1

atoi1
 inc index
 bne atoi$cvt

atoi$done
 lda sign
 bpl atoi$exit
 lda #0
 sec
 sbc imath$val
 sta imath$val
 lda #0
 sbc imath$val+1
 sta imath$val+1
;
atoi$exit
 ldx imath$val
 ldy imath$val+1
 rts


;
;Integer divide
;Called with:
; ACC = divisor
; X,Y = dividend
;Returns:
; ACC = remainder
; X = lsb of quotient
; Y = msb of quotient (always 0)

dvdnd .word 0 ;dividend
dvsr .byte 0 ;divisor
dvq .word 0 ;quotient

 .def idiv
idiv
 sta dvsr
 stx dvdnd
 sty dvdnd+1
 ldx #16 ;number of bits in divisor
 lda #0 ;start with lsb's
 sta dvq
 sta dvq+1 ;zero upper quotient
 sta dvdnd+2
idiv1
 asl dvq ;quot. * 2
 rol dvq+1
 asl dvdnd ;dividend, quot. left 1
 rol dvdnd+1
 rol a
 cmp dvsr ;can divisor be subtracted?
 bcc idiv2 ;no, do next step
 sbc dvsr ;subtract divisor
 inc dvq ;increment quotient
idiv2
 dex ;handle all 16 bits
 bne idiv1
;
;ACC = remainder
 ldx dvq
 ldy dvq+1
 rts
;
;Integer multiply
;8 bits * 8 bits = 16 bits
;Called with:
; a = multiplier
; x = multiplicand
;outputs:
; x = lsb's of product
; y = msb's of product
;
mpyr .byte 0 ;multiplier
mpcnd .byte 0 ;multiplicand
prod .word 0 ;product

 .def imul
imul
 sta mpyr
 stx mpcnd
 lda #0 ;lsb's of product=0
 sta prod ;msb's of product=0
 ldx #8 ;number of bits in multiplier
imul1
 asl a ;product left 1 bit
 rol prod+1
 asl mpyr ;multiplier left
 bcc imul2 ;no add if bit 0
 clc ;add mpcnd product
 adc mpcnd
 bcc imul2
 inc prod+1
imul2
 dex ;loop thru all 8 bits
 bne imul1
 tax ;X = lsb's of product
 ldy prod+1 ;Y = msb's of product
 rts
SHAR_EOF
fi # end of overwriting check
if test -f 'kernal.i'
then
	echo shar: will not over-write existing file "'kernal.i'"
else
cat << \SHAR_EOF > 'kernal.i'
;
;KERNAL ROM Routine Entry Points
;Filename: kernal.i
;History:
; 08/27/86 - Made listen,talk,unlsn,etc. available

acptr = $ffa5 ;get byte from serial port
chkin = $ffc6 ;open channel for input
chkout = $ffc9 ;open channel for output
chrin = $ffcf ;input character from channel
chrout = $ffd2 ;output char to channel
ciout = $ffa8 ;output byte to serial bus
clall = $ffe7 ;close all channels
close = $ffc3 ;close logical file
clrchn = $ffcc ;close input/output channels
eraseln = $e9ff ;erase screen line in X 
getin = $ffe4 ;get kb chr
ioinit = $ff84 ;init. i/o
listen = $ffb1 ;
open = $ffc0 ;open logical file
plot = $fff0 ;read/set cursor
rdtim = $ffde ;read jiffy clock
readst = $ffb7 ;read status word
second = $ff93 ;send secondary address
setlfs = $ffba ;set log. 1st, 2nd addr.
setnam = $ffbd ;set file name
stop = $ffe1 ;stop key pressed?
talk = $ffb4 ;command dvc to talk
tksa = $ff96 ;send 2nd addr after talk
unlsn = $ffae
untlk = $ffab
SHAR_EOF
fi # end of overwriting check
if test -f 'lib1.fo'
then
	echo shar: will not over-write existing file "'lib1.fo'"
else
cat << \SHAR_EOF > 'lib1.fo'
.in10
.rm70
.sp10
.ce 13
C-ASSM-LIB

Software Support Library

for the

C-ASSM Assembler

by

Mark R. Rinfret

06/18/86
.he /C-ASSM-LIB/C-ASSM Library/Introduction/
.bp
.ju1
.fo //Page 1-#//
Introduction
.sp1
.ti +5
This document describes a collection of
source files that constitute a library
of support data and routines for programs
written using the C-ASSM assembler.  C-ASSM
was developed for use with the Pro-Line C-Power (tm)
development system on the Commodore 64.
I am contributing this collection to the
public domain.  Use them, at your own risk,
for any legal purpose, including 
profit-making activities.  You are free
to make any changes you wish and to 
redistribute the source and/or object.


.sp2
.ti +5
The C-ASSM assembler is written in the
C-Power dialect of the C language and
runs under the C-Power Shell.  It generates
relocatable object modules which are
compatible with the C-Power linker.  The
combination of the shell, editor, linker
and other tools (supplied by Pro-Line or
created by the user) provides a powerful
development facility on the C64.
.sp2
.ti +5
This document describes a collection of
files which can be used as building
blocks in the creation of stand-alone
programs developed in the C-Power
environment with C-ASSM.  There are
two basic categories of files: 
.sp1
.in +7
.ti -2
- include files, which typically define
system-wide constants such as hardware-dependent
memory locations, and
.sp2
.ti -2
- source files, which contain a collection of
one or more interrelated routines associated
with performing a particular class of service.
.sp2
.in -5
.he /C-ASSM-LIB/C-ASSM Library/Design Strategy/
Design Strategy
.sp1
.ti +5
The two most important design goals for
this library were that the routines be as
compact as possible without sacrificing
modularity.  Where possible, code commonality
was taken advantage of.  If a routine could
perform several slightly different functions
via multiple entry points, that approach was
taken.  Intermodule dependence was avoided,
but not ruled out.  Many of the modules rely
on the screen/terminal handlers for
support (error messages, etc.).  Some of
this could be eliminated by making the
application responsible for the generation
of all terminal input/output requests.
.sp2
.ti +5
No conscious attempt was made to make these
routines compatible with C-Power C language
programs.  One of the motivations for writing
these routines was to overcome the large code
size caused by the stack and parameter-passing
conventions employed by C-Power.  This is not
a slur against the compiler, which is a fine
product.  The 6502 architecture does not lend
itself well to high level language
generalities.  With a hardware stack of only
256 bytes, a software stack implementation is
inevitable but costly.  I have discovered,
however, that modeling a program in C, then
converting it to assembly language, is a very
orderly and simple development approach.  Sure,
you write the program twice, but writing the
assembly language version while reading a C
language listing makes the job SO much easier!
.sp2
.he /C-ASSM-LIB/C-ASSM Library/Organization/
Organization
.sp1
.ti +5
The routines in this library are collected
into small modules.  Each module provides
a set of services, reasonably well described
by the source module name.  As you would
expect, the module STRING.A performs
string-related functions, while the
module SCREEN.A does screen-related
operations.
.sp2
.ti +5
There were several tradeoffs to be made
in determining how to organize the
various library modules.  If everything
were in one big file, it probably wouldn't
fit in the editor, and if you wrote an
application which used only a few of the
routines, you'd still end up linking them
all in, resulting in excess program size.
On the other hand, if each routine were
to be placed in a separate file, your
application would never link with any
more than was necessary, but the 
configuration management required for
such a great number of files would be
enormous (especially for a part-time
hacker). Though the current organization
is certainly not optimal for all applications,
it is reasonably manageable. 
.sp2
.he /C-ASSM-LIB/C-ASSM Library/Parameter Passing/
Parameter Passing
.sp1
.ti +5
In order for a routine to achieve some
degree of generality, it must be able
to accept and return parameters.  For
instance, a general routine which 
prints a line of text to the screen
should be flexible enough print ANY
line of text, not just one at a specific
location.  By writing the routine such
that we can pass the address of any 
string to it, it thus becomes a general-purpose
workhorse, ready to do our bidding and
saving us many lines of redundant code.
.sp2
.ti +5
Parameters can be passed in several ways.
They can be 'pushed' onto the stack by the
caller and 'popped' off by the callee.
They can be moved to a 'global' or 'local'
area of memory.  They can also be passed
in the 6502's limited register set.  The
design of these routines incorporates a
mix of the last two methods.  The 'push and pop'
method was not used, primarily because of its
complexity and propensity for error.
It does have its advantages
when passing more data than will fit in
the register set, since parameter memory
need not be set aside and memory conflicts
are less likely to arise when subroutine
calls become nested.
.sp2
.ti +5
This begins a discussion of the actual
conventions (or rules) employed for
parameter passing.  An honest attempt
was made to be consistent, but you may
discover a few departures from what's
layed down here.  Always refer to the
individual routine synopses (later in this
document) to be sure what is required or
returned by a given routine.
.sp2
.ti +5
When more data is passed to a routine than
will fit in the C64's registers, designated
memory locations are used to hold these
parameters.  Often, special zero-page
locations, PTR1, PTR2, PTR3 (defined in
include file MEM.I) are used.  Other
times, externally defined parameter
locations in a given source module are
used.
.sp2
.ti +5
When a word value (2 bytes) is passed to
a routine, it is always passed in either the
X and Y registers or via a designated
memory location.  The X register
contains the least significant byte and
the Y register contains the most significant
byte.  Remember that on the C64, the most
significant byte is stored at the higher
memory location, also.  The values
passed via X and Y are either addresses
or 16 bit integer values.  Single byte
values are always passed via the ACC (accumulator)
register.  When routines require two (2)
word values to be passed, and one of
the parameters is an address, the
address is passed in the X and Y registers.
The other word is placed in a designated
memory location.  An example of this is
the routine ITOA (integer to ASCII).
The integer value is stored in a parameter
named IMATH$VAL.  The string address is
passed in X and Y.  In instances where
two address values are required, two
designated parameters may be used or
X and Y may be used in conjunction with
one.
.sp2
.ti +5
Another resource for parameter passing
that is often overlooked is the status
register.  There are several flag bits
in the status register (carry, minus,
zero, overflow) which can be manipulated
to pass/return certain information.
The status register is used often by
these routines to return information
usually associated with a boolean
condition (true/false).  Upon return
from the called routine, the caller
need only perform the appropriate
conditional branch (bcc, bne, beq, etc.)
to effect a decision.
.sp2
.he /C-ASSM-LIB/C-ASSM Library/Include Files/
Include Files
.sp1
.ti +5
The following list of include files
is currently used by C-ASSM-LIB:
.sp1
.in +15
.ju0
.nf
.ti -10
char.i    - names commonly used character codes
.sp1
.ti -10
kernal.i  - KERNAL ROM entry points
.sp1
.ti -10
mem.i     - Commodore defined memory locations
.sp2
.in -15
.fi
.ju1
.he /C-ASSM-LIB/C-ASSM Library/Source Files/
Source Files
.sp1
.ti +5
The following set of source files
currently defines all of the C-ASSM-LIB
routines:
.sp1
.in +15
.ju0
.ti -10
array.a   - This module performs memory fill
and block move services.
.sp1
.ti -10
clock.a   - This module provides timing and
time of day services.
.sp1
.ti -10
disk.a    - This module provides disk (1541) and file
access support.  A primitive file number
management scheme frees the user from
micro-managing the allocation/deallocation
of file numbers.  Support is provided for
devices 8 - 11.  There are several externally
defined variables that the user should be
aware of.  The first, disk$dvc, contains
the device number (8 - 11) of the disk
currently being accessed.  It's default
value is 8, and must be changed by the
application to access another device;
fil$num is a 10 byte array used for the
allocation of file numbers.  Each element
of this array (except 0 and 1) is initially
set to its position number (i.e. position 2 = 2).
When a file number is allocated, the
element is set to zero.  File numbers
may be 'protected' by initializing
their respective elements to zero.
Secondary addresses are assigned the
same value as the file number (except for
the disk command channel).  For this
reason, file numbers 0 and 1 are not used
since they have special uses in the 1541
disk drive.
.sp1
.ti -10
imath.a   - This module provides services
related to integer math, such as multiplication,
division and string numeric conversions.
.sp1
.ti -10
menu.a    - This module provides a generalized
menu routine.
.sp1
.ti -10
screen.a  - This module provides screen
management services.  Actually, it is
very closely tied to the module termio.a.
The borders between these two modules are
not currently well defined.
.sp1
.ti -10
sid.a     - This module provides sound
effect routines and provides access to
the sid (sound interface device) chip
in the C64.
.sp1
.ti -10
termio.a  - This module provides terminal
input/output services.
.sp1
punter.a  - This is a modified version of
the public domain Punter file transfer
protocol.
.sp1
.ti -10
startup.a - This module provides a BASIC
compatible startup sequence, allowing you
to load and run your C-ASSM application as
you would a BASIC program.  It simulates
a BASIC SYS statement and jumps to an
externally defined label, start, which
you define in your application main module.
.sp1
.ti -10
string.a  - This module provides string
manipulation services.
.sp2
.in -15
.ju1
.bp
SHAR_EOF
fi # end of overwriting check
if test -f 'lib2.fo'
then
	echo shar: will not over-write existing file "'lib2.fo'"
else
cat << \SHAR_EOF > 'lib2.fo'
.in10
.rm70
.he /C-ASSM-LIB/C-ASSM Library/Routines/
.bp 1
.fo //Page 2-#//
.ti +5
The remainder of this document describes the
behavior and parameter requirements of each
of the C-ASSM-LIB routines.  All routines
are listed alphabetically and are not
organized by module.  In the following
descriptions, "X,Y" refers to the X and
Y registers as a pair, with X holding the
least significant byte of a 16 bit value.
ACC represents the accumulator.  If a flag
in the status register is described as being
'live', it means that you can perform a
conditional branch based on that flag's
value without having to do a compare
operation first.  For instance, if the
zero flag is declared live on return,
a BNE or BEQ instruction could be used
with reliable results.  All references to
strings refer to a sequence of bytes
terminated by a null (zero).
.sp2
.ti +5
Each of the descriptions is very terse but
should illustrate clearly how the routine
is used.  Following each routine name is the
defining source module, in parentheses.
Following that, you will see a symbolic
representation of the actual instructions
required to set up for the call and a
textual description of the return values.
.sp1
.ti +5
IT IS IMPORTANT that you understand the
notation used in this document.  First off,
all external symbols (declared with '.def')
and constants (defined with '=') are
printed in upper case.  This is for
purposes of highlighting only.  The
C-ASSM assembler is case-sensitive and
all of these names are actually defined
in lower case.  In the assembly language
examples for calling each routine, you
will notice some names or expressions in
square brackets [].  These names should
not be used literally - you plug in the
appropriate name or expression, as
defined in your application.  Pre-defined
names are either defined in the include
files previously mentioned, or in the
module that uses them.  For instance,
the name DISK$DVC is defined in
source module "disk.a".  Where you see
references similar to [string lo], [string hi],
the document is referring to the least
significant byte and the most significant
byte, respectively, of some variable.
Remember the C-ASSM construct for loading
16 bit constants into registers:
.in +5
.nf
.sp1
ldx #<string = [string lo]
ldy #>string = [string hi]
.fi
.sp2
.in +5
.nf
.ju0
.ti -5
ATOI (imath.a) - ascii to integer
.sp1
ldx [string lo]
ldy [string hi]
jsr atoi

X,Y = integer value
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
ATOI converts an ascii string (with
optional sign) to a 16 bit signed value.
.nf
.ju0
.sp2
.ti -5
BELL (sid.a) - bell sound effect
.sp1
jsr bell
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
BELL produces a medium-high-pitched bell
tone.
.nf
.ju0
.sp2

.nf
.ju0
.ti -5
BKRD (disk.a) - read block from file
.sp1
lda [buffer lo]
sta PTR1
lda [buffer hi]
sta PTR1+1
lda [file number]
ldx [count lo]
ldy [count hi]
jsr bkrd

ACC = status
zero flag
X,Y = actual number of bytes read
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
BKRD reads a block of bytes (up to the
specified count)
from ANY file into a buffer.
PTR1 must first be
set up with the address of the buffer area
to receive the data.  The programmer must
exercise caution that there is sufficient
room in this buffer for the number of
bytes requested (X,Y).  It should be
noted that a non-zero status does not
necessarily indicate an error.  If the
ACC is non-zero and X,Y are non-zero,
then end of file or error occurred before
the requested number of files could be
read.
.sp2
.nf
.ju0
.ti -5
BKWT (disk.a) - block write
.sp1
lda [buffer lo]
sta PTR1
lda [buffer hi]
sta PTR1+1
lda [file number]
ldx [count lo]
ldy [count hi]
jsr bkwt

ACC = status
carry clear on zero status, set on non-zero status
zero flag
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
This routine writes a specified number of
bytes to any file.
.nf
.ju0
.sp2
.nf
.ju0
.ti -5
BLKMOV (array.a) - move a block of memory
.sp1
lda [source lo]
sta PTR1
lda [source hi]
sta PTR1
lda [dest lo]
sta PTR2
lda [dest hi]
sta PTR2
ldx [length lo]
ldy [length hi]
jsr blkmov

.sp1
.ti -5
Description:
.fi
.ju1
.sp1
BLKMOV performs a 'smart' and fast move
of a block of memory.  It checks for
overlapping blocks and selects the
correct copy method (hi to lo or lo to hi)
depending upon the source and destination
addresses passed in PTR1 and PTR2.
.nf
.ju0
.sp2
.nf
.ju0
.ti -5
BUZZ (sid.a) - buzzer sound
.sp1
jsr buzz
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
BUZZ generates a raspy buzzer sound and
is appropriate as an error response to
a keyboard input.
.nf
.ju0
.sp2
.ti -5
CENTER (screen.a) - center string on current line
.sp1
ldx [string lo]
ldy [string hi]
jsr center

.sp1
.ti -5
Description:
.fi
.ju1
.sp1
CENTER prints a centered string on the current
cursor row (ROW is defined in mem.i).
To insure that the cursor is at the correct
row, you can first call the kernal PLOT routine:
.nf
.ju0
ldx [row number]
ldy #0
clc
jsr plot (defined in kernal.i)
.sp2
.nf
.ju0
.ti -5
CKFILE (disk.a) - check for file's existence
.sp1
lda [device number]
sta DISK$DVC
ldx [filename lo]
ldy [filename hi]
jsr ckfile

ACC = file type code ('s,'p,'r,'u) or zero
zero flag
DISK$BLKS = block count (2 bytes)
DISK$FNAM = full file name
DISK$FTYP = file type (same as ACC)
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
CKFILE is used to test for a file's
existence without actually trying to open
it.  The filename string in X,Y must not be null.
If it contains a wildcard specification,
the first file matching the specificaton is
selected.
.nf
.ju0
.sp2

.nf
.ju0
.ti -5
CKDISK (disk.a) - check disk status
.sp1
lda [device number]
sta DISK$DVC
jsr ckdisk

ACC = disk status value
zero flag
DISK$STATUS = status message
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
The status of the specified disk is
read into the string DISK$STATUS.  The
binary value of the status code is
returned in the ACC.
.nf
.ju0
.sp2
.ti -5
CRWAIT (screen.a) - wait for RETURN key
.sp1
jsr crwait
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
CRWAIT prints the prompt
.sp1
.ti +5
Press RETURN to continue...
.sp1
and waits until the user presses
the RETURN key (no other) before
returning to the caller.
.nf
.ju0
.sp2
.ti -5
ERASEEOL (screen.a) - erase to end of line
.sp1
ldx [row number]    (0-24)
ldy [column number] (0-39)
jsr eraseeol

.sp1
.ti -5
Description:
.fi
.ju1
.sp1
ERASEEOL erases a full or partial screen
line starting from the given coordinates.
Note that the cursor is repositioned to
the start of the field that was erased.
This eliminates the need to call the
kernal plot routine after a call to
ERASEEOL.
.nf
.ju0
.sp2
.ti -5
ERASELN (kernal.i) - erase one screen line
.sp1
ldx [row number] (0-24)
jsr eraseln

X = row
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
This is actually a kernal routine, but
was included here because it is not
documented in the C64 Programmer's
Reference manual.  The address of this
routine is defined in the include file
"kernal.i".
.nf
.ju0
.sp2
.ti -5
ERRMSG (screen.a) - flash message on line 24, wait for keypress
.sp1
ldx [string lo]
ldy [string hi]
jsr errmsg

ACC = keyboard response
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
ERRMSG flashes a message string on the
bottom line of the screen, also sounding
a gong (see GONG, above) and waiting for
a keyboard acknowledgement.  Any keypress
will allow ERRMSG to return, and that
character code will be returned in the
ACC.  This allows the programmer some
degree of flexibility in error handling.
For example, a simple error message
might read:
.sp1
Disk Error - RETURN=retry F7=ABORT
.sp1
The calling routine can then react to
the choice made by the user.  This
routine is not very aptly named.  It
might be more appropriate to name it
FLASH since informative (non-error)
messages can be displayed this way,
as well.
.nf
.ju0
.sp2
.nf
.ti -5
FCLOSE (disk.a) - Close a file and deallocate its file number.
.sp1
lda [file number]
jsr [fclose]

.sp1
.ti -5
Description:
.sp1
.fi
The file specified by the file number
is closed and the file number is returned
to the list of available file numbers.
.sp2
.nf
.ju0
.ti -5
FLUSH (termio.a) - empty the keyboard queue
.sp1
jsr flush
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
FLUSH discards any characters currently
waiting in the keyboard queue.
.nf
.ju0
.sp2
.nf
.ju0
.ti -5
GETS (termio.a) - get a string from the keyboard
.sp1
lda [max length]
jsr gets

ACC = actual length
BUF (mem.i) = input string
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
GETS gets a string from the keyboard,
providing a flashing cursor and limiting
the string's length to a programmer-specified
maximum.  GETS supresses the input of
certain control characters which would
move the cursor off the current line or
change screen characteristics.  Upon
return, the null-terminated string is
stored in the predefined memory area,
BUF (see mem.i).  If the string is not
to be used immediately after the call,
it should be copied to another area
using STRCPY (string.a).
.nf
.ju0
.sp2
.ti -5
GDK$CCF (disk.a) - Get disk command channel file number.
.sp1
lda [device number]
sta DISK$DVC
jsr gdk$ccf

X = disk command channel file number.
.sp1
.ti -5
Description:
.sp1
.fi
This routine computes the command channel
(secondary address 15) file number for
a disk defined by the external variable
DISK$DVC.  The command channel must have
first been opened with open$cmd.  Note that
the return value is passed in X, rather
than ACC.  This is because it is expected
that a call to GDK$CCF will likely be
followed by a call to the kernal routine,
CHKIN, which requires the file number in
X.
.nf
.sp2
.nf
.ju0
.ti -5
GONG (sid.a) - gong sound effect
.sp1
jsr gong
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
GONG is similar to BELL, except that the
tone is lower.
.nf
.ju0
.sp2
.ti -5
IDIV (imath.a) - unsigned integer divide
.sp1
lda [divisor] (0-255)
ldx [dividend lo]
ldy [dividend hi]
jsr idiv

ACC = remainder
X,Y = quotient
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
IDIV performs 16 bit unsigned division.
.nf
.ju0
.sp2
.ti -5
IMUL (imath.a) - integer multiply
.sp1
lda [multiplier] (0-255)
ldx [multiplicand] (0-255)
jsr imul

X,Y = product
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
IMUL performs 16 bit unsigned multiplication
.nf
.ju0
.sp2
.ti -5
ITOA (imath.a) - integer to ascii string
.sp1
lda [value lo]
sta IMATH$VAL
lda [value hi]
sta IMATH$VAL+1
ldx [string lo]
ldy [string hi]
jsr itoa

.sp1
.ti -5
Description:
.fi
.ju1
.sp1
.nf
ITOA converts a 16 bit signed quantity to
an ascii string.  No special formatting is
provided.
.ju0
.sp2
.nf
.ju0
.ti -5
KBWAIT (termio.a) - wait for keypress
.sp1
jsr kbwait

ACC = response character
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
KBWAIT first flushes the keyboard
character queue, then waits for a
new keypress.  Once a key is pressed,
its character code is returned in the
ACC.
.nf
.ju0
.sp2
.ti -5
MENU (menu.a) - present menu and get selection
.sp1
lda [menu list lo]
sta MENU$LIST
lda [menu list hi]
sta MENU$LIST+1
lda [menu title lo]
sta MENU$TITLE
lda [menu title hi]
sta MENU$TITLE+1
jsr menu

ACC = menu selection index (0..nitems-1)
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
MENU provides a primitive but fairly
general approach to selecting an item
(e.g. a command) from a list of options.
For each menu in an application, the
programmer must define a title string
describing the list of options and a
string array (list of string addresses),
each element of which is the address of
an option string.  The the last element
of this array is zero (2 zero bytes).
This is how MENU determines how many
entries there are.
Upon calling MENU,
the screen is cleared and the menu title
string is centered on row zero.  All menu
options are then displayed.  Only one
option is displayed per line, starting
row 2.  Instructions are printed on
rows 22 through 24.  This means that
menu lists should be limited to 21 items
or less (rows 2 - 20).
.sp1
When the menu is presented, the first
item will be highlighted (reverse video).
The user can select any option in the list
by positioning the highlight bar to the
desired option, then pressing RETURN,
or he can enter the first character of
any option.  For this reason, THE FIRST
CHARACTER OF EACH OPTION STRING MUST BE
UNIQUE.  The index for the selected
menu item is returned in the ACC.
.nf
.ju0
.sp2
.ti -5
MFILL (array.a) - fill a block of memory with a byte value
.sp1
lda [address lo]
sta PTR1
lda [address hi]
sta PTR1+1
lda [length lo]
sta PTR2
lda [length hi]
sta PTR2+1
lda [value]
jsr mfill

.sp1
.ti -5
Description:
.fi
.ju1
.sp1
MFILL stores the value in the ACC throughout
a consecutive area of memory whose starting
address is passed in PTR1 and whose
length is passed in PTR2.
.nf
.ju0
.sp2
.ti -5
NORASTER (screen.a) - disable screen
.sp1
jsr noraster
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
NORASTER is used to blank the screen
display to the border color.  It provides
a little extra horsepower to the CPU,
since the VIC-II chip no longer steals
memory cycles.  Another practical use is
to 'hide' the screen while loading a new
image from an external file.
.nf
.ju0
.sp2
.nf
.ju0
.ti -5
OPEN$CMD (disk.a) - open disk command channel
.sp1
lda [device number] (8-11)
sta DISK$DVC
jsr open$cmd

ACC = file number or zero
zero flag
DISK$STATUS
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
This routine should be called during the
initialization segment of an application
for each disk drive that is to be accessed,
BEFORE any disk files are opened.  Note that
this routine sends an initialize command to
the drive (I0:) which causes the drive to
'forget' about any currently open files,
even though the kernal may think that they
are still open.
.nf
.ju0
.sp2
.nf
.ju0
.ti -5
OPEN$DIR (disk.a) - open a disk directory
.sp1
lda [device number]
sta DISK$DVC
ldx [filespec lo]
ldy [filespec hi]
jsr open$dir

ACC = file number (1) or zero
zero flag
DISK$STATUS
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
This routine opens a disk directory
for read access, according to the 
file specification string in X,Y.  If
no file specification is to be made
(all files selected), X,Y must point
to a byte containing a zero (a null string).
The file specification string should not
contain a dollar sign - just a full or
partial (with wildcard) file name.  This
call may then be followed by calls to GETDIR
to read the individual directory entries.
.nf
.ju0
.sp2

.ti -5
OPEN$PRG (disk.a) - open program (PRG) file.
.sp1
lda [access code] ('r => read, 'w => write).
ldx [filename lo]
ldy [filename hi]
jsr open$prg

ACC = file number or zero
zero flag
DISK$STATUS contains disk status message
.sp1
.ti -5
Description:
.sp1
An attempt is made to open a program file
with either read or write access, depending
upon the access code in the ACC and the
filename string address in X,Y.  A non-zero
file number is returned in the ACC if
successful, zero otherwise.
.sp2
.ti -5
OPEN$SEQ (disk.a) - open a sequential (SEQ) disk file.
.sp1
lda [access code] ('r => read, 'w => write)
ldx [filename lo]
ldy [filename hi]
jsr open$seq

ACC = file number or zero
zero flag
DISK$STATUS
.sp1
.ti -5
Description:
.sp1
.fi
.ju1
An attempt is made to open the sequential
file according to the filename specified
in X,Y and the access code in the ACC.
If successful, a non-zero file number is
returned.  Otherwise, zero is returned.
.sp2
.nf
.ju0
.ti -5
PRINT (termio.a) - print string to screen
.sp1
ldx [string lo]
ldy [string hi]
jsr print
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
PRINT prints the string whose address is
passed in X,Y at the current cursor
position on the screen.
.nf
.ju0
.sp2
.nf
.ju0
.ti -5
PRINTLN (screen.a) - print string with carriage return
.sp1
ldx [string lo]
ldy [string hi]
jsr println
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
PRINTLN behaves like PRINT, except that
a carriage return is printed, forcing
the cursor down one line and over to 
the left margin.
.nf
.ju0
.sp2
.nf
.ju0
.ti -5
RASTER (screen.a) - enable screen display
.sp1
jsr raster
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
RASTER re-enables the screen display and
is normally called after a call to 
NORASTER.
.nf
.ju0
.sp2
.ti -5
RVSOFF (screen.a) - diasable reverse video
.sp1
jsr rvsoff

ACC is unchanged
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
RVSOFF disables reverse video.
.nf
.ju0
.sp2
.ti -5
RVSON (screen.a) - enable reverse video
.sp1
jsr rvson

ACC is unchanged
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
RVSON enables reverse video.
.nf
.ju0
.sp2
.nf
.ju0
.ti -5
SCRATCH (disk.a) - scratch a file or files
.sp1
lda [device number]
sta DISK$DVC
ldx [filename lo]
ldy [filename hi]
jsr scratch

No return value, though there should
at least be a DISK$STATUS.  Call CKDISK
if you need status info.
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
Scratches (deletes) zero or more files,
depending upon the file specification
string passed in X,Y.  No protection is
provided for a specification of "*"
(delete all files), so use with caution.
.sp2
.nf
.ju0
.ti -5
SID$INIT (sid.a) - initialize sid chip
.sp1
jsr sid$init

.sp1
.ti -5
Description:
.fi
.ju1
.sp1
SID$INIT simply sets all Sound Interface Device
locations to zero and then sets the volume
to maximum (15).  It should be called once at
the start of a program.  Note that the user
can very easily disable all sound effects,
without special coding, by
simply storing a zero in the sid volume
control register (55296).
.nf
.ju0
.sp2
.ti -5
SLEEP (clock.a) - sleep a number of seconds
.sp1
lda [seconds] (0-255)
jsr sleep
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
SLEEP suspends execution of a program for
the number of seconds specified.
.nf
.ju0
.sp2
.ti -5
TSLEEP (clock.a) - sleep a number of 'ticks'
.sp1
ldx [ticks lo]
ldy [ticks hi]
jsr tsleep
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
TSLEEP suspends execution of an applicaton for
a duration which is specified in clock
ticks (1/60 second).  It can be used where
medium timing resolution is required for
certain operations, such as pulsing an
auto-dial modem.
.nf
.ju0
.sp2
.ti -5
TYPENUM (screen.a) - type a number to the screen
.sp1
ldx [number lo]
ldy [number hi]
jsr typenum
.sp1
.ti -5
Description:
.fi
.ju1
.sp1
TYPENUM types a signed integer value at
the current cursor location.  No special
formatting is available.
.nf
.ju0
.sp2
.bp
*** template for new entries - cut then paste ***
.ti -5

.sp1

.sp1
.ti -5
Description:
.fi
.ju1
.sp1
.nf
.ju0
.sp2
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0
-- 
| Mark R. Rinfret, SofTech, Inc.		mark@unisec.usi.com |
| Guest of UniSecure Systems, Inc., Newport, RI                     |
| UUCP:  {gatech|mirror|cbosgd|uiucdcs|ihnp4}!rayssd!unisec!mark    |
| work: (401)-849-4174	home: (401)-846-7639                        |

jchikin@polyslo.UUCP (Joe Chikin) (05/22/87)

Hi all,
  this is my first posting so please excuse my awkwardness.  Anyway,
I was wondering what does C-ASSM provide for C-Power?  I have C-Power
but I am somewhat disappointed with it.  I can't seem to perform the
equivalent of basic's  OPEN8,2,1,chr$(6);chr$(0).  I don't remember
if that was what I wanted exactly but that's the general gist. C-Power
doesn't seem to provide the ability to open a file to the modem.
Also, I was disappointed that the left brace and right brace ( {, } )
were not printable (on my printer).  I would have thought that Proline
would have mapped the character set exactly onto normal ASCII or would
catch their own left and right brace characters and substitute the
correct left and right brace characters in. 

If someone would answer my questions concerning C-ASSM and the OPEN
statement, I would be very appreciative.  Just anwer via the netnews.

By the way, can C-ASSM files be linked directly with C-Power files?

Thanks in advance

Chikin Joe
1050 Foothill #200
SLO, Ca 93401