mirror of https://github.com/RevCurtisP/C02.git
Updated library modules and documentation
This commit is contained in:
parent
fb9f396240
commit
fc987bb36e
|
@ -0,0 +1,457 @@
|
|||
C02 Design Considerations
|
||||
|
||||
|
||||
Variable Types
|
||||
==============
|
||||
|
||||
Pointers
|
||||
--------
|
||||
|
||||
The 6502 differs from nearly all other microprocessors by not having
|
||||
a 16 bit index register, instead using indirect indexed mode in
|
||||
conjunction with zero page.
|
||||
|
||||
On other processors, it would be trivial to dereference a pointer
|
||||
stored anywhere in memory. For example, on the 6800:
|
||||
|
||||
LDX P ;N = *P
|
||||
LDAA IX
|
||||
|
||||
There is no direct equivalent on the 6502, but by using indirect
|
||||
indexed mode, any zero page variable pair can be used as a pointer:
|
||||
|
||||
LDY #0 ;N = *P
|
||||
LDA (P),Y
|
||||
|
||||
Additionally, accessing elements of a dereferenced zero page pointer
|
||||
is just as trivial:
|
||||
|
||||
LDY I ;N = *P[I]
|
||||
LDA (P),Y
|
||||
|
||||
expr ;N - *P[expr]
|
||||
TAY
|
||||
LDA (P),Y
|
||||
|
||||
However, trying to use a 16-bit value stored outside of zero-page
|
||||
would take extra code and require using a a zero page byte pair:
|
||||
|
||||
LDY P ;N = *P
|
||||
STY ZP
|
||||
LDY P+1
|
||||
STY ZP+1
|
||||
LDY #0
|
||||
LDA (ZP),Y
|
||||
|
||||
This violates two principles of the C02 design philosophy: that
|
||||
each token correspond to one or two machine instructions and
|
||||
that the compiler is completely agnostic of the system configuration.
|
||||
|
||||
Therefore, if pointers are implemented, they will have to be in
|
||||
zero page.
|
||||
|
||||
Implementation:
|
||||
|
||||
Declaration of a pointer should use two bytes of zero page storage,
|
||||
the address of which would be taken from the free zero page space
|
||||
specified by the #pragma zeropage directive.
|
||||
|
||||
P EQU $80 ;char *p
|
||||
Q EQU $82 ;char *q
|
||||
|
||||
Any pointers declared in a header file would added to the variable
|
||||
table but not allocated, so would be defined in the accompanying
|
||||
assembly file:
|
||||
|
||||
char *dst; //stddef.h02
|
||||
char dstlo,dsthi;
|
||||
|
||||
DST EQU $30 ;stddef.a02
|
||||
DSTLO EQU $30
|
||||
DSTHI EQU $31
|
||||
|
||||
Since they are 16-bit values, raw pointers cannot be passed into
|
||||
used directly in expressions. But could be used in standalone
|
||||
assignments:
|
||||
|
||||
LDX Q ;p = q
|
||||
STX P
|
||||
LDY Q+1 ;X is used for LSB and Y as MSB to match
|
||||
STY P+1 ;the address passing convention for functions
|
||||
|
||||
Likewise if a 16-bit integer variable type was added to C02,
|
||||
then one could be assigned to the other using the exact same
|
||||
assembly code.
|
||||
|
||||
A derefenced pointer can be used anywhere an array references
|
||||
is allowed and would be subject to the same restrictions.
|
||||
|
||||
A raw pointer used as an argument to a function will be passed
|
||||
using the same convention as an address:
|
||||
|
||||
LDY P+1 ;func(p)
|
||||
LDX P
|
||||
JSR FUNC
|
||||
|
||||
JSR FUNC ;p = func()
|
||||
STY P+1
|
||||
STX P
|
||||
|
||||
Since pointers are zero page the address of operator on a pointer
|
||||
will generate a char value:
|
||||
|
||||
LDA #P ;&p
|
||||
|
||||
This will allow passing of pointers for use inside of functions
|
||||
using indexed mode:
|
||||
|
||||
LDA #P ;inc(&p)
|
||||
JSR FUNC
|
||||
|
||||
TAX ;void inc()
|
||||
INC ($00,X)
|
||||
RTS
|
||||
|
||||
The memio module makes extensive use of pointer addresses as
|
||||
function arguments.
|
||||
|
||||
Structs
|
||||
-------
|
||||
|
||||
For the declarations
|
||||
|
||||
STRUCT RECORD { CHAR NAME[8]; CHAR INDEX; CHAR DATA[128]; };
|
||||
STRUCT RECORD REC;
|
||||
|
||||
references to the members of the struct REC will generate the code:
|
||||
|
||||
XXA REC+$09 ;REC.INDEX
|
||||
|
||||
LDX I ;REC.DATA[I]
|
||||
XXA REC+$0A,X
|
||||
|
||||
Using the address of operator on a struct member generates assembly
|
||||
code with parentherical expressions, which are not recognized by all
|
||||
assemblers:
|
||||
|
||||
LDY #>(REC+$0A) ;FUNC(&REC.DATA)
|
||||
LDX #<(REC+$0A)
|
||||
JSR FUNC
|
||||
|
||||
The compiler could optimize the generation of code for references
|
||||
to the first member of a struct, producing
|
||||
|
||||
XXA REC ;REC.NAME
|
||||
|
||||
instead of
|
||||
|
||||
XXA REC+$00 ;REC.NAME
|
||||
|
||||
but the machine code produced by the assembler should be indentical
|
||||
in either case.
|
||||
|
||||
|
||||
Expression Evaluation
|
||||
=====================
|
||||
|
||||
Array Indexes
|
||||
-------------
|
||||
|
||||
Array indexing normally uses the X register and indexed addressing mode:
|
||||
|
||||
LDX I ;R[I]
|
||||
XXA R,X
|
||||
|
||||
If the index is a constant or literal, absolute addressing is used:
|
||||
|
||||
LDA R+1 ;R[1]
|
||||
XXA S+0 ;S[0]
|
||||
|
||||
Specifying a register as the index also uses indexed addressing mode:
|
||||
|
||||
TAX ;R[A]
|
||||
XXA R,X
|
||||
XXA R,Y ;R[Y]
|
||||
XXA R,X ;R[X]
|
||||
|
||||
Allowing for an expression as the index in the first term of an
|
||||
expression uses only one extra byte of code and two machine cycles:
|
||||
|
||||
expression ;R[expr]
|
||||
TAX
|
||||
LDAA R,X
|
||||
|
||||
while in any other termm is uses an extra three extra bytes of code
|
||||
and ten machine cycles:
|
||||
|
||||
PHA ;R[expr]
|
||||
expr code ;code to evaluate the expression
|
||||
TAX
|
||||
PLA
|
||||
XXA R,X
|
||||
|
||||
compared to the extra four to six bytes and six to eight machine cycles
|
||||
used by the equivalent C02 code required to achieve the same result:
|
||||
|
||||
expr code ;Z = expr
|
||||
STA Z
|
||||
LDX Z ;R[Z]
|
||||
XXA R,X
|
||||
|
||||
Function Calls
|
||||
--------------
|
||||
|
||||
A function call in the first term of an expression requires additional
|
||||
processing by the compiler, since the accumulator holds the return
|
||||
value upon completion of the function call:
|
||||
|
||||
JSR FUNC ;R = func()
|
||||
STA R
|
||||
|
||||
Allowing a function call in susbsequent terms, however, requires
|
||||
extensive stack manipulation:
|
||||
|
||||
|
||||
|
||||
whereas the equivalent C02 code generates much simpler machine code:
|
||||
|
||||
|
||||
|
||||
Shift Operators
|
||||
----------------
|
||||
|
||||
In standard C, the shift operators use the number of bits to shift as
|
||||
the operand. Since the 6502 shift and rotate instructions only shift
|
||||
one bit at a time, this would require the use of an index register and
|
||||
six to seven bytes of code
|
||||
|
||||
expr code ;expr
|
||||
.LOOP LDY B ;>> B
|
||||
LSR
|
||||
DEY
|
||||
BNE .LOOP
|
||||
|
||||
whereas a library function would require five bytes of code:
|
||||
|
||||
SHIFTR: LSR ;A=Value to Shift
|
||||
DEY ;Y=Bits to Shift
|
||||
BNE SHIFTR
|
||||
RTS
|
||||
|
||||
and each function call would use five bytes of code
|
||||
|
||||
expr code ;shiftr(expr, B)
|
||||
LDY B
|
||||
JSR SHIFTR
|
||||
|
||||
Following the philosophy that a operator should correspond to a single
|
||||
machine instruction, in C02 shifting is implemented as post-operators
|
||||
using the various available addressing modes:
|
||||
|
||||
ASL S ;S<<
|
||||
|
||||
LDX I ;T[I]>>
|
||||
LSR T,X
|
||||
|
||||
ASL ;A<<
|
||||
|
||||
|
||||
Post-Operators and Pre-Operators
|
||||
--------------------------------
|
||||
|
||||
Parsing for post-operators in a standalone expression is trivial, since
|
||||
that is the only time the relevant characters will only follow the operand.
|
||||
|
||||
Implementing pre-operators on standalone expressions would be redundant
|
||||
since their would be no difference in the generated code.
|
||||
|
||||
Parsing for post-operators and/or preoperators within an expression or
|
||||
evaluation, however, would complicate the detection of operators and
|
||||
comparators.
|
||||
|
||||
In addition, the code generated from a post-operator or pre-operator
|
||||
withing an expression:
|
||||
|
||||
DEC I ;R[--I]
|
||||
LDX I
|
||||
XXA R,X
|
||||
|
||||
LDX I ;R[I++]
|
||||
XXA R,X
|
||||
INC I
|
||||
|
||||
Is indentical to the code generated when using a standalone post-operator;
|
||||
|
||||
DEC I ;I--
|
||||
LDX I ;R[I]
|
||||
XXA R,X
|
||||
|
||||
LDX I ;R[I]
|
||||
XXA R,X
|
||||
INC I ;I++
|
||||
|
||||
Assignments
|
||||
===========
|
||||
|
||||
Assignment to a variable generates an STA instruction, using either absolute
|
||||
or indexed addressing mode:
|
||||
|
||||
expr code ;R = expr
|
||||
STA R
|
||||
|
||||
expr code ;R[2] = expr
|
||||
STA R+2
|
||||
|
||||
expr code ;R[I] = expr
|
||||
LDX I
|
||||
STA R,I
|
||||
|
||||
while assignment to an index register generates a transfer instruction:
|
||||
|
||||
expr code ;Y = expr
|
||||
TAY
|
||||
|
||||
expr code ;X = expr
|
||||
TAX
|
||||
|
||||
and assignment to the Accumulator is simply a syntactical convenience:
|
||||
|
||||
expr code ;A = expr
|
||||
|
||||
Specific to C02 is the implied assignment, which also generates an STA:
|
||||
|
||||
STA S ;S
|
||||
|
||||
Allowing an expression as an array index in an assignment is problematic
|
||||
on an NMOS 6502 since the index expression will be evaluated prior to the
|
||||
expression being assigned to the array element and neither index register
|
||||
may be directly pushed or pulled from the stack.
|
||||
|
||||
The addition of the PLX instruction to the 65C02 would allows this to be
|
||||
done using only two extra bytes of code for each variable assignment:
|
||||
|
||||
indexp oode ;R[indexp] = expr
|
||||
PHA
|
||||
expr code
|
||||
PLX
|
||||
STA R,X
|
||||
|
||||
expr oode ;R[expr], S[exps] = func()
|
||||
PHA
|
||||
exps code
|
||||
PHA
|
||||
JSR FUNC
|
||||
PLX
|
||||
STY S,X
|
||||
PLX
|
||||
STA R,X
|
||||
|
||||
however, this would only work with the A and Y variables of a plural
|
||||
assignment.
|
||||
|
||||
A workaround for the NMOS 6502 would require an extra five bytes of code
|
||||
|
||||
indexp oode ;R[indexp] = expr
|
||||
PHA
|
||||
expr code
|
||||
TAY
|
||||
PLA
|
||||
TAX
|
||||
TYA
|
||||
STA R,X
|
||||
|
||||
and the use of the Y register would limit it to the only the A variable
|
||||
of a plural assigment, whereas the equivalent C02 code would use an
|
||||
extra four to six bytes of code
|
||||
|
||||
indexp code ;I = indexp;
|
||||
STA I
|
||||
expr code ;R[I] = expr
|
||||
LDX I
|
||||
STA R,X
|
||||
|
||||
and works with all three variables of a plural assignment.
|
||||
|
||||
Conditionals
|
||||
============
|
||||
|
||||
Conditionals are separate and distinct from expessions, due to the fact
|
||||
that the comparison operators all set status flags which affect the various
|
||||
branch instructions:
|
||||
|
||||
CMP DATA Normal Inverted
|
||||
Reg < Data BCC BCS
|
||||
Reg = Data BEQ BNE
|
||||
Reg ≥ Data BCS BCC
|
||||
Reg ≠ Data BNE BEQ
|
||||
|
||||
CLC:SBC DATA Normal Inverted
|
||||
Reg ≤ Data BCC BCS
|
||||
Reg > Data BCS BCC
|
||||
|
||||
When compiling a comparison, the generated code will usually, but not
|
||||
always, branch when the condition is false, skipping to the end of the
|
||||
block of code following the comparison. In addition, the logical not
|
||||
operator will invert the comparison.
|
||||
|
||||
By arranging the eight standard comparisons, along with evaluation of
|
||||
a term as true when non-zero, in this order:
|
||||
|
||||
0 1 2 3 4 5 6 7
|
||||
!0 = < ≤ ≥ > ≠ 0
|
||||
|
||||
the comparison can be inverted with a simple exclusive-or. For this
|
||||
reason, The ! operator is logical rather than bitwise and affects
|
||||
the result of the comparison rather than an individual expression
|
||||
or term within the expression.
|
||||
|
||||
Standalone Expressions
|
||||
----------------------
|
||||
|
||||
Flags Operators
|
||||
---------------
|
||||
|
||||
Logical Operators
|
||||
-----------------
|
||||
|
||||
Parsing the logical operators && and || is trivial if the preceding
|
||||
condition is a comparison or flag operation, since any expression
|
||||
evaluation is complete before the parse encounters the initial & or |
|
||||
character. For a standalone evaluation of an expression as true or\
|
||||
false, however, the expression evaluator will mistake the initial
|
||||
character of the && or || as a bitwise operator. Differentiating
|
||||
the two would require changing to a look-ahead parser.
|
||||
|
||||
One solution is to enclose require parenthises around each comparison
|
||||
when using logical operators, which is allowable in C syntax, but
|
||||
it's just as easy, and arguably cleaner looking, to use the words
|
||||
"and" and "or" instead. This is be allowble in standard C by using
|
||||
the @define directive to alias "and" to "&&" and "or" to "||".
|
||||
|
||||
The most efficient way to implement logical operators is to use shortcut
|
||||
evaluations.
|
||||
|
||||
Under the normal circumstances, where the generated code branches when
|
||||
the condition is false, && can be implemented by evaluation the next
|
||||
comparison only in the event of the first condition being true.
|
||||
|
||||
For ||, however, the following comparison will be evaluated only if the
|
||||
first comparison was false.
|
||||
|
||||
LDA I ;IF (I<J
|
||||
CMP J
|
||||
BCS ENDIF
|
||||
LDA M ;&& M<>N)
|
||||
CMP N
|
||||
BEQ ENDIF
|
||||
|
||||
LDA I ;IF (I<J
|
||||
CMP J
|
||||
BCC block
|
||||
LDA M ;|| M<>N)
|
||||
CMP N
|
||||
BEQ ENDIF
|
||||
block
|
||||
|
||||
When chaining multiple && and/or || operators, the shortcut evaluation
|
||||
effectively make them right-associative.
|
|
@ -1,5 +1,6 @@
|
|||
Function Library Name Description
|
||||
abs stdlib Absolute Value Return absolute value of byte.
|
||||
anykey stdiox Any Key Display "Any Key" prompt and wait for keypress.
|
||||
atoc stdlib ASCII to Character Convert numeric string to byte.
|
||||
blkbgn block Block Begin Set beginning of block address.
|
||||
blkend block Block End Set end of block address.
|
||||
|
@ -15,6 +16,8 @@ blkswp block Block Swap Swap bytes of array with the current seg
|
|||
blksrt block Block Sort Sort segments in block by initial string.
|
||||
ctoa stdlib Character to ASCII Convert byte to numeric string.
|
||||
div stdlib Divide Divide two bytes.
|
||||
failed test Failed Write " Fail" to screen.
|
||||
failln test Failed Line Write " Fail" plus newline to screen.
|
||||
fclall file File Close All Close all files.
|
||||
fclose file File Close Close file.
|
||||
feof file File End of File Check for end of file condition.
|
||||
|
@ -22,6 +25,8 @@ ferror file File Error Get file error information.
|
|||
fgetc file File Get Character Read character from file.
|
||||
fgets file File Get String Read string from file.
|
||||
fopen file File Open Open file.
|
||||
florps test Fail or Pass Write " Fail" or " Pass" to screen.
|
||||
flpsln test Fail or Pass Line Write " Fail" or " Pass" plus newline to screen.
|
||||
fputc file File Put Character Write character to file.
|
||||
fputs file File Put String Write string to file.
|
||||
fread file File Read Read bytes from file.
|
||||
|
@ -33,7 +38,10 @@ fssrc file File Set Source Set source array for fwrite.
|
|||
fstat file File System Status Get file pointer status.
|
||||
fwrite file File Write Write bytes to file.
|
||||
getc stdio Get Character Read character from keyboard.
|
||||
getdst stddef Get Destination Get address in Destination Pointer.
|
||||
getprc stdiox Get Prompt Character Display prompt and wait for keypress.
|
||||
gets stdio Get String Read string from keyboard.
|
||||
getsrc stddef Get Source Get address in Source Pointer.
|
||||
isalnm ctype Is Alphanumeric Return TRUE if character is A-Z, a-z, or 0-9.
|
||||
isalph ctype Is Alphabetic Return TRUE if character is A-Z or a-z.
|
||||
isbdgt ctype Is Binary Digit Return TRUE if character is 0 or 1.
|
||||
|
@ -46,16 +54,30 @@ ispnct ctype Is Punctuation Return TRUE if Graphical and not Alphanu
|
|||
isprnt ctype Is Printable Return TRUE if ASCII code is 32-126.
|
||||
isspce ctype Is white Space Return TRUE if ASCII code is 9-13 or 32.
|
||||
isuppr ctype Is Uppercase Return TRUE if character is A-Z.
|
||||
maddr memio Memory Address Return address contained in memory file pointer.
|
||||
max stdlib Maximum Return greater of two byte.
|
||||
mclose memio Memory Close Close memory file.
|
||||
memdst memory Memory Destination Set destination array for subsequent functions.
|
||||
memset memory Memory Set File bytes in array with character.
|
||||
memset memory Memory Set File bytes in array with byte.
|
||||
memchr memory Memory Character Search for byte in array.
|
||||
memclr memory Memory Cllear File bytes in array with $00.
|
||||
memcmp memory Memory Compare Compare bytes in array against destination array.
|
||||
memcpy memory Memory Copy Copy bytes from array to destination array.
|
||||
memswp memory Memory Swap Swap bytes in array with destination array.
|
||||
mflush memio Memory Flush Flush memory file.
|
||||
mgetc memio Memory Get Character Read single character from memory file.
|
||||
mgets memio Memory Get String Read string from memory file.
|
||||
min stdlib Minimum Return lesser of two byte.
|
||||
mopen memio Memory Open Open memory file.
|
||||
mputc memio Memory Put Character Write single character to memory file.
|
||||
mputln memio Memory Put String Write string followed by newline to memory file.
|
||||
mputs memio Memory Put String Write string to memory file.
|
||||
mult stdlib Multiply Multiply two bytes.
|
||||
ptrset pointer Pointer Set Set pointer to address.
|
||||
passed test Passed Write " Pass" to screen.
|
||||
passln test Passed Line Print " Pass" plus newline to screen.
|
||||
psflln test Pass or Fail Line Write " Pass" or " Fail" plus newline to screen.
|
||||
psorfl test Pass or Fail Write " Pass" or " Fail" to screen.
|
||||
ptrset pointer Pointer Set Write pointer to address.
|
||||
ptrput pointer Pointer Put Write byte and increment pointer.
|
||||
ptrget pointer Pointer Get Read byte and increment pointer.
|
||||
ptrinc pointer Pointer Increment Increment pointer.
|
||||
|
@ -65,14 +87,46 @@ ptrsub pointer Pointer Subtract Subtract value from pointer.
|
|||
ptrcmp pointer Pointer Compare Compare pointer against address.
|
||||
ptrsav pointer Pointer Save Save pointer into two-byte array.
|
||||
ptrrst pointer Pointer Restore Restore pointer from two-byte array.
|
||||
printf stdiox Print Formatted Write formatted byte and/or string/address to screen.
|
||||
putadr test Put Address Write "address=" and hexadecimal address to screen.
|
||||
putc stdio Put Character Write character to screen.
|
||||
puts stdio Output String Write string to screen.
|
||||
putsub stdio Output Substring Write substring to screen.
|
||||
putln stdio Put String Write string plus newline to screen.
|
||||
putdec stdiox Put Decimal Write byte to screen as decimal number.
|
||||
putdel stdiox Put Decimal Left Write byte to screen as left-justified decimal.
|
||||
putder stdiox Put Decimal Right Write byte to screen as right-justified decimal.
|
||||
putdst stdios Put Destination Write destination string to screen.
|
||||
puthex stdiox Put Hexadecimal Write byte to screen as hexadecimal number.
|
||||
putln stdio Put Line Write string plus newline to screen.
|
||||
puts stdio Put String Write string to screen.
|
||||
putspc stdiox Put Space Write space character to screen.
|
||||
putsub stdio Put Substring Write substring to screen.
|
||||
putwrd stdiox Put Word Write address to screen as hexadecimal number.
|
||||
rand stdlib Random Generate pseudorandom number.
|
||||
rands stdlib Random Seed Seed random number generator.
|
||||
ressrc stddef Restore Destination Restore Destination Pointer from TEMP variables.
|
||||
resreg stddef Restore Registers Restore A, X, and Y registers from TEMP variables.
|
||||
resrxy stddef Restore Reg. X and Y Restore X, and Y registers from TEMP variables.
|
||||
ressrc stddef Restore Source Restore Source Pointer from TEMP variables.
|
||||
savreg stddef Save Registers Save A, X, and Y registers in TEMP variables.
|
||||
savrxy stddef Save Reg. X and Y Save X, and Y registers in TEMP variables.
|
||||
savsrc stddef Save Source Save Source Pointer in TEMP variables.
|
||||
setdss stddef Set Dest. Source Set Destination Pointer to Source Pointer.
|
||||
setdst stddef Set Destination Set Destination Pointer to address.
|
||||
setsrc stddef Set Source Set Source Pointer to address.
|
||||
setsrd stddef Set Source Dest. Set Source Pointer to Destination Pointer.
|
||||
shiftl stdlib Shift Left Shift byte left specified number of bits.
|
||||
shiftr stdlib Shift Right Shift byte right specified number of bits.
|
||||
stkbgn stack Stack Begin Set start of stack address.
|
||||
stkdup stack Stack Duplicate Duplicate top entry of stack.
|
||||
stkend stack Stack End Set end of stack address.
|
||||
stkovr stack Stack Over Copy second from top entry of stack to top.
|
||||
stkpop stack Stack Pop Remove entry from top of stack.
|
||||
stkpsh stack Stack Push Push array contents onto top of stack.
|
||||
stkptr stack Stack Pointer Get stack pointer address.
|
||||
stkrst stack Stack Reset Initialize or clear stack.
|
||||
stkset stack Stack Set Set stack pointer to address.
|
||||
stkstr stack Stack String Push string onto top of stack.
|
||||
stktop stack Stack Top Get entry from top of stack without popping it.
|
||||
stkswp stack Stack Swap Swap top entry of stack with entry below it.
|
||||
strapd string String Append Append character to string.
|
||||
strcat string String Concatenate Concatenate string to destination string.
|
||||
strchr string String Character Search for character in string.
|
||||
|
@ -86,5 +140,7 @@ strpbk stringx String Pointer Break Find first character in destination foun
|
|||
strrch string String Reverse Char Search for character from end of string.
|
||||
strspn stringx String Span Return length of span in destination found in string.
|
||||
strstr string String String Search for string in destination string.
|
||||
swap stdlib Swap nybbles Swaps the upper and lower nybbles in a byte.
|
||||
tolowr ctype To Lowercase Convert character to lowercase.
|
||||
touppr ctype To Uppercase Convert character to uppercase.
|
||||
trufls test True or False Convert value to #TRUE or #FALSE.
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
The C02 library provides functions for common tasks and allows the
|
||||
creation of programs that can be compiled for different systems with
|
||||
little or no changes.
|
||||
|
||||
Use of the C02 library requires a system specific header, which can be
|
||||
specified using the #include directive in the source code or by using
|
||||
a command line argument when running the compiler. The available
|
||||
headers include:
|
||||
|
||||
appl2std Original Apple 2 (incomplete)
|
||||
apple1 Apple 1 (incomplete)
|
||||
c64 Commodored 64 (incomplete)
|
||||
oric Oric-1 (incomplete)
|
||||
plus4 Commoded Plus/4 (incomplete)
|
||||
py65 Python 6502 Emulator - py65mon
|
||||
vic3k Vic-20 with 3k memory (incomplete)
|
||||
vic8k Vic-20 with 8k+ memory (incomplete)
|
||||
|
||||
The library functions are contained in various modules. The #include
|
||||
directive is used to allow the functions in a module to be used in a
|
||||
program. Most modules require that orher modules be included. These
|
||||
dependencies are detailed in the documentation for each individual
|
||||
module. The available modules are as follows:
|
||||
|
||||
stddef Standard Definitions
|
||||
|
||||
Contains commonly used constants, as well as base
|
||||
functions common to nearly every other module.
|
||||
|
||||
stdlib Standard Library
|
||||
|
||||
Includes the most commonly used functions, including
|
||||
mathematical operations and string/numeric conversions.
|
||||
|
||||
stdio Standard Input/Output
|
||||
|
||||
Contains functions for reading and writing characters
|
||||
and strings from the keyboard and to the screen.
|
||||
|
||||
stdiox Standard Input/Output Extended
|
||||
|
||||
Contains functions for writing formatted data to the
|
||||
screen, including decimal and hexadecimal numbers.
|
||||
|
||||
memio Memory Input/Ouput
|
||||
|
||||
Provides functions to simulate reading and writing to
|
||||
a section of memory as though it were a file.
|
||||
|
||||
string String functions
|
||||
|
||||
Contains functions for copying, searching, comparing,
|
||||
and concatenating strings.
|
||||
|
||||
stringx String Extended
|
||||
|
||||
Contains the more powerful, but less frequently used
|
||||
string manipulation functions.
|
||||
|
||||
memory Memory functions
|
||||
|
||||
Contains functions for copying, searching, and comparing
|
||||
arrays.
|
||||
|
||||
block Block functions
|
||||
|
||||
Contains functions for reading, writing, and searching
|
||||
for fixed length segments of data to an arbitrarily large
|
||||
section of memory.
|
||||
|
||||
Stack Stack functions
|
||||
|
||||
Contains functions for pushing and popping variable
|
||||
length segments of data onto and off of a stack in memory.
|
|
@ -9,6 +9,7 @@ function has the same signature it's equivalent in the file library.
|
|||
|
||||
At the beginning of the program use the directives
|
||||
|
||||
#include <stddef.h02>
|
||||
#include <memio.h02>
|
||||
|
||||
The following functions are defined:
|
||||
|
|
133
doc/pointer.txt
133
doc/pointer.txt
|
@ -5,120 +5,69 @@ This library contains functions for basic pointer access and manipulation.
|
|||
These functions are intended to allow sequential reading and writing of
|
||||
individual bytes to arbitrary locations in memory.
|
||||
|
||||
Only one pointer may be active at a time, but it's contents may be saved
|
||||
and restored using the following code:
|
||||
|
||||
savelo = ptrlo; savehi = ptrhi; //save current pointer
|
||||
ptrlo = savelo; ptrhi = savehi; //restore current pointer
|
||||
|
||||
where savelo and savehi are an arbitrary pair of variables defined in the
|
||||
program.
|
||||
A pointer consists of any two consecutive bytes in Zero Page and is
|
||||
referenced using the single byte zeto page address (0-254).
|
||||
|
||||
Note: There is no concept of a null pointer in C02. A pointer containing
|
||||
the value 0 simply points to the first byte of memory.
|
||||
|
||||
In the equivalent C code examples below, the system pointer is represented
|
||||
as the variable p. In all cases, assume the following declaration :
|
||||
|
||||
int *p;
|
||||
|
||||
Usage: at the beginning of the program use the directives
|
||||
|
||||
#include <pointer.h02>
|
||||
|
||||
The following application functions are defined:
|
||||
|
||||
ptrset(&v); Pointer Set: Set pointer contents to the address of
|
||||
variable v.
|
||||
ptr, msb, lsb = Pointer Set: Set the contents of the pointer at
|
||||
ptrset(zp, &addr); location zp to the address &addr.
|
||||
|
||||
Returns the zsro-page pointer location, address
|
||||
high byte, and address low byte.
|
||||
|
||||
This is equivalent to the C code
|
||||
|
||||
p = &v;
|
||||
|
||||
Note: Sets variables ptrlo and ptrhi.
|
||||
ptr, msb, lsb = Pointer Address: Retrieves the contents of the
|
||||
ptradr(zp); pointer at location zp.
|
||||
|
||||
Returns the zsro-page pointer location, address
|
||||
high byte, and address low byte.
|
||||
|
||||
ptrput(b); Pointer Put: Stores value of b in the byte currently
|
||||
pointed to and increments the pointer.
|
||||
ptr, b = Pointer Put: Stores byte of b at the address
|
||||
ptrput(zp, b); pointed to by the pointer at location zp, then
|
||||
increments the pointer contents.
|
||||
|
||||
This is equivalent to the C code
|
||||
|
||||
*p = b; p++;
|
||||
|
||||
Note: Updates variables ptrlo and ptrhi.
|
||||
Returns the zsro-page pointer location and value
|
||||
written to address.
|
||||
|
||||
b = ptrget(); Pointer Get: Retrieves the contents of the byte
|
||||
currently pointed to and increments the pointer.
|
||||
b = ptrget(zp); Pointer Get: Retrieves the contents of the byte
|
||||
at the address pointed to by the pointer at
|
||||
location zp, then increments the pointer contents.
|
||||
|
||||
This is equivalent to the C code
|
||||
|
||||
b = *p; p++;
|
||||
|
||||
Note: Updates variables ptrlo and ptrhi.
|
||||
ptrinc(zp); Pointer Increment: Increases the contents of the
|
||||
pointer at location zp by one.
|
||||
|
||||
ptrinc(); Pointer Increment: Increases the pointer value by 1,
|
||||
causing it to point to the next byte in memory.
|
||||
ptrdec(zp); Pointer Decrement: Decreases the contents of the
|
||||
pointer at location zp by one.
|
||||
|
||||
This is equivalent to the C code
|
||||
|
||||
p++;
|
||||
|
||||
Note: Updates variables ptrlo and ptrhi.
|
||||
ptr, msb, lsb = Pointer Add: Adds the 16-bit value specified by &addr
|
||||
ptradd(zp, &addr); or msb, lsb to the contents of the pointer at
|
||||
ptradd(zp,msb,lsb); location zp.
|
||||
|
||||
ptrdec(); Pointer Decrement: Decreases the pointer value by 1,
|
||||
causing it to point to the previous byte in memory.
|
||||
ptr, msb, lsb = Pointer Add: Subtracts the 16-bit value specified by
|
||||
ptrsub(zp, &addr); &addr or msb, lsb to the contents of the pointer at
|
||||
ptrsub(zp,msb,lsb); location zp.
|
||||
|
||||
This is equivalent to the C code
|
||||
|
||||
p++;
|
||||
|
||||
Note: Updates variables ptrlo and ptrhi.
|
||||
r = Pointer Compare: Compares the contents of the pointer
|
||||
ptrcmp(zp, &addr); at location zp to the address &addr.
|
||||
|
||||
ptradd(n); Pointer Add: Adds the value n to the address contained
|
||||
in the pointer, moving it that many bytes forward in
|
||||
memory.
|
||||
|
||||
This is equivalent to the C code
|
||||
|
||||
p += n;
|
||||
|
||||
Note: Updates variables ptrlo and ptrhi.
|
||||
|
||||
ptrsub(n); Pointer Subtract: Adds the value n to the address
|
||||
contained in the pointer, moving it that many bytes
|
||||
backward in memory.
|
||||
|
||||
This is equivalent to the C code
|
||||
|
||||
p -= n;
|
||||
|
||||
Note: Updates variables ptrlo and ptrhi.
|
||||
|
||||
ptrcmp(&v); Pointer Compare: Compares pointer contents against
|
||||
the address of variable v.
|
||||
|
||||
Returns 255 if the pointer is less than the address
|
||||
(pointing to a byte lower in memory), 0 if the pointer
|
||||
is equal to the address (pointing to the same byte),
|
||||
and 1 if greater than tge address (pointing to a
|
||||
byte higher in memory).
|
||||
These results can be evaluated using the C02
|
||||
unary comparator ! or the test-operators :+ or :-.
|
||||
|
||||
This is equivalent to the C code
|
||||
|
||||
if (p < &v) return 255;
|
||||
else if (p > &v) return 1;
|
||||
else return 0;
|
||||
|
||||
Note: Sets variables srclo and srchi.
|
||||
Returns 255 if the contents are less than the address
|
||||
(pointing to a byte lower in memory), 0 if the contents
|
||||
are equal to the address (pointing to the same byte),
|
||||
and 1 if the contents are greater than the address
|
||||
(pointing to a byte higher in memory).
|
||||
|
||||
These results can be evaluated using the C02 unary
|
||||
comparator ! or the test-operators :+ or :-.
|
||||
|
||||
Note: This library expects the following to be defined:
|
||||
|
||||
the zero page variable pair
|
||||
|
||||
ptrlo, ptrhi System Pointer
|
||||
the transient variables
|
||||
|
||||
and the transient variable
|
||||
|
||||
temp0 Temporary storage
|
||||
temp0, temp1, temp2 Temporary storage
|
||||
|
|
|
@ -14,6 +14,7 @@ most of these functions do not match those in standard C and C++.
|
|||
|
||||
Usage: at the beginning of the program use the directives
|
||||
|
||||
#include <stddef.h02>
|
||||
#include <string.h02>
|
||||
|
||||
The following functions are defined:
|
||||
|
|
|
@ -8,6 +8,7 @@ Strings follow all the same rules as specified in the string.h02 library.
|
|||
|
||||
Usage: at the beginning of the program use the directives
|
||||
|
||||
#include <stddef.h02>
|
||||
#include <string.h02>
|
||||
#include <stringx.h02>
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
Character Symbols Recognized by the C02 Compiler
|
||||
|
||||
Symbol Prefix Operator Comparator Delimiter
|
||||
! Bitwise Or Logical Not
|
||||
" String Literal
|
||||
# Constant
|
||||
$ Hexadecimal
|
||||
% Binary
|
||||
& Address Of Bitwise And
|
||||
' Character Literal
|
||||
( Comparison
|
||||
) Comparison
|
||||
* (pointer)
|
||||
+ Addition
|
||||
, Declarations
|
||||
- Subtraction
|
||||
. Struct Members
|
||||
/ Comment
|
||||
: Status Flag Shortcut Else
|
||||
; Statement
|
||||
< Less Than
|
||||
= Equal To Assignment
|
||||
> Greater Than
|
||||
? Index Of Shortcut If
|
||||
@ Length Of
|
||||
[ Array Element
|
||||
\
|
||||
] Array Element
|
||||
^ (pointer)
|
||||
_
|
||||
{ Block Start
|
||||
| Bitwise Or
|
||||
} Block End
|
||||
~
|
|
@ -0,0 +1,36 @@
|
|||
Template Functions for C02 Programs
|
||||
|
||||
This is a template for the documentation of a C02 library module.
|
||||
|
||||
At the beginning of the program use the directives
|
||||
|
||||
#include <stddef.h02>
|
||||
#include <template.h02>
|
||||
|
||||
The following functions are defined:
|
||||
|
||||
c,d,e = func(a,&d); Stores the input value a and the address of d
|
||||
in memory.
|
||||
|
||||
Returns three bytes read from memory.
|
||||
|
||||
Note: Writes argument a to variable arg0,
|
||||
the address of d to variables adr0 and adr1,
|
||||
and returns the values of variables var0,
|
||||
var1, and var2.
|
||||
|
||||
Note: This library expects the following functions to be defined:
|
||||
|
||||
ext(); External function description
|
||||
|
||||
along with the zero page variables
|
||||
|
||||
zpage0,zpage1: Zero page variable pair
|
||||
|
||||
the external variables
|
||||
|
||||
exvar0,exvar1: External variable pair
|
||||
|
||||
and the constants
|
||||
|
||||
#CNSTNAME Constant description
|
|
@ -49,7 +49,7 @@ along with the following functions:
|
|||
|
||||
Note: Calls puts() with the string variable fail.
|
||||
|
||||
passln(); Prints the string " Fail" to the screen, followed
|
||||
failln(); Prints the string " Fail" to the screen, followed
|
||||
by a New Line.
|
||||
|
||||
Note: Calls failed() and newlin().
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
; Program initialization code for Oric-1
|
||||
|
||||
;System Specific ASCII Key Mappings
|
||||
DELKEY EQU $7F ;Delete/Backspace Key (Delete)
|
||||
ESCKEY EQU $1B ;Escape/Stop Key (Escape)
|
||||
RTNKEY EQU $0D ;Return/Enter Key ($0D=Carriage Return)
|
||||
NULKEY EQU $00 ;No Key was Pressed ($00=Null)
|
||||
|
||||
;Zero Page Locations
|
||||
SRCLO EQU $00 ;Source String Pointer (stdio.asm)
|
||||
SRCHI EQU $01
|
||||
DSTLO EQU $02 ;Destination String Pointer (string.asm)
|
||||
DSTHI EQU $03
|
||||
|
||||
STKSAV EQU $04 ;Stack Pointer Storage
|
||||
RDSEED EQU $05 ;Pseudo-RANDOM Seed
|
||||
RANDOM EQU $06 ;Pseudo-RANDOM Number Storage
|
||||
|
||||
TEMP0 EQU $07 ;Temporary Storage
|
||||
TEMP1 EQU $08
|
||||
TEMP2 EQU $09
|
||||
TEMP3 EQU $0A
|
||||
|
||||
BLKSLO EQU $0B ;Block Start Address
|
||||
BLKSHI EQU $0C
|
||||
BLKELO EQU $0D ;Block End Address
|
||||
BLKEHI EQU $0E
|
||||
|
||||
;Oric-1 Memory Locations
|
||||
CAPLCK EQU $020C ;Caps Lock: 127=Off, 255 = On
|
||||
|
||||
;Oric-1 ROM Funxtions
|
||||
GTORKB EQU $E905 ;Get Character from Keyboard
|
||||
VDU EQU $F409 ;Print character in X to screen
|
||||
|
||||
;Oric-1 Tape images have the file extension ".tap"
|
||||
;and have the following header prepended to the code
|
||||
; $16,$16,$16, $16 Tape Syncronization Pattern
|
||||
; $24 Tape Syncronization Byte
|
||||
; $00,$00 Filler Bytes
|
||||
; $00 Basic Program
|
||||
; $00 No Autostart ($80 for Autostart)
|
||||
; $xx,$xx MSB, LSB of End Address
|
||||
; $05,$01 MSB, LSB of Start Address
|
||||
; $00 Filler Byte
|
||||
; "filename" Up to 16 ASCII Characters
|
||||
; $00 Strint Terminator
|
||||
|
||||
;The End Address is actually one higher than the last
|
||||
;byte of the Basic program and the first byte of Basic
|
||||
;variable space. so the compiled program need to have
|
||||
;one dummy byte added to the end.
|
||||
|
||||
ORG $0501 ;Basic Program Start Address
|
||||
|
||||
BASIC: .DB $0C,$05 ;Address of Next Line
|
||||
.DB $00,$00 ;Basic Line Number (0)
|
||||
.DB $BF ;Token for Basic Call Command
|
||||
.DB $20 ;Space
|
||||
.DS "1294" ;Address of START Label
|
||||
.DB $00 ;End of Line
|
||||
.DB $00,$00 ;End of Program Marker
|
||||
|
||||
START: TXS ;Save Stack Pointer
|
||||
STX STKSAV
|
||||
LDA #127 ;Set Caps Lock Off
|
||||
STA CAPLCK
|
||||
JMP MAIN ;Execute Program
|
||||
|
||||
;Poll Character from Keyboard
|
||||
PLKEY: INC RDSEED ;Cycle the Random Seed (if not provided by system)
|
||||
JMP GTORKB ;Call ROM Key Reading function and return
|
||||
|
||||
;Read Character from Console
|
||||
GETKEY; ;Drop into RDKEY routine
|
||||
|
||||
;Wait for Character from Console
|
||||
RDKEY: JSR PLKEY ;Usually calls PLKEY
|
||||
BEQ RDKEY ; until a non-zero is returned
|
||||
RTS
|
||||
|
||||
;Delete Previous Character
|
||||
DELCHR: LDA DELKEY ;Load Delete Character
|
||||
BNE PRCHR ;and Print to Screem
|
||||
|
||||
;Advance Cursor to Next line
|
||||
NEWLIN: LDA RTNKEY ;Load Carriage Return and fall through to PRCHR
|
||||
|
||||
;Print Character to Screen
|
||||
PRCHR: TAX ;Transfer Character to X Register
|
||||
JMP VDU ;Call ROM Print Function and Return
|
||||
|
||||
;Exit Program and Return to Operating System or Monitor
|
||||
EXIT: LDA #255 ;Set Caps Lock On
|
||||
STA CAPLCK
|
||||
LDX STKSAV ;Restore Stack Pointer
|
||||
TXS
|
||||
RTS ;and Return to Basic
|
||||
|
||||
;Note: The following two functions replicate calls available
|
||||
;in the Apple-1 monitor and are included for test purposes
|
||||
;They will likely be removed before the final release
|
||||
|
||||
;Print Byte as Two-Digit Hex Number to Console
|
||||
PRBYTE: PHA ;Save Accumulater
|
||||
LSR ;Shift Hi Nybble to Low Nybble
|
||||
LSR
|
||||
LSR
|
||||
LSR
|
||||
JSR PRHEX ; and Print it
|
||||
PLA ;Restore Accumulator
|
||||
; and fall into PRHEX
|
||||
|
||||
;Print Low Nybble as Hex Digit to Console
|
||||
PRHEX: AND #$0F ;Strip High Nybble
|
||||
CMP #$0A ;If Low Nybble >= 10
|
||||
BCC PRHEXC ;
|
||||
ADC #$06 ; Convert ':' to 'A'...
|
||||
PRHEXC: ADC #$30 ;Convert to ASCII Character
|
||||
JMP PRCHR ;Print Hex Digit and Return
|
||||
|
||||
|
||||
;Functions to set String Pointers
|
||||
;Used by memory, stdio, stdlin, string, and stringx libraries
|
||||
|
||||
;Initialize Destination String Pointer
|
||||
SETDST: STX DSTLO ;Save Destination String Pointer
|
||||
STY DSTHI
|
||||
RTS
|
||||
|
||||
;Initialize Source String Pointer and Index
|
||||
SETSRC: STX SRCLO ;Save Source String Pointer
|
||||
STY SRCHI
|
||||
LDY #$00 ;Initialize Index Into String
|
||||
RTS
|
|
@ -0,0 +1,28 @@
|
|||
/* C02 Standard Header for Oric-1 */
|
||||
|
||||
|
||||
/* System Specific ASCII Key Codes */
|
||||
const DELKEY; //Delete/Backspace Key
|
||||
const ESCKEY; //Escape/Stop Key
|
||||
const RTNKEY; //Return/Enter Key
|
||||
const NULKEY //No Key was Pressed
|
||||
|
||||
/* Zero Page Variables used as Pointers */
|
||||
char strlo,strhi; //String pointer for String and I/O functions
|
||||
char dstlo,dsthi; //Secondary string pointer for String functions
|
||||
|
||||
char temp0,temp1,temp2,temp3; //Temporary variables
|
||||
|
||||
/* Static Library Variables */
|
||||
char random; //Last Result of Pseudo-Random Number Generator
|
||||
char rdseed; //System Seed for Pseudo-Random Number Generator
|
||||
|
||||
//System Subroutines
|
||||
char plkey(); //Poll Console for character
|
||||
char rdkey(); //Wait for character from Console
|
||||
char getkey(); //Read ASCII character from Console
|
||||
void newlin(); //Advance cursor to beginning of next line
|
||||
void prchr(); //Print ASCII character to Console
|
||||
void prbyte(); //Print Accumulator as Hexadadecimal number
|
||||
void prhex(); //Print Low Nybble of Accumulator as Hex Digit
|
||||
|
|
@ -2,88 +2,139 @@
|
|||
;Requires External Zero Page Variables PTRLO, PTRHI
|
||||
;External Routines MSETSRC
|
||||
|
||||
;ptrset(&a) - Store Address in Pointer
|
||||
;Args: A = Zero Page Pointer Locatione
|
||||
; X,Y = Address
|
||||
;Sets: PTRLO, PTRHI = Pointer
|
||||
PTRSET: STX PTRLO ;Pointer Low Byte
|
||||
STY PTRHI ;Pointer Start High Byte
|
||||
;ptrini - Pointer Initialization code
|
||||
;Sets: TEMP0 = Memory Pointer Address
|
||||
PTRINI: STX TEMP0 ;Save Address LSB
|
||||
TAX ;Copy Memory Pointer to X register
|
||||
LDA TEMP0 ;Retrieve Address LSB
|
||||
RTS
|
||||
|
||||
;ptrcmp(&a) - Compare Pointer to Address
|
||||
;Requires: PTRLO, PTRHI - Pointer
|
||||
;Args: X,Y = Address to Compare Against
|
||||
;ptradr(ptr, &addr) - Return Address Stored in Pointer
|
||||
;Args: A = Zero Page Pointer Address
|
||||
;Sets: TEMP0 = Pointer Address
|
||||
;Affects: N,Z
|
||||
;Returns: A = Zero Page Pointer Address
|
||||
; Y,X = New Pointer Contents
|
||||
PTRADR: JSR PTRINI ;Swap A and X Registers
|
||||
PTRRTN: LDY (1,X) ;Load Pointer MSB into Y
|
||||
LDA (1,X) ;Load Pointer LSB into A
|
||||
TAX ;and transfer to X
|
||||
LDA TEMP0 ;Load Pointer Addres into A
|
||||
RTS
|
||||
|
||||
|
||||
;ptrset(ptr, &addr) - Store Address in Pointer
|
||||
;Args: A = Zero Page Pointer Address
|
||||
; X,Y = Address to Store
|
||||
;Sets: TEMP0 = Pointer Address
|
||||
;Affects: N,Z
|
||||
;Returns: A = Zero Page Pointer Address
|
||||
; Y,X = New Pointer Contents
|
||||
PTRSET: JSR PTRINI ;Swap A and X Registers
|
||||
STA 0,X ;Store in Memory Pointer LSB
|
||||
STY 1,X ;Store Address MSB in Memory Pointer MSB
|
||||
TXA
|
||||
LDX TEMP0
|
||||
RTS ;Return Pointer Address as Result
|
||||
|
||||
;ptrcmp(ptr, &addr) - Compare Pointer to Address
|
||||
;Args: A = Zero Page Pointer Address
|
||||
; X,Y = Address to Compare Against
|
||||
;Affects N,Z
|
||||
;Returns A=$01 and C=? if Pointer > Address
|
||||
; A=$00 and Z=1, C=? if Pointer = Address
|
||||
; A=$FF and C=? if Pointer < Address
|
||||
PTRCMP: CPY PTRHI ;Compare High Bytes
|
||||
BCC PTRCMN ;If Pointer > Address, Return 1
|
||||
BNE PTRCMF ;If Pointer < Address Return 1
|
||||
CPX PTRLO ;Compare Low Byte
|
||||
BCC PTRCMN ;If Pointer > Address, Return 1
|
||||
BNE PTRCMF ;If Pointer < Address Return 1
|
||||
PTRCMZ: LDA #$00 ;Return 0
|
||||
PTRCMP: JSR PRTINI ;Swap A and X Registers
|
||||
CPY 1,X ;Compare High Bytes
|
||||
BCC PTRCMN ;If Pointer > Address, Return 1
|
||||
BNE PTRCMF ;If Pointer < Address Return 1
|
||||
CPA 0,X ;Compare Low Byte
|
||||
BCC PTRCMN ;If Pointer > Address, Return 1
|
||||
BNE PTRCMF ;If Pointer < Address Return 1
|
||||
PTRCMZ: LDA #$00 ;Return 0
|
||||
RTS
|
||||
PTRCMN: LDA #$01 ;Return 1
|
||||
PTRCMN: LDA #$01 ;Return 1
|
||||
RTS
|
||||
PTRCMF: LDA #$FF ;Return 255
|
||||
PTRCMF: LDA #$FF ;Return 255
|
||||
RTS
|
||||
|
||||
;ptrget() - Read Byte from Pointer Address
|
||||
; and Increment Pointer
|
||||
;Sets: PTRLO, PTRSHI = New pointer address
|
||||
;ptrget(ptr) - Read Byte from Pointed to Address
|
||||
; and Increment Pointer
|
||||
;Args: A = Zero Page Pointer Address
|
||||
;Affects: N, Z
|
||||
;Returns: A = Byte at pointer address
|
||||
;Affects: Y, N, Z
|
||||
PTRGET: LDY #0 ;Set Offset to 0
|
||||
LDA (PTRLO),Y ;Load Value at Pointer
|
||||
; X = Zero Page Pointer Address
|
||||
PTRGET: TAX ;Transfer Pointer Address to X
|
||||
LDA (0,X) ;Load Value at Pointer
|
||||
JMP PTRINN ;Increment Pointer Value
|
||||
|
||||
;ptrinc() - Increment Pointer Address
|
||||
;Sets: PTRLO, PTRSHI = New pointer address
|
||||
;ptrinc(ptr) - Increment Pointer Address
|
||||
;Args: A = Zero Page Pointer Address
|
||||
;Affects: N, Z
|
||||
PTRINC: INC PTRLO ;Increment Pointer Low Byte
|
||||
BNE PTRRET ;If Zero
|
||||
INC PTRHI ; Increment Pointer High Byte
|
||||
PTRRET: RTS ;Return from function
|
||||
;Returns: A,X = Zero Page Pointer Address
|
||||
PTRINC: TAX ;Transfer Pointer Address to X
|
||||
PTRINN: INC (0,X) ;Increment Pointer Low Byte
|
||||
BNE PTRRET ;If Zero
|
||||
INC (1,X) ; Increment Pointer High Byte
|
||||
PTRRET: RTS ;Return from function
|
||||
|
||||
;ptrput() - Write Byte from Pointer Address
|
||||
;ptrput(ptr,byte) - Write Byte from Pointer Address
|
||||
; and Increment Pointer
|
||||
;Args: A = Byte to write
|
||||
;Sets: PTRLO, PTRSHI = New pointer address
|
||||
;Affects: Y, N, Z
|
||||
PTRPUT: LDY #0 ;Set Offset to 0
|
||||
STA (PTRLO),Y ;Load Value at Pointer
|
||||
JMP PTRINC ;Increment Pointer
|
||||
;Args: A = Zero Page Pointer Address
|
||||
; Y = Byte to write
|
||||
;Affects: N, Z
|
||||
;Returns: A,X = Zero Page Pointer Address
|
||||
PTRPUT: TAX ;Transfer Pointer Address to X
|
||||
STY (0,X) ;Store Value at Pointed to Address
|
||||
JMP PTRINN ;Increment Pointer
|
||||
|
||||
;ptrdec() - Decrement Pointer Address
|
||||
;Sets: PTRLO, PTRSHI = New pointer address
|
||||
;Args: A = Zero Page Pointer Address
|
||||
;Affects: Y, N, Z
|
||||
PTRDEC: LDY PTRLO ;Get Pointer Low Byter
|
||||
BNE PTRDEL ;If Zero
|
||||
DEC PTRHI ; Deccrement Pointer High Byte
|
||||
PTRDEL: DEC PTRLO ;Decrement Pointer Low Byte
|
||||
RTS ;Return from function
|
||||
;Returns: A = Zero Page Pointer Address
|
||||
; Y,X = New Pointer Contents
|
||||
PTRDEC: TAX ;Transfer Pointer Address to X
|
||||
LDY (0,X) ;Get Pointer Low Byter
|
||||
BNE PTRDEL ;If Zero
|
||||
DEC (1,X) ; Decrement Pointer High Byte
|
||||
PTRDEL: DEC (0,X) ;Decrement Pointer Low Byte
|
||||
JMP PTRRTN ;Set Registers and Return
|
||||
|
||||
;ptradd() - Add Offset to Pointer
|
||||
;Args: A = Number of bytes to add
|
||||
;Sets: PTRLO, PTRSHI = New pointer address
|
||||
;Affects: A, N, Z
|
||||
PTRADD: CLC ;Add Offset to Low Byte
|
||||
ADC PTRLO
|
||||
STA PTRLO ;And Save It
|
||||
BCC PTRRET ;If Carry
|
||||
INC PTRHI ; Increment High Byte
|
||||
RTS
|
||||
;ptradd(ptr, &offset) - Add Offset to Pointer
|
||||
;Args: A = Zero Page Pointer Address
|
||||
; Y,X = Number of bytes to add
|
||||
;Sets: TEMP0 = Pointer Address
|
||||
;Affects: N, Z
|
||||
;Returns: A = Zero Page Pointer Address
|
||||
; Y,X = New Pointer Contents
|
||||
PTRADD: JSR PRTINI ;Swap A and X Registers
|
||||
CLC ;Add Offset Low Byte
|
||||
ADC (0,X) ;to Pointer Low Byte
|
||||
STA (0,X) ;and Save It
|
||||
TYA ;Add Offset High Byte
|
||||
ADC (1,X) ;to Pointer High Byte
|
||||
STA (1,X) ;and Save It
|
||||
JMP PTRRTN ;Set Registers and Return
|
||||
|
||||
;ptrsub(offset) - Subtract Offset from Pointer
|
||||
;Args: A = Zero Page Pointer Address
|
||||
; Y,X = Number of bytes to add
|
||||
;Sets: TEMP0 = Pointer Address
|
||||
; TEMP1 = Offset LSB
|
||||
; TEMP2 = Offset MSB
|
||||
;Affects: N, Z
|
||||
;Returns: A = Zero Page Pointer Address
|
||||
; Y,X = New Pointer Contents
|
||||
PTRSUB: STY TEMP2 ;Save Offset MSB
|
||||
STX TEMP1 ;Save Offset LSB
|
||||
STA TEMP0 ;Save Pointer Address
|
||||
TAX ;Transfer Pointer Address to X
|
||||
LDA (0,X) ;Get Pointer Low Byte
|
||||
SEC ;Subtract Offset LSB
|
||||
SBC TEMP1 ;from Pointer LSB
|
||||
STA PTRLO ;and Save It
|
||||
LDA (1,X) ;Subtract Offset MSB
|
||||
SBC TEMP1 ;from Pointer MSB
|
||||
STA (1,X) ;and Save It
|
||||
JMP PTRRTN ;Set Registers and Return
|
||||
|
||||
;ptrsub() - Subtract Offset from Pointer
|
||||
;Args: A = Number of bytes to subtract
|
||||
;Sets: PTRLO, PTRSHI = New pointer address
|
||||
;Affects: A, N, Z
|
||||
PTRSUB: STA TEMP0 ;Save Offset
|
||||
LDA PTRLO ;Get Pointer Low Byte
|
||||
SEC ;Subtract Offset
|
||||
SBC TEMP0 ;
|
||||
STA PTRLO ;And Save New Low Byte
|
||||
BCS PTRRET ;If Borrow
|
||||
DEC PTRHI ; Decrement High Byte
|
||||
RTS
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
; C02 library test.h02 assembly language subroutines
|
||||
; Requires external functions
|
||||
; external zero page locations SRCLO and srchi
|
||||
; and external locations RANDOM, RDSEED, TEMP0, TEMP1, and TEMP2.
|
||||
|
||||
|
||||
;func(aa,xx,yy) - FUNCtion description
|
||||
;Args: A = First arguments
|
||||
; Y,X = Address argument
|
||||
;Sets: ARG0 = First argument
|
||||
; ADRLO,ADRLHI = Address argument
|
||||
;Uses: VAR0 = First Return Value
|
||||
; VAR2 = Second Return Value
|
||||
; VAR3 = Third Return Value
|
||||
;Affects: N,Z,C
|
||||
;Returns: A = First Return Value
|
||||
; Y = Second Return Value
|
||||
; X = Third Return Value
|
||||
FUNC: STA ARG0 ;Save First Argument
|
||||
STY ADRHI ;Save Address MSB
|
||||
STX ADRLO ;Save Address LSB
|
||||
LDA VAR0 ;Load First Return Value
|
||||
LDY VAR1 ;Load Second Return Value
|
||||
LDX VAR2 ;Load Third Return Value
|
||||
TYA ;Copy Second Parameter into Accumulator
|
||||
RTS
|
|
@ -0,0 +1,11 @@
|
|||
/*********************************************
|
||||
* stdlib - Template Library Routines for C02 *
|
||||
*********************************************/
|
||||
|
||||
/* Function Description *
|
||||
* Args: a - First Argument *
|
||||
* &d - Address Argumnt *
|
||||
* Returns: First Result *
|
||||
* Second Result *
|
||||
* Third Result */
|
||||
char func();
|
|
@ -6,31 +6,33 @@ ESCKEY EQU $03 ;Escape/Stop Key (RUN/STOP)
|
|||
RTNKEY EQU $0D ;Return/Enter Key (RETURN)
|
||||
|
||||
;Zero Page Locations
|
||||
RDSEED EQU $A2 ;Software Jiffy Clock (Low Byte)
|
||||
SRCLO EQU $D1 ;Pointer to Address of Current Screen Line
|
||||
SRCHI EQU $D2 ;Pointer to Address of Current Screen Line
|
||||
DSTLO EQU $FB ;Free Byte for User Programs
|
||||
DSTHI EQU $FC ;Free Byte for User Programs
|
||||
BLKLO EQU $FD ;Free Byte for User Programs
|
||||
BLKHI EQU $FE ;Free Byte for User Programs
|
||||
SRCLO EQU $22 ;Source Pointer LSB [Temporary Pointers]
|
||||
SRCHI EQU $23 ;Source Pointer MSB [Temporary Pointers]
|
||||
DSTLO EQU $25 ;Destination Pointer LSB [Temporary Pointers]
|
||||
DSTHI EQU $24 ;Destination Pointer MSB [Temporary Pointers]
|
||||
RDSEED EQU $A2 ;Random Seed [Software Jiffy Clock (Low Byte)]
|
||||
BLKLO EQU $FD ;Block Pointer LSB [Unused Byte]
|
||||
BLKHI EQU $FE ;Block Pointer MSB [Unused Byte]
|
||||
STKLO EQU $FD ;Stack Pointer LSB [Unused Byte]
|
||||
STKHI EQU $FE ;Stack Pointer MSB [Unused Byte]
|
||||
|
||||
USER0 EQU $0310 ;Free Byte for User Programs
|
||||
USER1 EQU $0311 ;Free Byte for User Programs
|
||||
USER2 EQU $0312 ;Free Byte for User Programs
|
||||
USER3 EQU $0313 ;Free Byte for User Programs
|
||||
USER4 EQU $0334 ;Free Byte for User Programs
|
||||
USER5 EQU $0335 ;Free Byte for User Programs
|
||||
USER6 EQU $0336 ;Free Byte for User Programs
|
||||
BLKSLO EQU $0337 ;Free Byte for User Programs
|
||||
BLKSHI EQU $0338 ;Free Byte for User Programs
|
||||
BLKELO EQU $0339 ;Free Byte for User Programs
|
||||
BLKEHI EQU $033A ;Free Byte for User Programs
|
||||
STKSAV EQU $033B ;Free Byte for User Programs
|
||||
STKSAV EQU $0312 ;Machine Stack Storage [Unused Byte]
|
||||
STKSLO EQU $0313 ;Stack Start LSB [Unused Byte]
|
||||
STKSHI EQU $0334 ;Stack Start MSB [Unused Byte]
|
||||
STKELO EQU $0335 ;Stack End LSB [Unused Byte]
|
||||
STKEHI EQU $0336 ;Stack End MSB [Unused Byte]
|
||||
BLKSLO EQU $0337 ;Block Start LSB [Unused Byte]
|
||||
BLKSHI EQU $0338 ;Block Start MSB [Unused Byte]
|
||||
BLKELO EQU $0339 ;Block Start MSB [Unused Byte]
|
||||
BLKEHI EQU $033A ;Block End MSB [Unused Byte]
|
||||
BLKLEN EQU $033B ;Block Length [Unused Byte]
|
||||
TBFFR EQU $033C ;Cassette I/O Buffer
|
||||
TEMP0 EQU $03FC ;Free Byte for User Programs
|
||||
TEMP1 EQU $03FD ;Free Byte for User Programs
|
||||
TEMP2 EQU $03FE ;Free Byte for User Programs
|
||||
TEMP3 EQU $03FF ;Free Byte for User Programs
|
||||
TEMP0 EQU $03FC ;Temporary Variable [Unused Byte]
|
||||
TEMP1 EQU $03FD ;Temporary Variable [Unused Byte]
|
||||
TEMP2 EQU $03FE ;Temporary Variable [Unused Byte]
|
||||
TEMP3 EQU $03FF ;Temporary Variable [Unused Byte]
|
||||
|
||||
;Video RAM and ROM
|
||||
VICSCN EQU $1E00 ;Video Screen Memory Area (Unexpanded)
|
||||
|
@ -59,19 +61,20 @@ EXIT: LDX STKSAV ;Retrieve Saved Stack Pointer
|
|||
PLKEY EQU $FFE4 ;Aliased to Kernal GETIN Routine
|
||||
|
||||
;Get Character from Keyboard
|
||||
GETKEY: EQU RDKEY
|
||||
GETKEY EQU PLKEY
|
||||
|
||||
;Wait for Character from Keyboard
|
||||
RDKEY: JSR PLKEY ;Poll Keyboard
|
||||
BEQ GETKEY ;If No Key, Loop
|
||||
RDKEY: JSR GETKEY ;Poll Keyboard
|
||||
BEQ RDKEY ;If No Key, Loop
|
||||
RTS
|
||||
|
||||
;Delete Previous Character
|
||||
DELCHR: LDA #DELKEY ;Load Delete Character
|
||||
JMP PRCHR :Print and Return
|
||||
JMP PRCHR ;Print and Return
|
||||
|
||||
;Advance Character to Next line
|
||||
NEWLIN: LDA #RTNKEY ;Load C/R into Accumulator
|
||||
JMP PRCHR ;Print and Return
|
||||
|
||||
;Print Character to Console
|
||||
PRCHR EQU $FFD2 ;Aliased to Kernal CHROUT Routine
|
||||
|
@ -82,7 +85,7 @@ PRBYTE: PHA ;Save Accumulater
|
|||
LSR
|
||||
LSR
|
||||
LSR
|
||||
JSR prhex ; and Print it
|
||||
JSR PRHEX ; and Print it
|
||||
PLA ;Restore Accumulator
|
||||
; and fall into prhex
|
||||
|
||||
|
@ -92,5 +95,5 @@ PRHEX: AND #$0F ;Strip High Nybble
|
|||
BCC PRHEXC ;
|
||||
ADC #$06 ; Convert ':' to 'A'...
|
||||
PRHEXC: ADC #$30 ;Convert to ASCII Character
|
||||
JMP prchr ;Print Hex Digit and Return
|
||||
JMP PRCHR ;Print Hex Digit and Return
|
||||
|
||||
|
|
|
@ -6,101 +6,42 @@ ESCKEY EQU $03 ;Escape/Stop Key (RUN/STOP)
|
|||
RTNKEY EQU $0D ;Return/Enter Key (RETURN)
|
||||
|
||||
;Zero Page Locations
|
||||
usradd EQU $01 ;Address of USR Routine
|
||||
linnum EQU $14 ;Integer Line Number Value
|
||||
txttab EQU $2B ;Pointer to Start of BASIC Program Text
|
||||
vartab EQU $2D ;Pointer to Start of BASIC Variable Storage Area
|
||||
arytab EQU $2F ;Pointer to Start of BASIC Array Storage Area
|
||||
strend EQU $31 ;Pointer to Start of Free RAM
|
||||
fretop EQU $33 ;Pointer to Bottom of String Text Storage Area
|
||||
memsiz EQU $37 ;Pointer to Highest Address Used by BASIC
|
||||
inpptr EQU $43 ;Pointer to Source of GET, READ, or INPUT Information
|
||||
facexp EQU $61 ;Floating Point Accumulator #1: Exponent
|
||||
facho EQU $62 ;Floating Point Accumulator #1: Mantissa
|
||||
facsgn EQU $66 ;Floating Point Accumulator #1: Sign
|
||||
fac2 EQU $69 ;Floating Point Accumulator #2
|
||||
argexp EQU $69 ;Floating Point Accumulator #2: Exponent
|
||||
argho EQU $6E ;Floating Point Accumulator #2: Mantissa
|
||||
argsgn EQU $6F ;Floating Point Accumulator #2: Sign
|
||||
chrget EQU $73 ;Subroutine: Get Next BASIC Text Character
|
||||
chrgot EQU $79 ;Entry Point: Get Current BASIC Text Character
|
||||
txtptr EQU $7A ;Pointer to Current BASIC Text Character
|
||||
pointb EQU $7C ;Entry Point: Test Character in Accumulator
|
||||
exit EQU $8A ;RTS at end of CHRGET, CHRGOT, and POINTB Routines
|
||||
status EQU $90 ;Kernal I/O Status Word
|
||||
ldtnd EQU $98 ;Number of Open I/O Files, Index to End of File Tables
|
||||
dfltn EQU $99 ;Default Input Device (Set to 0 for Keyboard)
|
||||
dflto EQU $9A ;Default Output (CMD) Device (Set to 3 for Screen)
|
||||
time EQU $A0 ;Software Jiffy Clock
|
||||
tape1 EQU $B2 ;Pointer: Start of Tape Buffer
|
||||
fnlen EQU $B7 ;Length of Current Filename
|
||||
la EQU $B8 ;Current Logical File Number
|
||||
sa EQU $B9 ;Current Secondary Address
|
||||
fa EQU $BA ;Current Device Number
|
||||
fnadr EQU $BB ;Pointer: Current Filename
|
||||
lste EQU $C5 ;Matrix Coordinate of Last Key Pressed
|
||||
ndx EQU $C6 ;Number of Characters in Keyboard Buffer
|
||||
rvs EQU $C7 ;Flag: Print Reverse Characters
|
||||
sfdx EQU $CB ;Matrix Coordinate of Current Key Pressed
|
||||
pnt EQU $D1 ;Pointer to Address of Current Screen Line
|
||||
pntr EQU $D3 ;Cursor Column on Current Line
|
||||
lnmx EQU $D5 ;Maximum Length of Physical Screen Line
|
||||
tblx EQU $D6 ;Current Cursor Physical Line Number
|
||||
insrt EQU $D8 ;Insert Mode (Number of Inserts)
|
||||
ldtb1 EQU $D9 ;Screen Line Link Table
|
||||
pntc EQU $F3 ;Pointer to Address of Current Screen Color RAM Location
|
||||
usrzp1 EQU $FB ;Free Byte for User Programs
|
||||
usrzp2 EQU $FC ;Free Byte for User Programs
|
||||
usrzp3 EQU $FD ;Free Byte for User Programs
|
||||
usrzp4 EQU $FE ;Free Byte for User Programs
|
||||
SRCLO EQU $22 ;Source Pointer LSB [Temporary Pointers]
|
||||
SRCHI EQU $23 ;Source Pointer MSB [Temporary Pointers]
|
||||
DSTLO EQU $25 ;Destination Pointer LSB [Temporary Pointers]
|
||||
DSTHI EQU $24 ;Destination Pointer MSB [Temporary Pointers]
|
||||
RDSEED EQU $A2 ;Random Seed [Software Jiffy Clock (Low Byte)]
|
||||
BLKLO EQU $FD ;Block Pointer LSB [Unused Byte]
|
||||
BLKHI EQU $FE ;Block Pointer MSB [Unused Byte]
|
||||
STKLO EQU $FD ;Stack Pointer LSB [Unused Byte]
|
||||
STKHI EQU $FE ;Stack Pointer MSB [Unused Byte]
|
||||
|
||||
;Basic and Kernal Working Storage
|
||||
buf EQU $0200 ;BASIC Line Editor Input Buffer
|
||||
lat EQU $0259 ;Kernal Table of Active Logical File Numbers
|
||||
fat EQU $0263 ;Kernal Table of Device Numbers for Each Logical File
|
||||
sat EQU $026D ;Kernal Table of Secondary Addressed for Each Logical File
|
||||
keyd EQU $0277 ;Keyboard Buffer (Queue)
|
||||
memstr EQU $0281 ;Pointer: Operating System Start of Memory
|
||||
memsiz EQU $0283 ;Pointer: Operating System End of Memory
|
||||
color EQU $0286 ;Current Foreground Color Text
|
||||
hibase EQU $0288 ;Top Page of Screen Memory
|
||||
xmax EQU $0289 ;Maximum Keyboard Buffer Size
|
||||
rptflg EQU $028A ;Flag: Which Key Will Repeat?
|
||||
kount EQU $028B ;Counter for Timing Delay Between Key Repeats
|
||||
shflag EQU $028D ;Flag: SHIFT/CTRL/Logo Keypress
|
||||
mode EQU $0291 ;Flag: Change Character Sets with SHIFT/Logo Keypress
|
||||
|
||||
user0 EQU $0310 ;Free Byte for User Programs
|
||||
user1 EQU $0311 ;Free Byte for User Programs
|
||||
user2 EQU $0312 ;Free Byte for User Programs
|
||||
user3 EQU $0313 ;Free Byte for User Programs
|
||||
user4 EQU $0334 ;Free Byte for User Programs
|
||||
user5 EQU $0335 ;Free Byte for User Programs
|
||||
user6 EQU $0336 ;Free Byte for User Programs
|
||||
user7 EQU $0337 ;Free Byte for User Programs
|
||||
user8 EQU $0338 ;Free Byte for User Programs
|
||||
user9 EQU $0339 ;Free Byte for User Programs
|
||||
user10 EQU $033A ;Free Byte for User Programs
|
||||
user11 EQU $033B ;Free Byte for User Programs
|
||||
tbffr EQU $033C ;Cassette I/O Buffer
|
||||
user12 EQU $03FC ;Free Byte for User Programs
|
||||
user13 EQU $03FD ;Free Byte for User Programs
|
||||
user14 EQU $03FE ;Free Byte for User Programs
|
||||
user15 EQU $03FF ;Free Byte for User Programs
|
||||
USER0 EQU $0310 ;Free Byte for User Programs
|
||||
USER1 EQU $0311 ;Free Byte for User Programs
|
||||
USER2 EQU $0312 ;Free Byte for User Programs
|
||||
STKSLO EQU $0313 ;Free Byte for User Programs
|
||||
STKSHI EQU $0334 ;Free Byte for User Programs
|
||||
STKELO EQU $0335 ;Free Byte for User Programs
|
||||
STKEHI EQU $0336 ;Free Byte for User Programs
|
||||
BLKSLO EQU $0337 ;Block Start LSB [Unused Byte]
|
||||
BLKSHI EQU $0338 ;Block Start MSB [Unused Byte]
|
||||
BLKELO EQU $0339 ;Block Start MSB [Unused Byte]
|
||||
BLKEHI EQU $033A ;Block End MSB [Unused Byte]
|
||||
STKSAV EQU $033B ;Machine Stack Storage [Unused Byte]
|
||||
TBFFR EQU $033C ;Cassette I/O Buffer
|
||||
TEMP0 EQU $03FC ;Temporary Variable [Unused Byte]
|
||||
TEMP1 EQU $03FD ;Temporary Variable [Unused Byte]
|
||||
TEMP2 EQU $03FE ;Temporary Variable [Unused Byte]
|
||||
TEMP3 EQU $03FF ;Temporary Variable [Unused Byte]
|
||||
|
||||
;Video RAM and ROM
|
||||
vicscn EQU $1000 ;Video Screen Memory Area (Unexpanded)
|
||||
chrrom EQU $8000 ;Character Generator ROM
|
||||
vicclr EQU $9400 ;Color RAM (Unexpanded)
|
||||
|
||||
;Kernal Routines
|
||||
chrin EQU $FFCF ;Input Character to Channel
|
||||
chrout EQU $FFD2 ;Output Character to Channel
|
||||
getin EQU $FFE4 ;Read Character from Keyboard Buffer
|
||||
VICSCN EQU $1000 ;Video Screen Memory Area (Unexpanded)
|
||||
CHRROM EQU $8000 ;Character Generator ROM
|
||||
VICCLR EQU $9400 ;Color RAM (Unexpanded)
|
||||
|
||||
;Machine Language Basic Stub
|
||||
ORG $1201 ;Start
|
||||
basic: DC $0C, $12 ; Pointer to Next Line (4108)
|
||||
BASIC: DC $0C, $12 ; Pointer to Next Line (4108)
|
||||
DC $00, $00 ; Line Number (0)
|
||||
DC $9E ; SYS
|
||||
DC $20 ; ' '
|
||||
|
@ -108,51 +49,50 @@ basic: DC $0C, $12 ; Pointer to Next Line (4108)
|
|||
DC $00 ;End of Line Marker
|
||||
DC $00, $00 ;End of Basic Program
|
||||
|
||||
start: TSX ;Get Stack Pointer
|
||||
STX user15 ;and Save for Exit
|
||||
START: TSX ;Get Stack Pointer
|
||||
STX STKSAV ;and Save for Exit
|
||||
JMP main ;Execute Program
|
||||
|
||||
exit: LDX user15 ;Retrieve Saved Stack Pointer
|
||||
EXIT: LDX STKSAV ;Retrieve Saved Stack Pointer
|
||||
TXS ;and Restore It
|
||||
RTS ;Return to BASIC
|
||||
|
||||
;Poll Keyboard for Character
|
||||
plkey EQU getin ;Read Character from Keyboard Buffer
|
||||
PLKEY EQU $FFE4 ;Aliased to Kernal GETIN Routine
|
||||
|
||||
;Get Character from Keyboard
|
||||
getkey:
|
||||
GETKEY: EQU PLKEY
|
||||
|
||||
;Wait for Character from Keyboard
|
||||
rdkey: JSR plkey ;Poll Keyboard
|
||||
BEQ getkey ;If No Key, Loop
|
||||
RDKEY: JSR GETKEY ;Poll Keyboard
|
||||
BEQ RDKEY ;If No Key, Loop
|
||||
RTS
|
||||
|
||||
;Delete Previous Character
|
||||
delchr: RTS
|
||||
DELCHR: LDA #DELKEY ;Load Delete Character
|
||||
JMP PRCHR ;Print and Return
|
||||
|
||||
;Advance Character to Next line
|
||||
newlin: LDA #$0D ;Load C/R into Accumulator
|
||||
|
||||
NEWLIN: LDA #RTNKEY ;Load C/R into Accumulator
|
||||
JMP PRCHR ;Print and Return
|
||||
|
||||
;Print Character to Console
|
||||
prchr EQU chrout ;
|
||||
PRCHR EQU $FFD2 ;Aliased to Kernal CHROUT Routine
|
||||
|
||||
;Print Byte as Two-Digit Hex Number to Console
|
||||
prbyte: PHA ;Save Accumulater
|
||||
PRBYTE: PHA ;Save Accumulater
|
||||
LSR ;Shift Hi Nybble to Low Nybble
|
||||
LSR
|
||||
LSR
|
||||
LSR
|
||||
JSR prhex ; and Print it
|
||||
JSR PRHEX ; and Print it
|
||||
PLA ;Restore Accumulator
|
||||
; and fall into prhex
|
||||
|
||||
|
||||
;Print Low Nybble as Hex Digit to Console
|
||||
prhex: AND #$0F ;Strip High Nybble
|
||||
PRHEX: AND #$0F ;Strip High Nybble
|
||||
CMP #$0A ;If Low Nybble >= 10
|
||||
BCC prhexc ;
|
||||
BCC PRHEXC ;
|
||||
ADC #$06 ; Convert ':' to 'A'...
|
||||
prhexc: ADC #$30 ;Convert to ASCII Character
|
||||
JMP prchr ;Print Hex Digit and Return
|
||||
|
||||
exit: RTS ;Return to Monitor
|
||||
|
||||
PRHEXC: ADC #$30 ;Convert to ASCII Character
|
||||
JMP PRCHR ;Print Hex Digit and Return
|
||||
|
|
Loading…
Reference in New Issue