Updated library modules and documentation

This commit is contained in:
Curtis F Kaylor 2018-08-02 05:10:14 -04:00
parent fb9f396240
commit fc987bb36e
17 changed files with 1103 additions and 300 deletions

457
doc/design.txt Normal file
View File

@ -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.

View File

@ -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.

74
doc/library.txt Normal file
View File

@ -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.

View File

@ -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:

View File

@ -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

View File

@ -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:

View File

@ -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>

34
doc/symbols.txt Normal file
View File

@ -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
~

36
doc/template.txt Normal file
View File

@ -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

View File

@ -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().

135
include/oric.a02 Normal file
View File

@ -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

28
include/oric.h02 Normal file
View File

@ -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

View File

@ -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

26
include/template.a02 Normal file
View File

@ -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

11
include/template.h02 Normal file
View File

@ -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();

View File

@ -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

View File

@ -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