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