diff --git a/doc/design.txt b/doc/design.txt new file mode 100644 index 0000000..bb2e676 --- /dev/null +++ b/doc/design.txt @@ -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 (IN) + CMP N + BEQ ENDIF + + LDA I ;IF (IN) + CMP N + BEQ ENDIF + block + +When chaining multiple && and/or || operators, the shortcut evaluation +effectively make them right-associative. \ No newline at end of file diff --git a/doc/func-idx.txt b/doc/func-idx.txt index 999c6f2..400eb19 100644 --- a/doc/func-idx.txt +++ b/doc/func-idx.txt @@ -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. diff --git a/doc/library.txt b/doc/library.txt new file mode 100644 index 0000000..c48a0fe --- /dev/null +++ b/doc/library.txt @@ -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. diff --git a/doc/memio.txt b/doc/memio.txt index 876e283..9805a07 100644 --- a/doc/memio.txt +++ b/doc/memio.txt @@ -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 #include The following functions are defined: diff --git a/doc/pointer.txt b/doc/pointer.txt index 9674656..6e1fa73 100644 --- a/doc/pointer.txt +++ b/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 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 diff --git a/doc/string.txt b/doc/string.txt index 088fbfd..c957924 100644 --- a/doc/string.txt +++ b/doc/string.txt @@ -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 #include The following functions are defined: diff --git a/doc/stringx.txt b/doc/stringx.txt index 8b04ef8..6a50f6c 100644 --- a/doc/stringx.txt +++ b/doc/stringx.txt @@ -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 #include #include diff --git a/doc/symbols.txt b/doc/symbols.txt new file mode 100644 index 0000000..58f8387 --- /dev/null +++ b/doc/symbols.txt @@ -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 + ~ diff --git a/doc/template.txt b/doc/template.txt new file mode 100644 index 0000000..b9cd99d --- /dev/null +++ b/doc/template.txt @@ -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 + #include + +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 diff --git a/doc/test.txt b/doc/test.txt index 46ecc56..f979a98 100644 --- a/doc/test.txt +++ b/doc/test.txt @@ -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(). diff --git a/include/oric.a02 b/include/oric.a02 new file mode 100644 index 0000000..f371370 --- /dev/null +++ b/include/oric.a02 @@ -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 diff --git a/include/oric.h02 b/include/oric.h02 new file mode 100644 index 0000000..56d9b59 --- /dev/null +++ b/include/oric.h02 @@ -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 + diff --git a/include/pointer.a02 b/include/pointer.a02 index 2b78f9f..cc6cb97 100644 --- a/include/pointer.a02 +++ b/include/pointer.a02 @@ -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 diff --git a/include/template.a02 b/include/template.a02 new file mode 100644 index 0000000..19a7eca --- /dev/null +++ b/include/template.a02 @@ -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 diff --git a/include/template.h02 b/include/template.h02 new file mode 100644 index 0000000..53f559f --- /dev/null +++ b/include/template.h02 @@ -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(); diff --git a/include/vic3k.a02 b/include/vic3k.a02 index 904117f..1919d7c 100644 --- a/include/vic3k.a02 +++ b/include/vic3k.a02 @@ -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 diff --git a/include/vic8k.a02 b/include/vic8k.a02 index fba2c9d..8695ab8 100644 --- a/include/vic8k.a02 +++ b/include/vic8k.a02 @@ -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