Merge branch 'master' into x16vera

This commit is contained in:
RevCurtisP 2019-11-20 11:13:02 -05:00 committed by GitHub
commit 4da225525b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
77 changed files with 4031 additions and 1567 deletions

5
.gitignore vendored
View File

@ -24,4 +24,7 @@ output
#Deprecated Files
*/oldclude
*/*.zip
*/*.zip
#Private Directories
notes

View File

@ -4,5 +4,6 @@ mainfile=src/c02.c
outfile=c02
c02: ${incfiles} ${mainfile}
gcc ${gccopts} ${incfiles} ${mainfile} -o ${outfile}
gcc ${gccopts} a02.h a02.c -o a02
clean:
rm ${outfile}
rm ${outfile} a02

View File

@ -43,7 +43,6 @@ but it may not be in a working state.
#pragma origin 8192 //Set start address of object code
#pragma zeropage $80 //Set start address of zero page variables
/* Constants */
#define TRUE = $FF ; //Constants
#define FALSE = 0
@ -54,50 +53,63 @@ struct record {char name[8]; char index;}; //Struct Definition
struct record rec; //Struct Declaration
/* Variables and Array Declarations */
char i, j; //Variables
zeropage p,q; //Variables in zeropage
const char nine = 9; //Const variable set to decimal literal
const char maxsiz = $FF; //Const variable set to hexadecimal literal
const char flag = %01010101; //Const variable set to binary literal
const char debug = #TRUE; //Const variable set to constant
char r[7]; //8 byte array 0 (decimal dimension)
char b, c, d, e, f, g, h; //8-bit Variables
int i, j; //16-bit Variables
zeropage char p, q; //8-bit Variables in Page 0
zeropage int u, v; //16-bit Variables in Page 0
const char nine = 9; //Const 8-bit variable set to decimal literal
const char maxsiz = $FF; //Const 8-bit variable set to hexadecimal literal
const char flag = %01010101; //Const 8-bit variable set to binary literal
const char debug = #TRUE; //Const 8-bit variable set to constant
const int k = $1234; //Const 16-bit variable set to hexadecimal literal
char r[7]; //8 byte Array (decimal dimension)
aligned char m[$FF]; //256 byte array aligned to page boundary
const char n = {1,2,3}; //Const array set to literal list
const char s = "string"; //Const array set to string literal
const char m = {1,2,3}; //Const array set to literal list
const char t = {"one", 1); //Const array set to mixed list
/* Functions Declarations */
void myfunc(); //Forward declaration of function
char myfunp(tmp1, tmp2, tmp3) {
//function code
}
char fnc(c) { /*function body */} //One 8-bit Parameter
char fnd(c,d) { /*function body */} //Two 8-bit Parameters
char fne(c,d,e) { /*function body */} //Three 8-bit Parameters
char fni(i) { /*function body */} //One 16-bit Parameter
char fnj(c,i) { /*function body */} //8-bit and 16-bit Parameters
/* Returning from a Function */
return c, d, e; //Return up to three 8-bit values
return c,j; //Return an 8-bit an 16-bit value
return i; //Return a 16-bit value
return; //No explicit return values
/* Assignments */
hmove; s80vid; //Implicit Assignments
x = 0; y = a; a = 1; //Register Assignments
b = c + d - e & f | g ^ h; //Assignment and Expression
r[i] = s[j+1] & t[k-1]; //Array Indexing
d[j] = r[a] + s[x] + t[y]; //Arrays Indexed by Register
r = (i>j) ? d[i] : e[j]; //Shortcut If
a<< ;b[i]>>; x++; y--; //Post-Operations
r[f] = m[g+1] & t[h-1]; //Array Indexing
r[j] = r[a] + s[x] + t[y]; //Arrays Indexed by Register
d = (e>f) ? d[e] : e[f]; //Shortcut If
b<< ;c[d]>>; x++; y--; //Post-Operations
/* Function Calls */
i = abs(n); j = min(b,c), plot(h,v,c); //Up to Three Char Arguments
q = div(m+n,d)) - t; n = mult(e+f, z); //Expression in First Arg Only
puts("string"); fputs(fp, &line); //Passing Strings and Arrays
setdst(&dst); n = strcpy(&src); //Using Multiple String Agruments
c = getc(); setptr(*,addrhi,addrlo); //No and Skipped Arguments
row,col = scnpos(); i,j,k = get3d(); //Plural Assignments
push d,r; mult(); pop p; //Pass Arguments via Stack
iprint(); inline "Hello World"; //Pass Inline String Argument
irect(); inline 10,10,100,100; //Pass Inline Char Arguments
icpstr(); inline &dst, &src; //Pass Inline Address Arguments
b = abs(c); d = min(e,f), plot(b,c,d); //Up to Three Char Arguments
b = div(c+d,e)) - f; c = mult(d+e, f); //Expression in First Arg Only
j = swap(i); j = ishift(b, i); //Pass Int or Char with Int
puts("string"); fputs(f, &s); //Passing Strings and Arrays
setdst(&r); b = strcpy(&s); //Using Multiple String Arguments
proc(@record, &record); //Pass Length and Address of Struct
c = getc(); setptr(?,g,h); //No Args and Skipped Arguments
b,c = scnpos(); d,e,f = get3d(); //Plural Assignments
push b,c; mult(); pop p; //Pass Arguments via Stack
iprint(); inline "Hello World"; //Pass Inline String Argument
irect(); inline 10,10,100,100; //Pass Inline Char Arguments
icpstr(); inline &r, &s; //Pass Inline Address Arguments
/* Control Structures */
if (c = 27) goto end;
if (n) q = div(n,d) else puts("Division by 0!");
if (b) e = div(f,g) else puts("Division by 0!");
if (b==0 || b>10 && b<20) fprint(n,"input %d in range");
c = 'A' ; while (c <= 'Z') { putc(c); c++; }
c = 'A' ; while (c <= 'Z') { putc(c); c++; }
while() { c=rdkey; if (c=0) continue; putchr(c); if (c=13) break; }
do c = rdkey(); while (c=0);
do {c = getchr(); putchr(c);} while (c<>13)

724
a02.c Normal file
View File

@ -0,0 +1,724 @@
/* Simple 6502 Assembler *
* for C02 Compiler *
* Uses DASM Syntax but *
* supports 65C02 Op Codes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "a02.h"
#define DEBUG FALSE
int debug; //Ouput Debug Info
enum otypes {BINFIL, PRGFIL}; //Object File Types
char objtyp; //Object File Type
int orgadr; //Origin Address
int curadr; //Current Address
int lstadr; //List Address
struct sym {int block; char name[MAXLBL+1]; int bytes, value, refrd;};
struct sym symbol; //Current Symbol
struct sym symtbl[MAXSYM]; //Global Symbol Table
int symcnt; //Number of Global Labels
int blknum; //Local Label Block Number (0 = Global)
char label[MAXSTR]; //Assembly Line Label
char mnmnc[MAXSTR]; //Opcode Mnemonic
char oprnd[MAXSTR]; //Opcode Mnemonic
char cmmnt[MAXSTR]; //Assembly Line Comment
char mcode[MAXSTR]; //Generated Bytes
char strng[MAXSTR]; //Parsed String
int opridx; //Index into Operand
unsigned char token, opmod; //OpCode Token, Modifier
unsigned int amode; //Addressing Modes
int zpage, opval; //ZeroPage Flag, Operand Value
char hexadr[6]; //Current Address in Hexadecimal
char bytstr[5]; //String Representation of Byte
char inplin[MAXSTR]; //Input Buffer
char *linptr; //Pointer into Input Buffer
int lineno; //Input File Line Number
int savlno; //Line Number (Saved)
int passno; //Assembler Pass Number (1 or 2)
int endasm; //End Assembly Flag
char prgnam[256]; //Assembler Path and Name (from Command Line)
char inpnam[256]; //Input File Name
char outnam[256]; //Output File Name
char lstnam[256]; //List File Name
char incnam[256]; //Include File Name
FILE *inpfil; //Input File Pointer
FILE *outfil; //Output File Pointer
FILE *lstfil; //List File Pointer
FILE *incfil; //Include File Pointer
/* Print Usage Info and Exit */
void usage(char* appnam) {
printf("Usage: %s [opts] asmfile objfile [lstfile]\n", appnam);
printf(" Opts: -p - Commodore PRG format\n");
printf(" -d - Output Debug Info\n");
exit(EXIT_FAILURE);
}
/* Print Error Message and Exit */
void xerror(char* format, char *s) {
if (lineno) fprintf(stderr, "%04d: ", lineno);
fprintf(stderr, format, s);
exit(EXIT_FAILURE);
}
/* Open File with Error Checking */
FILE * opnfil(char* name, char* mode) {
if (debug) printf("Opening file '%s' with mode '%s'\n", name, mode);
FILE *fp = fopen(name, mode);
if (!fp) xerror("Error Opening File '%s'\n", name);
return fp;
}
/* Skip Character in Input Line *
* Args: c - Character to Skip *
* Updates: linptr */
int skpchr(char c) {
if (*linptr == c) {linptr++; return TRUE;}
else return FALSE;
}
/* Skip Spaces in Input Line *
* Updates: linptr */
void skpspc(void) {
while (*linptr && *linptr <= ' ') linptr++;
}
/* Parse Word from Input Line *
* Args: skip - Skip Spaces Flag *
* *word - Buffer for Word *
* Updates: linptr *
* Returns: Word Found (TRUE/FALSE) */
int pword(int skip, char* word) {
int wrdlen = 0;
if (skip) skpspc();
while (isalnum(*linptr) || *linptr == '_') {
word[wrdlen++] = toupper(*linptr);
linptr++;
}
word[wrdlen] = 0; //Terminate String
if (wrdlen) return TRUE; else return FALSE;
}
struct sym *fndsym(int block, char* name) {
for (int i=0; i < symcnt; i++) {
if (symtbl[i].block != block || strcmp(symtbl[i].name,name)) continue;
return &symtbl[i];
}
return NULL;
}
/* Set Symbol Value and Size */
void setsym(int value, int bytes) {
if (debug) printf("Setting Symbol %s to %d\n", symbol.name, value);
symbol.value = value;
if (bytes) symbol.bytes = bytes;
else symbol.bytes = (value > 0xFF) ? 2 : 1;
symbol.refrd = FALSE;
}
/* Add Character to Beginning of String */
void pfxstr(char c, char* s) {
for (int i=strlen(s)+1; i; i--)
s[i] = s[i-1]; //Copy All Characters to the Right
s[0] = c; //Insert Character at Beginning
}
/* Parse Label from Input Line
* Sets: label
* Updates: linptr
* Returns: Label Found (TRUE/FALSE) */
int plabel(void) {
if (debug) puts("Parsing Label");
int block = (skpchr('.')) ? blknum : 0; //Local Label Block Number
int found = pword(FALSE, label); //Parse Word without Skipping Spaces
if (debug) {
if (found) printf("Found Label %s\n", label);
else puts("No Label Found");
}
skpchr(':'); //Skip Optional Label Terminator
if (found && passno == 1) {
if (label[0] && fndsym(block, label)) xerror("Duplicate Label %s Encountered\n", label);
if (debug) printf("Initializing Symbol %s\n", label);
symbol.block = block;
if (strlen(label) > MAXLBL) xerror("Label %s Too Long\n", label);
strcpy(symbol.name, label);
setsym(curadr, 0);
}
if (block) pfxstr('.', label);
skpspc(); //Skip to Mnemonic, Comment, or EOL
return found;
}
/* Copy Character to Operand and Increment */
int cpychr(int c) {
if (c && toupper(*linptr) != c) return FALSE;
if (opridx < MAXSTR) oprnd[opridx++] = toupper(*linptr);
linptr++;
return TRUE;
}
/* Evaluate Binary Number */
int evlbin() {
int result = 0;
cpychr('%');
while (isdigit(*linptr)) {
if (*linptr > '1') break;
result = (result << 1) + *linptr - '0';
cpychr(0);
}
return result;
}
/* Evaluate Binary Number */
int evlchr() {
int result = 0;
cpychr('\'');
result = *linptr;
cpychr(0);
cpychr('\'');
return result;
}
/* Evaluate Decimal Number */
int evldec() {
int result = 0;
while (isdigit(*linptr)) {
result = result * 10 + *linptr - '0';
cpychr(0);
}
return result;
}
/* Evaluate Hexadecimal Number */
int evlhex() {
int result = 0;
cpychr('$');
while (isxdigit(*linptr)) {
int digit = *linptr - '0';
if (digit > 9) digit = digit - 7;
result = (result << 4) + digit;
cpychr(0);
}
return result;
}
/* Evaluate Symbol */
struct sym *evlsym() {
char name[MAXSTR];
int block = (cpychr('.')) ? blknum : 0;
pword(TRUE, name);
for (int i=0; name[i]; i++) if (opridx<MAXSTR) oprnd[opridx++] = name[i];
struct sym *result = fndsym(block, name);
if (passno == 2 && result == NULL) xerror("Undefined Symbol %s\n", name);
if (result) result->refrd = TRUE; //Symbol was Referenced
return result;
}
/* Evaluate Term in Operand */
int evltrm() {
int result;
skpspc();
if (isalpha(*linptr) || *linptr == '.') {
struct sym *target = evlsym();
result = (target) ? target->value : 0x100;
}
else if (isdigit(*linptr))
result = evldec();
else switch(*linptr) {
case '$': result = evlhex(); break;
case '%': result = evlbin(); break;
case '\'': result = evlchr(); break;
default: result = -1;
}
skpspc();
if (debug) printf("Term Evaluated to %d\n", result);
return result;
}
/* Evaluate Operand */
int evlopd(int maxsiz) {
int result = 0;
int hilo = 0; //Return LSB (1) or MSB (2)
int prns; //Optional Parenthesis after Hi/Low Operator
if (debug) puts("Evaluating Operand");
skpspc();
if (cpychr('<')) hilo = 1;
else if (cpychr('>')) hilo = 2;
if (hilo) prns = cpychr('(');
result = evltrm();
if (result >= 0)
while (cpychr('+')) {
int opdval = evltrm();
if (opdval < 0) break;
result += opdval;
}
if (hilo) {
if (result < 0) xerror("Hi/Low Operator Requires Operand", "");
if (prns) cpychr(')'); //
switch (hilo) {
case 1: result = result & 0xFF; break; //LSB
case 2: result = result >> 8; break; //MSB
}
}
if (debug) printf("Operand Evaluated to %d\n", result);
if (result > maxsiz) xerror("Operand Value too Large\n", "");
return result;
}
/* Write Byte to Output File */
void outbyt(int b) {
if (curadr > -1) curadr++;
if (passno != 2) return;
fputc(b & 0xFF, outfil);
sprintf(bytstr, "%02X ", b);
if (strlen(mcode) < 9) strcat(mcode, bytstr);
}
/* Write Word to Output File */
void outwrd(int w) {
outbyt(w & 0xff);
outbyt(w >> 8);
}
/* Lookup Opcode */
int lkpopc(struct opc opl[]) {
if (debug) printf("Looking up Mnemonic %s\n", mnmnc);
token = 0xFF; //Set Token to Invalid
char mne[5]; strncpy(mne, mnmnc, 4); mne[4] = 0; //Truncate Mnemonic to Four Characters
for (int i=0; opl[i].name[0]; i++) {
if (strcmp(opl[i].name, mne)) continue;
token = opl[i].token;
amode = opl[i].amode;
if (debug) printf("Found token %02X, amode %04X\n", token, amode);
return TRUE;
}
return FALSE;
}
/* Assemble BYTE Pseudo-Op */
void asmbyt(void) {
if (debug) puts("Assembling BYTE Pseudo-Op");
do {
if (cpychr('"')) { //String Operand
while (!cpychr('"')) {outbyt(*linptr); cpychr(0); }
skpspc();
} else
outbyt(evlopd(0xFF)); //Evaluate Operand
} while (cpychr(','));
}
/* Assemble HEX Pseudo-Op */
void asmhex(void) {
if (debug) puts("Assembling HEX Pseudo-Op");
do {outbyt(evlhex(0xFF)); } while (cpychr(','));
}
/* Assemble WORD Pseudo-Op */
void asmwrd(void) {
do {
outwrd(evlopd(0xFFFF)); //Evaluate Operand
} while (cpychr(','));
}
/* Assemble FILL Pseudo-Op */
void asmaln(void) {
if (debug) puts("Assembling ALIGN Pseudo-Op");
int size = evlopd(0xFFFF); if (size < 2) return;
if (debug) printf("Aligning to %d Bytes\n", size);
int fill = size - (curadr % size); if (fill == size) return;
if (debug) printf("Filling %d Bytes\n", fill);
for (int i=0; i<fill; i++) outbyt(0);
}
/* Assemble FILL Pseudo-Op */
void asmfll(void) {
if (debug) puts("Assembling FILL Pseudo-Op");
int size = evlopd(0xFFFF);
if (debug) printf("Filling %d Bytes\n", size);
for (int i=0; i<size; i++) outbyt(0);
}
/* Assemble EQU Pseudo-Op */
void asmequ(void) {
if (label[0] == 0) xerror("EQUate without Label", 0);
setsym(evlopd(0xFFFF), 0);
}
/* Assemble ORG Pseudo-Op */
void asmorg(void) {
orgadr = evlopd(0xFFFF);
if (passno == 1 && symbol.name[0]) {
symbol.value = orgadr;
symbol.bytes = 2;
}
if (passno == 2 && objtyp == PRGFIL)
outwrd(orgadr);
curadr = orgadr;
lstadr = orgadr;
}
/* Assemble PROCESSOR Pseudo-Op */
void asmprc(void) {
skpspc();
while (isalnum(*linptr)) cpychr(0);
if (debug) printf("Ignoring Operand %s\n", oprnd);
}
/* Assemble SUBROUTINE Pseudo-Op */
void asmsub(void) {
blknum++;
sprintf(oprnd, "%d", blknum); opridx = strlen(oprnd);
if (debug) printf("Block Number set to %s\n", oprnd);
}
/* Assemble INCLUDE Pseudo-Op */
void asminf(void) {
int incidx = 0;
if (debug) puts("Assembling INCLUDE Pseudo-Op");
if (incfil) xerror("Nested INCLUDE not Allowed", "");
if (!cpychr('"')) xerror("File Name Must be Quoted", "");
while (*linptr && !cpychr('"')) {
char c = *linptr; if (c == '/') c = '\\'; //Reverse Slashes for DOS/Windows
incnam[incidx++] = c;
cpychr(0);
}
incnam[incidx] = 0; //Terminate Include Name
if (incidx == 0) xerror("INCLUDE requires file name\n", "");
if (debug) printf("Include File Set to Name to '%s'\n", incnam);
}
/* Assemble END Pseudo-Op */
void asmend(void) {
endasm = TRUE;
}
/* Assemble Pseudo-Op */
int asmpso(int dot) {
if (lkpopc(psolst) == FALSE && dot == FALSE) return FALSE;
skpspc();
if (debug) printf("Assembling Pseudo-Op %s, Token '%c'\n", mnmnc, token);
switch (token) {
case '=': asmequ(); break; //EQU
case 'B': asmbyt(); break; //BYTE
case 'H': asmhex(); break; //BYTE
case 'W': asmwrd(); break; //WORD
case 'F': asmfll(); break; //FILL
case 'S': asmsub(); break; //SUBRoutine
case 'I': asminf(); break; //INCLude
case '*': asmorg(); break; //ORG
case 'P': asmprc(); break; //PROCessor
case 'E': asmend(); break; //END
case 'A': asmaln(); break; //ALIGn
default: xerror("Undefined Pseudo-Op %s\n", mnmnc);
}
if (dot) pfxstr('.', mnmnc);
return TRUE;
}
/* Check for Valid Addressing Mode */
int chkmod(int mode) {
char* s = NULL; //Pointer to Addressing Mode Description
for (int i=0; amdesc[i].amode; i++)
if (amdesc[i].amode == mode) {s = amdesc[i].desc; break;}
if (debug) printf("Checking Addressing Mode %s, %04X against %04X\n", s, mode, amode);
if (mode & amode) return TRUE;
xerror("Invalid Addressing Mode %s", s);
}
/* Assemble Branch Opcode */
void asmbrn(int setzp) {
int offset = 0;
int ofsadj = (setzp) ? 2 : 3; //Offset Adjustment
if (debug) printf("Assembling Branch Opcode Token 0x%02X\n", token);
zpage = setzp;
if (isalpha(*linptr) || *linptr =='.') {
struct sym *target = evlsym();
if (target) offset = (target->value - curadr - ofsadj);
}
else if (cpychr('+')) offset = evlopd(0xFF);
else if (cpychr('-')) offset = -evlopd(0xFF);
else {
opval = evlopd(0xFFFF);
if (opval < 0) xerror("Illegal Branch Operand\n", "");
offset = opval - curadr - 2;
}
if (debug) printf("Calculated Branch Offset of %d\n", offset);
if ((offset > 127 || offset < -128) && passno == 2)
xerror("Branch Out of Range\n", "");
if (debug) printf("Branch Offset %d\n", offset);
opval = offset & 0xFF;
}
/* Assemble Zero Page, Relative Opcode */
void asmzpr(void) {
int bitno = -1;
if (debug) printf("Assembling ZeroPage (Relative) Opcode Token 0x%02X\n", token);
if (strlen(mnmnc) < 4) {opmod = evlopd(7) << 4; cpychr(','); skpspc();} //Set Modifier to Bit Position
int zpval = evlopd(0xFF); cpychr(','); skpspc();//Get ZeroPage Operand
if (zpval < 0) xerror ("Instruction %s requires Multiple Operands\n", mnmnc);
if (amode == 0x0004) {zpage = TRUE; opval = zpval;} //RMB, SMB - Zero Page Operand
else {asmbrn(FALSE); opval = opval << 8 | zpval;} //BBR, BBS - Combine Operanda
}
/* Assemble Immediate Mode Instruction */
void asmimd(void) {
if (debug) printf("Assembling Immediate Opcode Token 0x%02X\n", token);
opval = evlopd(0xFF);
zpage = TRUE;
opmod = 0x08; //Immediate
}
/* Assemble Indirect Mode Instruction */
void asmind(void) {
if (debug) puts("Assembling Indirect Mode Instruction");
zpage = TRUE; opval = evlopd(0xFFFF);
if (cpychr(',') && cpychr('X') && chkmod(INDCX)) cpychr(')'); ////(Indirect,X) opmod=0
else if (cpychr(')')) {
if (cpychr(',') && cpychr('Y') && chkmod(INDCY)) opmod = 0x10; //(Indirect),Y
else if (chkmod(INDCT)) opmod = 0x11; //(Indirect)
if (token == 0x4C) zpage = FALSE; //JMP (Indirect Absolute)
}
else chkmod(0); //Illegal Addressing Mode
if (zpage && opval > 0x00FF) xerror("Operand Value too Large\n", "");
}
/* Assemble Implied/Accumulator/Absolute/ZeroPage Mode Instruction */
void asmiaz(void) {
opval = evlopd(0xFFFF);
if (opval < 0) {
if (amode != IMPLD) //Implied
if (chkmod(ACMLT)) opmod = 0x08; //Accumulator
return;
}
if (debug) printf("Assembling Absolute/ZeroPage 0x%02X\n", token);
zpage = (opval <= 0xff) ? TRUE : FALSE;
if (zpage && chkmod(ZPAGE)) opmod = 0x04; //ZeroPage
else if (chkmod(ABSLT)) opmod = 0x0C; //Absolute
if (cpychr(',')) {
if (cpychr('X')) {
if (zpage && chkmod(ZPAGX)) opmod = 0x14; //ZeroPage,X
else if (chkmod(ABSLX)) opmod = 0x1C; //Absolute,X
} else if (cpychr('Y')) {
if (zpage && (token == 0x82 || token == 0xA2))
opmod = 0x14; //ZeroPage,Y
else {zpage = FALSE; opmod = 0x18;} //Absolute,Y
} else chkmod(0); //Illegal Addressing Mode
}
}
/* Fix Opcode (if needed) */
unsigned char fixopc(void) {
if (debug) printf("Fixing OpCode $%02X+$%02X\n", token, opmod);
for (int i=0; opfix[i].token; i++)
if (opfix[i].token == token && opfix[i].opmod == opmod)
return opfix[i].opcode;
return token + opmod;
}
/* Ouput Opcode debug Info */
void dbgopc(void) {
printf("token=$%02X, opmod=$%02X, Address Mode: ", token, opmod);
if (amode == 0x1004) puts("ZeroPage, Relative");
else if (amode == 0x0004) puts("ZeroPage");
else switch (opmod) {
case 0x00: if (amode == IMPLD) puts("Implied"); else puts("(Indirect,X)"); break;
case 0x08: if (opval < 0) puts("Accumulator"); else puts("#Immediate"); break;
case 0x10: puts("(Indirect),Y"); break;
case 0x11: puts("(Indirect)"); break;
case 0x04: puts("ZeroPage"); break;
case 0x0C: puts("Absolute"); break;
case 0x14: if ((token == 0x82 || token == 0xA2)) puts("ZeroPage,Y");
else puts("ZeroPage,X"); break;
case 0x1C: puts("Absolute,X"); break;
case 0x18: puts("Absolute,Y"); break;
default: puts("UNKOWN");
}
if (opval < 0) puts("No Operand");
else {
printf("Operand Value %d, ", opval);
if (zpage) puts("Zero Page"); else puts("Absolute");
}
}
/* Assemble Opcode */
int asmopc(int dot) {
opmod = 0;
if (asmpso(dot)) return TRUE; //Check For/Assemble Pseudo-Op
if (lkpopc(opclst) == FALSE) xerror("Invalid Mnemonic %s\n", mnmnc);
if (debug) printf("Assembling Opcode Token 0x%02X, ", token);
if (debug) printf("Addressing Mode Mask 0x%04X\n", amode);
skpspc();
if (amode == RELTV) asmbrn(TRUE); //Branch (Relative) Instruction
else if (amode == 0x0004 || amode == 0x1004) asmzpr(); //Branch (Relative) Instruction
else if (cpychr('#')) asmimd(); //Assemble Implied Instruction
else if (cpychr('(')) asmind(); //Assemble Indirect Instruction
else asmiaz(); //Assemble Implied/Accumulator/Absolute/ZeroPage Instruction
if (debug) dbgopc();
int opcode = fixopc();
if (debug) printf("Writing OpCode $%02X\n", opcode);
outbyt(opcode);
if (debug) printf("Writing %s Operand %d\n", zpgabs[-zpage], opval);
if (opval >= 0) {
if (zpage) outbyt(opval); //Byte Operand
else outwrd(opval); //Word Operand
}
return TRUE;
}
/* Parse Opcode Mnemonic from Input Line
* Sets: mnmnc
* Updates: linptr
* Returns: Label Found (TRUE/FALSE) */
int pmnmnc(void) {
if (debug) puts("Parsing Mnemonic");
int dot = cpychr('.'); //Optional Dot before Pseudo-Op
int found = pword(TRUE, mnmnc);
opridx = 0; //Initialize Operand Index
if (found) asmopc(dot);
oprnd[opridx] = 0; //Terminate Operand String
return found;
}
/* Parse Comment from Input Line
* Sets: cmmnt
* Updates: linptr */
void pcmmnt(void) {
skpspc();
int i = 0;
while (*linptr >= ' ') cmmnt[i++] = *linptr++;
cmmnt[i] = 0; //Terminate Comment
if (debug) {if (i) printf("Comment: %s\n", cmmnt); else puts("No Comment Found");}
}
/* Add Label to Symbol Table */
void addsym() {
if (symbol.value<0) xerror("Origin Not Set", "");
memcpy(&symtbl[symcnt++], &symbol, sizeof(symbol));
}
/* Open Include File */
void opninc(void) {
if (debug) printf("Opening Include File %s\n", incnam);
if (lstfil) fputs("\n", lstfil);
incfil = opnfil(incnam, "r");
savlno = lineno;
lineno = 1;
}
/* Close Include File */
void clsinc(void) {
if (debug) printf("Closing Include File %s\n", incnam);
if (lstfil) fputs("\n", lstfil);
fclose(incfil);
incfil = NULL;
incnam[0] = 0;
lineno = savlno;
endasm = FALSE; //Clear End Flag for Return to Maun File
}
/* Assemble Input File (Two Pass) *
* Args: pass - Assembly Pass (1 or 2) *
* Requires: inpfil - Input File Pointer *
* Uses: inplin - Input Line Buffer *
* lineno - Input File Line Number */
void asmfil(int pass) {
endasm = FALSE; //Reset End Assembly Flag
passno = pass; //Assembly Pass Number
if (debug) printf("Assembling Pass %d\n", pass);
lineno = 1; //Initialize Input File Line Number
blknum = 1; //Initialize Local Block Number
orgadr = -1; //Origin Address Not Set
curadr = orgadr; //Set Current Address to Origin
if (debug) printf("Rewinding Input File\n");
rewind(inpfil); //Start at Beginning of Input File
while (TRUE) {
if (incfil) linptr = fgets(inplin, MAXSTR, incfil);
else linptr = fgets(inplin, MAXSTR, inpfil);
if (endasm || linptr == NULL) {if (incfil) {clsinc(); continue;} else break;}
if (debug) printf("%05d %04X: %s", lineno, curadr, inplin);
lstadr = curadr; //Set List Address
mcode[0] = 0; //Clear Generated Macbine Code
plabel(); //Parse Label
pmnmnc(); //Parse Mnemonic
pcmmnt(); //Parse Comment
if (passno == 1 && label[0]) addsym(); //Add Label to Table
if (passno == 2) {
if (lstadr < 0) hexadr[0] = 0; else sprintf(hexadr, "%04X", lstadr);
fprintf(lstfil, "%05d %-4s %-9s%-7s %-5s %-16s %s\n", lineno, hexadr, mcode, label, mnmnc, oprnd, cmmnt );
fflush(lstfil); //Flush Output Buffer in case of Segmentation Fault
}
lineno++;
if (incnam[0] && incfil == NULL) opninc(); //Open Include File
}
}
/* Print Symbol Table */
void prtsym(void) {
fprintf(lstfil, "\n%s Symbol Table\nBlock Name Size Value Rfd\n", "Global");
for (int i=0; i<symcnt; i++) {
int refrd = (symtbl[i].refrd) ? '*' : ' ';
fprintf(lstfil, "%5d %-8s %4d %5d %c \n", symtbl[i].block, symtbl[i].name, symtbl[i].bytes, symtbl[i].value, refrd);
}
}
/* Parse Command Line Option */
int pcoptn(char *argval) {
if (argval[0] != '-') return FALSE;
char option = toupper(argval[1]);
if (debug) printf(" Option '%c'\n", option);
switch(option) {
case 'D': debug = TRUE; break; //Enable debug Output
case 'P': objtyp = PRGFIL; break; //Commodore PRG File
default: xerror("Illegal Command Line Option %s\n", argval);
}
return TRUE;
}
/* Parse Command Line Arguments */
void pcargs(int argc, char *argv[]) {
int argnum = 0;
for (int arg = 0; arg<argc; arg++) {
if (debug) printf("Arg %d='%s'\n", arg, argv[arg]);
if (arg == 0) {strcpy(prgnam, argv[arg]); continue;}
if (pcoptn(argv[arg])) continue;
switch (argnum++) {
case 0: strcpy(inpnam, argv[arg]); break;
case 1: strcpy(outnam, argv[arg]); break;
case 2: strcpy(lstnam, argv[arg]); break;
default: xerror("Too Many Arguments\n", "");
}
}
if (argnum<2) usage(argv[0]);
}
int main(int argc, char *argv[]) {
debug = DEBUG; //Initialize Debug Flag
lstnam[0] = 0; lstfil = NULL; //Default to No List File
incnam[0] = 0; incfil = NULL; //Include File Not Opened
lineno = 0; //No Line Number (yet)
objtyp = BINFIL; //Default Object File Type to Binary
pcargs(argc, argv); //Parse Command Line Arguments
inpfil = opnfil(inpnam, "r"); //Open Input File
outfil = opnfil(outnam, "wb"); //Open Output File
if (lstnam[0]) //If List File Name Specified
lstfil = opnfil(lstnam, "w"); // Open List File
asmfil(1); //Assemble Input File (First Pass)
asmfil(2); //Assemble Input File (First Pass)
if (lstfil && symcnt) prtsym(); //Print Symbol Table
exit(0); //Exit with No Errors
}

115
a02.h Normal file
View File

@ -0,0 +1,115 @@
/* Definitions for A02 Assembler */
#define MAXSTR 128 //Maximum String Length
#define MAXLBL 8 //Maximum Symbol Length
#define MAXSYM 1024 //Maximum Number of Global Labels
#define FALSE 0
#define TRUE -1
/* Address Mode Bit Masks */
#define ACMLT 0x0001 //Accumulator [$xA]
#define IMMDT 0x0002 //*Immediate [w/Acc]
#define ZPAGE 0x0004 //Zero Page
#define ZPAGX 0x0008 //*Zero Page,X
//#define ZPAGY 0x0010 //*Zero Page,Y [By OpCodes]
#define ABSLT 0x0020 //Absolute
#define ABSLX 0x0040 //*Absolute,X [fixops()]
#define ABSLY 0x0080 //Absolute,Y
#define IMPLD 0x0100 //*Implied [x0001]
#define INDCT 0x0200 //(Indirect)
#define INDCX 0x0400 //(Indirect,X)
#define INDCY 0x0800 //(Indirect),Y
#define RELTV 0x1000 //Relative
char zpgabs[][] = {"Absolute", "ZeroPage"};
struct amd {int amode; char desc[12];};
struct amd amdesc[] = {
{ACMLT, "Accumulator"},
{IMMDT, "Immediate"},
{ZPAGE, "Zero Page"},
{ZPAGX, "Zero Page,X"},
{ABSLT, "Absolute"},
{ABSLX, "Absolute,X"},
{ABSLY, "Absolute,Y"},
{IMPLD, "Implied"},
{INDCT, "(Indirect)"},
{INDCX, "(Indirect,X)"},
{INDCY, "(Indirect),Y"},
{RELTV, "Relative"},
{0, ""}
};
struct opc {char name[5], token; int amode;};
struct opc psolst[] = {
{"BYTE", 'B', 0}, {"HEX", 'H'}, {"WORD", 'W', 0}, {"EQU", '=', 0}, {"FILL", 'F', 0},
{"INCL", 'I', 0}, {"SUBR", 'S', 0}, {"DC", 'B', 0}, {"DS", 'F', 0}, {"ALIG", 'A', 0},
{"ORG", '*', 0}, {"PROC", 'P', 0}, {"END", 'E', 0}, {"", 0, 0}
};
struct opc opclst[] = {
{"BRK", 0x00, 0x0100}, {"NOP", 0xEA, 0x0100}, {"STP", 0xDB, 0x0100}, {"WAI", 0xCB, 0x0100},
{"DEX", 0xCA, 0x0100}, {"DEY", 0x88, 0x0100}, {"INX", 0xE8, 0x0100}, {"INY", 0xC8, 0x0100},
{"PHA", 0x48, 0x0100}, {"PHP", 0x08, 0x0100}, {"PHX", 0xDA, 0x0100}, {"PHY", 0x5A, 0x0100},
{"PLA", 0x68, 0x0100}, {"PLP", 0x28, 0x0100}, {"PLX", 0xFA, 0x0100}, {"PLY", 0x7A, 0x0100},
{"CLC", 0x18, 0x0100}, {"CLD", 0xD8, 0x0100}, {"CLI", 0x58, 0x0100}, {"CLV", 0xB8, 0x0100},
{"SEC", 0x38, 0x0100}, {"SED", 0xF8, 0x0100}, {"SEI", 0x78, 0x0100},
{"TAX", 0xAA, 0x0100}, {"TAY", 0xA8, 0x0100}, {"TSX", 0xBA, 0x0100},
{"TXA", 0x8A, 0x0100}, {"TYA", 0x98, 0x0100}, {"TXS", 0x9A, 0x0100},
{"RTI", 0x40, 0x0100}, {"RTS", 0x60, 0x0100},
{"BCS", 0xB0, 0x1000}, {"BEQ", 0xF0, 0x1000}, {"BMI", 0x30, 0x1000}, {"BVS", 0x70, 0x1000},
{"BCC", 0x90, 0x1000}, {"BNE", 0xD0, 0x1000}, {"BPL", 0x10, 0x1000}, {"BVC", 0x50, 0x1000},
{"BRA", 0x80, 0x1000},
{"LDA", 0xA1, 0x0EFE}, {"ADC", 0x61, 0x0EFE}, {"AND", 0x21, 0x0EFE}, {"CMP", 0xC1, 0x0EFE},
{"STA", 0x81, 0x0EFE}, {"SBC", 0xE1, 0x0EFE}, {"ORA", 0x01, 0x0EFE}, {"EOR", 0x41, 0x0EFE},
{"ASL", 0x02, 0x007D}, {"ROL", 0x22, 0x007D}, {"INC", 0xE2, 0x007D}, {"LSR", 0x42, 0x007D},
{"ROR", 0x62, 0x007D}, {"DEC", 0xC2, 0x007D},
{"RMB0", 0x07, 0x0004}, {"RMB1", 0x17, 0x0004}, {"RMB2", 0x27, 0x0004}, {"RMB3", 0x37, 0x0004},
{"RMB4", 0x47, 0x0004}, {"RMB5", 0x57, 0x0004}, {"RMB6", 0x67, 0x0004}, {"RMB7", 0x77, 0x0004},
{"SMB0", 0x87, 0x0004}, {"SMB1", 0x97, 0x0004}, {"SMB2", 0xA7, 0x0004}, {"SMB3", 0xB7, 0x0004},
{"SMB4", 0xC7, 0x0004}, {"SMB5", 0xD7, 0x0004}, {"SMB6", 0xE7, 0x0004}, {"SMB7", 0xF7, 0x0004},
{"RMB", 0x07, 0x0004}, {"SMB", 0x87, 0x0004},
{"BBR0", 0x0F, 0x1004}, {"BBR1", 0x1F, 0x1004}, {"BBR2", 0x2F, 0x1004}, {"BBR3", 0x3F, 0x1004},
{"BBR4", 0x4F, 0x1004}, {"BBR5", 0x5F, 0x1004}, {"BBR6", 0x6F, 0x1004}, {"BBR7", 0x7F, 0x1004},
{"BBS0", 0x8F, 0x1004}, {"BBS1", 0x9F, 0x1004}, {"BBS2", 0xAF, 0x1004}, {"BBS3", 0xBF, 0x1004},
{"BBS4", 0xCF, 0x1004}, {"BBS5", 0xDF, 0x1004}, {"BBS6", 0xEF, 0x1004}, {"BBS7", 0xFF, 0x1004},
{"BBR", 0x0F, 0x1004}, {"BBS", 0x8F, 0x1004},
{"TRB", 0x10, 0x0024}, {"TSB", 0x00, 0x0024},
{"CPX", 0xE0, 0x0026}, {"CPY", 0xC0, 0x0026},
{"LDX", 0xA2, 0x00A6}, {"STX", 0x82, 0x00A6},
{"BIT", 0x20, 0x006E},
{"STZ", 0x60, 0x006C},
{"JMP", 0x4C, 0x0620},
{"JSR", 0x14, 0x0020},
{"LDY", 0xA0, 0x006E},
{"STY", 0x80, 0x002C},
{"", 0, 0}
};
struct opf {unsigned char token, opmod, opcode;};
struct opf opfix[] = {
{0x20, 0x08, 0x89},
{0xE0, 0x08, 0xE0},
{0xC0, 0x08, 0xC0},
{0xA0, 0x08, 0xA0},
{0xA2, 0x08, 0xA2},
{0xC2, 0x08, 0x3A},
{0xE2, 0x08, 0x1A},
{0x60, 0x0C, 0x9C},
{0x60, 0x1C, 0x9E},
{0xA2, 0x18, 0xBE},
{0x82, 0x18, 0xBC},
{0x4C, 0x0C, 0x4C},
{0x4C, 0x11, 0x6C},
{0x4C, 0x00, 0x7C},
{0,0,0}
};

10
c02.ppj
View File

@ -8,7 +8,7 @@ POC_PROJECT_TYPE = 13#
POC_PROJECT_OUTPUTDIR = output#
POC_PROJECT_RESULTDIR = .#
POC_PROJECT_ARGUMENTS = #
POC_PROJECT_WORKPATH = .#
POC_PROJECT_WORKPATH = src#
POC_PROJECT_EXECUTOR = #
POC_PROJECT_ZIPEXTRA = #
CC = pocc.exe#
@ -153,8 +153,10 @@ output\label.obj: \
src\label.c \
src\asm.h \
src\common.h \
src\files.h \
src\label.h \
src\parse.h
src\parse.h \
src\vars.h
$(CC) $(CCFLAGS) "$!" -Fo"$@"
#
@ -164,9 +166,11 @@ output\parse.obj: \
src\parse.c \
src\asm.h \
src\common.h \
src\expr.h \
src\files.h \
src\label.h \
src\parse.h
src\parse.h \
src\stmnt.h
$(CC) $(CCFLAGS) "$!" -Fo"$@"
#

3
ca02.sh Normal file
View File

@ -0,0 +1,3 @@
echo "Compiling a02.c"
gcc -o a02 a02.c

View File

@ -35,3 +35,7 @@ void newlin(); //Advance cursor to beginning of next line
char putchr(); //Print ASCII character to Console
void setdst(); //Set Destination Pointer
void setsrc(); //Set Source Pointer
//System Labels
start: //Start of Code
exit: //Return to Operating System

View File

@ -1,8 +1,26 @@
;Screen Control Assembly Lanuage Routines for Apple 1
SUBROUTINE _SCREEN
SMTEXT EQU $00 ;Default Text Screen
SMWIDE EQU $FF ;Wide Text Screen (Undefined)
;Set Screen Mode
SETSCR: CMP SMTEXT ;If Default Text Screen
BEQ GETSCR ;Return Return 0
LDA #$FF ;Else Return ERROR
RTS
;Else Return 0
;Get Screen Mode
GETSCR: LDA #0 ;Return 0 (Default Text Mode)
RTS
;Clear the Screen
CLRSCR: RTS ;Do Nothing (Drop to RTS)
;Move Cursor Home
CRSRHM EQU CLRSCR ;No Action
;Move Cursor to Specified Coordinates
SETPOS EQU CLRSCR ;No Action

View File

@ -2,6 +2,10 @@
* screen - Screen Control Routines for C02 *
********************************************/
/* Screen Modes for getscr() and setscr() */
#define SMTEXT $00 //System Default Text Mode
#define SMWIDE $FF //Wide Screen Text Mode (Unsupported)
/* Clear the Screen */
void clrscn();
@ -13,6 +17,10 @@ void crsrhm();
* cursor row */
char getpos();
/* Get Screen Mode *
* Returns: char mode - Current Screen Mode */
char getscr();
/* Get Screen Size *
* Returns: width in columns *
* height in rows */
@ -22,3 +30,9 @@ char getsiz();
* Args: column - screen column (0 = left) *
* row - screen line (0 = top) */
void setpos();
/* Set Screen Mode *
* Args: char mode - screen mode *
* 0 = default text mode *
* Returns: $FF if Mode Invalid */
char setscr();

View File

@ -1,5 +1,20 @@
;Screen Control Assembly Lanuage Routines for Apple II
SUBROUTINE _SCREEN
SMTEXT EQU $00 ;Default Text Screen
SMWIDE EQU $FF ;Wide Text Screen (Undefined)
;Set Screen Mode
SETSCR: CMP SMTEXT ;If Default Text Screen
BEQ GETSCR ;Return Return 0
LDA #$FF ;Else Return ERROR
RTS
;Else Return 0
;Get Screen Mode
GETSCR: LDA #0 ;Return 0 (Default Text Mode)
RTS
;Clear the Screen
CLRSCR: EQU $FC58 ;Applesoft Routine HOME

View File

@ -1,6 +1,10 @@
/********************************************
* screen - Screen Control Routines for C02 *
********************************************/
/*****************************************
* Screen Control Functions for Apple II *
****************************************/
/* Screen Modes for getscr() and setscr() */
#define SMTEXT $00 //System Default Text Mode
#define SMWIDE $FF //Wide Screen Text Mode (Unsupported)
/* Clear the Screen */
void clrscn();
@ -18,7 +22,17 @@ char getpos();
* height in rows */
char getsiz();
/* Get Screen Mode *
* Returns: char mode - Current Screen Mode */
char getscr();
/* Move Cursor to Specified Position *
* Args: column - screen column (0 = left) *
* row - screen line (0 = top) */
void setpos();
/* Set Screen Mode *
* Args: char mode - screen mode *
* 0 = default text mode *
* Returns: $FF if Mode Invalid */
char setscr();

View File

@ -1,26 +1,29 @@
; c02 Program Initialization Code for Unexpanded VIC-20
; c02 Program Initialization Code for Commodore 64
;PETSCII Key Mappings
DELKEY EQU $14 ;Delete/Backspace Key (Delete)
ESCKEY EQU $03 ;Escape/Stop Key (RUN/STOP)
RTNKEY EQU $0D ;Return/Enter Key (RETURN)
DELKEY EQU $14 ;Delete/Backspace Key (Delete)
ESCKEY EQU $03 ;Escape/Stop Key (RUN/STOP)
RTNKEY EQU $0D ;Return/Enter Key (RETURN)
;Zero Page Variables
SRCLO EQU $22 ;Source Pointer LSB [Temporary Pointers]
SRCHI EQU $23 ;Source Pointer MSB [Temporary Pointers]
DSTLO EQU $24 ;Destination Pointer LSB [Temporary Pointers]
DSTHI EQU $25 ;Destination Pointer MSB [Temporary Pointers]
BLKLO EQU $26 ;Block Pointer LSB [Floating Point Work Area]
BLKHI EQU $27 ;Block Pointer MSB [Floating Point Work Area]
STKLO EQU $28 ;Stack Pointer LSB [Floating Point Work Area]
STKHI EQU $29 ;Stack Pointer MSB [Floating Point Work Area]
BFRLO EQU $35 ;Buffer Pointer LSB [Temporary String Pointer]
BFRHI EQU $36 ;Buffer Pointer MSB [Temporary String Pointer]
RDSEED EQU $A2 ;Random Seed [Software Jiffy Clock (Low Byte)]
TEMP0 EQU $FB ;Temporary Variable [Unused Byte]
TEMP1 EQU $FC ;Temporary Variable [Unused Byte]
TEMP2 EQU $FD ;Temporary Variable [Unused Byte]
TEMP3 EQU $FE ;Temporary Variable [Unused Byte]
XMBANK EQU $0A ;Extended Memory Bank (Load/Verify Flag)
XADRLO EQU $0B ;Ext Memory Address LSB (Text Index/Array Size)
XADRHI EQU $0C ;Ext Memory Address MSB (Array Dimension Fkags)
SRCLO EQU $22 ;Source Pointer LSB [Temporary Pointers]
SRCHI EQU $23 ;Source Pointer MSB [Temporary Pointers]
DSTLO EQU $24 ;Destination Pointer LSB [Temporary Pointers]
DSTHI EQU $25 ;Destination Pointer MSB [Temporary Pointers]
BLKLO EQU $26 ;Block Pointer LSB [Floating Point Work Area]
BLKHI EQU $27 ;Block Pointer MSB [Floating Point Work Area]
STKLO EQU $28 ;Stack Pointer LSB [Floating Point Work Area]
STKHI EQU $29 ;Stack Pointer MSB [Floating Point Work Area]
BFRLO EQU $35 ;Buffer Pointer LSB [Temporary String Pointer]
BFRHI EQU $36 ;Buffer Pointer MSB [Temporary String Pointer]
RDSEED EQU $A2 ;Random Seed [Software Jiffy Clock (Low Byte)]
TEMP0 EQU $FB ;Temporary Variable [Unused Byte]
TEMP1 EQU $FC ;Temporary Variable [Unused Byte]
TEMP2 EQU $FD ;Temporary Variable [Unused Byte]
TEMP3 EQU $FE ;Temporary Variable [Unused Byte]
;System Variables
USER3 EQU $0313 ;Free Byte for User Programs
@ -51,7 +54,7 @@ FSFLFA EQU $F314 ;Find Logical File A
;Machine Language Basic Stub
ORG $0801 ;Start of Basic Program
BASIC: DC $0C, $10 ;Pointer to Next Line (4109)
BASIC: DC $0C, $08 ;Pointer to Next Line
DC $00, $00 ;Line Number (0)
DC $9E ;SYS
DC $20 ;' '
@ -91,4 +94,8 @@ NEWLIN: LDX #0 ;Store 0
STX $D3 ;in Cursor Column and
JMP $E87C ;Execute NXTLINE Routine
;Print Zero Delimited String to Screen
PUTSTR: TXA ;Copy LSB to Accumulator
JMP $AB1E ;Execute STROUT
INCLUDE "../include/prbyte.a02" ;PRBYTE and PRHEX routine

View File

@ -1,6 +1,6 @@
;Joystick Assembly Language Module for C64
JYSTKS EQU $04 ;Number of Joysticks
JYSTKS EQU $02 ;Number of Joysticks
;Joystick Bit Masks
JOYUP EQU $01 ;Bit 0 - Up
@ -12,14 +12,11 @@ JOYB0 EQU $10 ;Bit 4 - Button
;Read Joystick
JOYSTK: CMP #JYSTKS ;If Invalid Joystick#
BCS JOYSTZ ; Return Error
EOR #1 ;Invert Joystick #
TAX ;Copy Joystick # to X
LDA $0284,X ;Read Trigger Control Register
ROR ;Move Bit 0 into Carry
LDA $DC00,X ;Read Joystick Shadow Register
EOR #$FF ;Invert and
AND #$0F ;Mask Bits
BCS JOYSTX ;If Trigger Pressed
ORA #$10 ; Set Bit 4
HOYSTX: RTS
AND #$1F ;Mask Bits
JOYSTX: RTS
JOYSTZ: LDA #$FF ;Return Error
RTS

37
include/c64/keydef.a02 Normal file
View File

@ -0,0 +1,37 @@
;PETSCII Key Code Definitions
;for Commmodore 64 Computer
KEYBCK EQU $00 ;Backspace [N/A]
KEYBRK EQU $03 ;Break (RUN/STOP)
KEYCLR EQU $93 ;Clear (Shift-CLR/HOME)
KEYCPY EQU $00 ;Copy [N/A]
KEYDEL EQU $14 ;Delete
KEYDN EQU $11 ;Cursor Down
KEYESC EQU $00 ;Escape [N/A]
KEYFN1 EQU $85 ;F1 (F1/F2)
KEYFN2 EQU $89 ;F2 (Shift-F1/F2)
KEYFN3 EQU $86 ;F3 (F3/F4)
KEYFN4 EQU $8A ;F4 (Shift-F3/F4)
KEYFN5 EQU $87 ;F5 (F5/F6)
KEYFN6 EQU $8B ;F6 (Shift-F5/F6)
KEYFN7 EQU $88 ;F7 (F7/F8)
KEYFN8 EQU $8C ;F8 (Shift-F7/F8)
KEYFN9 EQU $00 ;F9 [N/A]
KEYFNA EQU $00 ;F10 [N/A]
KEYFNB EQU $00 ;F11 [N/A]
KEYFNC EQU $00 ;F12 [N/A]
KEYHLP EQU $84 ;Help [N/A]
KEYHOM EQU $13 ;Home (CLR/HOME)
KEYINS EQU $94 ;Insert (Shift-INS/DEL)
KEYLFT EQU $9D ;Cursor Left
KEYLNF EQU $00 ;Line Feed [N/A]
KEYRGT EQU $1D ;Cursor Right
KEYRTN EQU $0D ;Return
KEYRTS EQU $8D ;Shift-Return
KEYRUN EQU $00 ;Run (Shift-RUN/STOP)
KEYRVF EQU $92 ;Reverse Off
KEYRVS EQU $12 ;Reverse On
KEYSPS EQU $A0 ;Shifted Space
KEYTAB EQU $09 ;Tab
KEYTAS EQU $00 ;Shift-Tab [N/A]
KEYUP EQU $91 ;Cursor Up

37
include/c64/keydef.h02 Normal file
View File

@ -0,0 +1,37 @@
/* PETSCII Key Code Definitions *
* for Commodore 64 Computer */
#define KEYBCK $00 //Backspace
#define KEYBRK $03 //Break (RUN/STOP)
#define KEYCLR $93 //Clear (Shift-CLR/HOME)
#define KEYCPY $00 //Copy [N/A]
#define KEYDEL $14 //Delete
#define KEYDN $11 //Cursor Down
#define KEYESC $00 //Escape [N/A]
#define KEYFN1 $85 //Function Key 1 (F1/F2)
#define KEYFN2 $89 //Function Key 2 (Shift-F1/F2)
#define KEYFN3 $86 //Function Key 3 (F3/F4)
#define KEYFN4 $8A //Function Key 4 (Shift-F3/F4)
#define KEYFN5 $87 //Function Key 5 (F5/F6)
#define KEYFN6 $8B //Function Key 6 (Shift-F5/F6)
#define KEYFN7 $88 //Function Key 7 (F7/F8)
#define KEYFN8 $8C //Function Key 8 (Shift-F7/F8) [HELP on C16]
#define KEYFN9 $00 //Function Key 9 [N/A]
#define KEYFNA $00 //Function Key 10 [N/A]
#define KEYFNB $00 //Function Key 11 [N/A]
#define KEYFNC $00 //Function Key 12 [N/A]
#define KEYHLP $84 //Help [N/A]
#define KEYHOM $13 //Home (CLR/HOME)
#define KEYINS $94 //Insert (Shift-INS/DEL)
#define KEYLFT $9D //Cursor Left
#define KEYLNF $00 //Line Feed (N/A)
#define KEYRGT $1D //Cursor Right
#define KEYRTN $0D //Return
#define KEYRTS $8D //Shift-Return
#define KEYRUN $00 //Run (Shift-RUN/STOP)
#define KEYRVF $92 //Reverse Off
#define KEYRVS $12 //Reverse On
#define KEYSPS $A0 //Shifted Space
#define KEYTAB $09 //Tab
#define KEYTAS $00 //Shift-Tab [N/A]
#define KEYUP $91 //Cursor Up

View File

@ -1,5 +1,20 @@
;Screen Control Assembly Lanuage Routines for VIC-20
SUBROUTINE _SCREEN
SMTEXT EQU $00 ;Default Text Screen
SMWIDE EQU $FF ;Wide Text Screen (Undefined)
;Set Screen Mode
SETSCR: CMP SMTEXT ;If Default Text Screen
BEQ GETSCR ;Return Return 0
LDA #$FF ;Else Return ERROR
RTS
;Else Return 0
;Get Screen Mode
GETSCR: LDA #0 ;Return 0 (Default Text Mode)
RTS
;Clear the Screen
CLRSCR EQU $E544 ;Aliased to CLSR Routine

View File

@ -2,6 +2,10 @@
* Screen Control Functions and Constants for VIC-20 *
*****************************************************/
/* Screen Modes for getscr() and setscr() */
#define SMTEXT $00 //System Default Text Mode
#define SMWIDE $FF //Wide Screen Text Mode (Unsupported)
/* Clear the Screen */
void clrscn();
@ -18,7 +22,17 @@ char getpos();
* height in rows */
char getsiz();
/* Get Screen Mode *
* Returns: char mode - Current Screen Mode */
char getscr();
/* Move Cursor to Specified Position *
* Args: column - screen column (0 = left) *
* row - screen line (0 = top) */
void setpos();
/* Set Screen Mode *
* Args: char mode - screen mode *
* 0 = default text mode *
* Returns: $FF if Mode Invalid */
char setscr();

37
include/cbm/keydef.a02 Normal file
View File

@ -0,0 +1,37 @@
;PETSCII Key Code Definitions
;Common to All PET/CBM Computers
KEYBCK EQU $00 ;Backspace [N/A]
KEYBRK EQU $03 ;Break (RUN/STOP)
KEYCLR EQU $93 ;Clear (Shift-CLR/HOME)
KEYCPY EQU $00 ;Copy [N/A]
KEYDEL EQU $14 ;Delete
KEYDN EQU $11 ;Cursor Down
KEYESC EQU $00 ;Escape [C128/C65]
KEYFN1 EQU $85 ;F1 [VIC20/C64/C16/C128/C65]
KEYFN2 EQU $89 ;F2 [VIC20/C64/C16/C128/C65]
KEYFN3 EQU $86 ;F3 [VIC20/C64/C16/C128/C65]
KEYFN4 EQU $8A ;F4 [VIC20/C64/C16/C128/C65]
KEYFN5 EQU $87 ;F5 [VIC20/C64/C16/C128/C65]
KEYFN6 EQU $8B ;F6 [VIC20/C64/C16/C128/C65]
KEYFN7 EQU $88 ;F7 [VIC20/C64/C16/C128/C65]
KEYFN8 EQU $8C ;F8 [VIC20/C64/C128/C65] [HELP on C16]
KEYFN9 EQU $00 ;F9 [C65]
KEYFNA EQU $00 ;F10 [C65]
KEYFNB EQU $00 ;F11 [C65]
KEYFNC EQU $00 ;F12 [C65]
KEYHLP EQU $84 ;Help [C128/xC65]
KEYHOM EQU $13 ;Home (CLR/HOME)
KEYINS EQU $94 ;Insert (Shift-INS/DEL)
KEYLFT EQU $9D ;Cursor Left
KEYLNF EQU $00 ;Line Feed [C128]
KEYRGT EQU $1D ;Cursor Right
KEYRTN EQU $0D ;Return
KEYRTS EQU $8D ;Shift-Return
KEYRUN EQU $00 ;Run (Shift-RUN/STOP)
KEYRVF EQU $92 ;Reverse Off
KEYRVS EQU $12 ;Reverse On
KEYSPS EQU $A0 ;Shifted Space
KEYTAB EQU $09 ;Tab
KEYTAS EQU $00 ;Shift-Tab [C128/C65]
KEYUP EQU $91 ;Cursor Up

37
include/cbm/keydef.h02 Normal file
View File

@ -0,0 +1,37 @@
/* PETSCII Key Code Definitions *
* Common to All PET/CBM Computers */
#define KEYBCK $00 //Backspace
#define KEYBRK $03 //Break (RUN/STOP)
#define KEYCLR $93 //Clear (Shift-CLR/HOME)
#define KEYCPY $00 //Copy
#define KEYDEL $20 //Delete
#define KEYDN $11 //Cursor Down
#define KEYESC $00 //Escape (N/A)
#define KEYFN1 $00 //F1 (N/A)
#define KEYFN2 $00 //F2 (N/A)
#define KEYFN3 $00 //F3 (N/A)
#define KEYFN4 $00 //F4 (N/A)
#define KEYFN5 $00 //F5 (N/A)
#define KEYFN6 $00 //F6 (N/A)
#define KEYFN7 $00 //F7 (N/A)
#define KEYFN8 $00 //F8 (N/A)
#define KEYFN9 $00 //F9 (N/A)
#define KEYFNA $00 //F10 (N/A)
#define KEYFNB $00 //F11 (N/A)
#define KEYFNC $00 //F12 (N/A)
#define KEYHLP $00 //Help (N/A)
#define KEYHOM $13 //Home (CLR/HOME)
#define KEYINS $94 //Insert (Shift-INS/DEL)
#define KEYLFT $9C //Cursor Left
#define KEYLNF $00 //Line Feed (N/A)
#define KEYRGT $1D //Cursor Right
#define KEYRTN $0D //Return
#define KEYRTS $8D //Shift-Return
#define KEYRUN $83 //Run (Shift-RUN/STOP)
#define KEYRVF $92 //Reverse Off
#define KEYRVS $12 //Reverse On
#define KEYSPS $A0 //Shifted Space
#define KEYTAB $09 //Tab
#define KEYTAS $00 //Shift-Tab (N/A)
#define KEYUP $91 //Cursor Up

View File

@ -37,6 +37,10 @@ STKEHI EQU $2B
STKLO EQU $2C ;Stack Pointer
STKHI EQU $2D
;Placeholders Labels for the Example Code Below
POLKEY EQU $FFFE ;ROM Read Key Routine
WSTART EQU $FFFF ;BASIC Warm Start Routine
ORG $0200 ;Program Start Address
START: NOP ;System specific initialization code
@ -77,45 +81,5 @@ NEWLIN: RTS ;Code to move Cursor to beginning of next line
;Print Character to Screen
PUTCHR RTS ;Code to write ASCII character to Screen
;Clear the Screen
CLRSCR: RTS ;Code to Clear Screen
;Move Cursor to Specified Coordinates
SETPOS: RTS ;Move Cursor to Column A, Row Y
;Get Cursor Position
GETPOS: RTS ;Return Cursor Column in A, Row in Y
;Get Screen Size
GETSIZ: RTS ;Return Screen Width in A, Height in Y
;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 Nybb
SED ;Set Decimal Flag for
CLC ; Addition Wizardry
ADC #$90 ;Convert to $90-$99,$00-$05
ADC #$40 ;Convert to $30-$39,$41-$46
CLD ;Clear Decimal Flag
JMP PUTCHR ;Print Hex Digit and Return
;Alternate Code for Systems with Interrupts that don't CLD
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 PUTCHR ;Print Hex Digit and Return
INCLUDE "../include/prbyte.a02" ;PRBYTE and PRHEX routines

View File

@ -36,15 +36,12 @@ char rdseed; //System Seed for Pseudo-Random Number Generator
//System Subroutines
void delchr(); //Delete previous character
char getkey(); //Read ASCII character from Console
char getpos(); //Get Cursor Position
char getsiz(); //Get Screen Size
void newlin(); //Advance cursor to beginning of next line
char polkey(); //Poll Console for character
char putchr(); //Print ASCII character to Console
void prbyte(); //Print Accumulator as Hexadadecimal number
void prhex(); //Print Low Nybble of Accumulator as Hex Digit
char getchr(); //Wait for character from Console
void setpos(); //Set Cursor Position
//System Labels
start: //Start of Code

37
include/keydef.a02 Normal file
View File

@ -0,0 +1,37 @@
;Standard ASCII Key Code Definitions
;Undefined Keys hae value $00
KEYBCK EQU $08 ;Backspace
KEYBRK EQU $03 ;Break
KEYCLR EQU $00 ;Clear
KEYCPY EQU $00 ;Copy [Acorn Atom]
KEYDEL EQU $7F ;Delete
KEYDN EQU $00 ;Cursor Down
KEYESC EQU $1B ;Escape
KEYFN1 EQU $00 ;F1
KEYFN2 EQU $00 ;F2
KEYFN3 EQU $00 ;F3
KEYFN4 EQU $00 ;F4
KEYFN5 EQU $00 ;F5
KEYFN6 EQU $00 ;F6
KEYFN7 EQU $00 ;F7
KEYFN8 EQU $00 ;F8
KEYFN9 EQU $00 ;F9
KEYFNA EQU $00 ;F10
KEYFNB EQU $00 ;F11
KEYFNC EQU $00 ;F12
KEYHLP EQU $00 ;Help [C128/C65]
KEYHOM EQU $00 ;Home
KEYINS EQU $00 ;Insert
KEYLFT EQU $00 ;Cursor Left
KEYLNF EQU $0A ;;Line Feed [C128]
KEYRGT EQU $00 ;Cursor Right
KEYRTN EQU $0D ;Return
KEYRTS EQU $80 ;Shift-Return
KEYRUN EQU $00 ;Run [PET/CBM]
KEYRVF EQU $92 ;Reverse OffCtrl-0
KEYRVS EQU $12 ;Reverse On Ctrl-9
KEYSPS EQU $00 ;Shifted Space
KEYTAB EQU $09 ;Tab
KEYTAS EQU $00 ;Shift-Tab
KEYUP EQU $00 ;Cursor Up

37
include/keydef.h02 Normal file
View File

@ -0,0 +1,37 @@
/* Standard ASCII Key Code Definitions *
* Undefined Keys hae value $00 *
#define KEYBCK $08 //Backspace
#define KEYBRK $03 //Break
#define KEYCLR $00 //Clear
#define KEYCPY $00 //Copy
#define KEYDEL $7F //Delete
#define KEYDN $00 //Cursor Down
#define KEYESC $1B //Escape
#define KEYFN1 $00 //1
#define KEYFN2 $00 //2
#define KEYFN3 $00 //3
#define KEYFN4 $00 //4
#define KEYFN5 $00 //5
#define KEYFN6 $00 //6
#define KEYFN7 $00 //7
#define KEYFN8 $00 //8
#define KEYFN9 $00 //9
#define KEYFNA $00 //10
#define KEYFNB $00 //11
#define KEYFNC $00 //12
#define KEYHLP $00 //Help
#define KEYHOM $00 //Home
#define KEYINS $00 //Insert
#define KEYLFT $00 //Cursor Left
#define KEYLNF $0A //Line Feed
#define KEYRGT $00 //Cursor Right
#define KEYRTN $0D //Return
#define KEYRTS $80 //Shift-Return
#define KEYRUN $00 //Run
#define KEYRVF $92 //Reverse Off
#define KEYRVS $12 //Reverse On
#define KEYSPS $00 //Shifted Space
#define KEYTAB $09 //Tab
#define KEYTAS $00 //Shift-Tab
#define KEYUP $00 //Cursor Up

39
include/orao/screen.a02 Normal file
View File

@ -0,0 +1,39 @@
;Screen Control Assembly Lanuage Routines for C02
;Skeleton Code for Systems with no Screen Control
SUBROUTINE _SCREEN
SMTEXT EQU $00 ;Default Text Screen
SMWIDE EQU $FF ;Wide Text Screen (Undefined)
;Set Screen Mode
SETSCR: CMP SMTEXT ;If Default Text Screen
BEQ GETSCR ;Return Return 0
LDA #$FF ;Else Return ERROR
RTS
;Else Return 0
;Get Screen Mode
GETSCR: LDA #0 ;Return 0 (Default Text Mode)
RTS
;Clear the Screen
CLRSCR: LDA #$0C ;Print Form Feed
JMP PUTCHR ;and Return
;Move Cursor Home
CRSRHM EQU $E395 ;Aliad to HOME Routine
;Move Cursor to Specified Coordinates
SETPOS: STA $E9 ;Set CURCOL
STY $E8 ;Set CURROW
JMP $E39D ;Set Pointers and Return
;Get Cursor Position
GETPOS: LDA $E9 ;Load Column Position
LDY $E8 ;Load Row Position
RTS ;Return Cursor Column in A, Row in Y
;Get Screen Size
GETSIZ: LDA #32 ;Return 32 Columns
TAY ;and 32 Rows
RTS

38
include/orao/screen.h02 Normal file
View File

@ -0,0 +1,38 @@
/*********************************************
* Screen Control Routines for Orao Computer *
*********************************************/
/* Screen Modes for getscr() and setscr() */
#define SMTEXT $00 //System Default Text Mode
#define SMWIDE $FF //Wide Screen Text Mode (Unsupported)
/* Clear the Screen */
void clrscn();
/* Move Cursor to Top Left of Screen */
void crsrhm();
/* Get Current Cursor Position *
* Returns: cursor column *
* cursor row */
char getpos();
/* Get Screen Mode *
* Returns: char mode - Current Screen Mode */
char getscr();
/* Get Screen Size *
* Returns: width in columns *
* height in rows */
char getsiz();
/* Move Cursor to Specified Position *
* Args: column - screen column (0 = left) *
* row - screen line (0 = top) */
void setpos();
/* Set Screen Mode *
* Args: char mode - screen mode *
* 0 = default text mode *
* Returns: $FF if Mode Invalid */
char setscr();

View File

@ -1,5 +1,20 @@
;Screen Control Assembly Lanuage Routines for Oric-1
SUBROUTINE _SCREEN
SMTEXT EQU $00 ;Default Text Screen
SMWIDE EQU $FF ;Wide Text Screen (Undefined)
;Set Screen Mode
SETSCR: CMP SMTEXT ;If Default Text Screen
BEQ GETSCR ;Return Return 0
LDA #$FF ;Else Return ERROR
RTS
;Else Return 0
;Get Screen Mode
GETSCR: LDA #0 ;Return 0 (Default Text Mode)
RTS
;Clear the Screen
CLRSCR EQU $CC0A ;Basic CLS Routine (Atmos = $CCCE)

View File

@ -2,6 +2,10 @@
* Screen Control Functions for Oric-1 *
***************************************/
/* Screen Modes for getscr() and setscr() */
#define SMTEXT $00 //System Default Text Mode
#define SMWIDE $FF //Wide Screen Text Mode (Unsupported)
/* Clear the Screen */
void clrscn();
@ -13,6 +17,10 @@ void crsrhm();
( cursor row */
char getpos();
/* Get Screen Mode *
* Returns: char mode - Current Screen Mode */
char getscr();
/* Get Screen Size *
* Returns: width in columns *
* height in rows */
@ -22,3 +30,9 @@ char getsiz();
* Args: column - screen column (0 = left) *
* row - screen line (0 = top) */
void setpos();
/* Set Screen Mode *
* Args: char mode - screen mode *
* 0 = default text mode *
* Returns: $FF if Mode Invalid */
char setscr();

View File

@ -23,7 +23,7 @@ char temp0, temp1, temp2, temp3; //Temporary Storage
//Memory Mapped I/O
char putcon; //Write Character to Console
char getcomn; //Read Character from Console
char getcon; //Read Character from Console
//System Subroutines
char polkey(); //Poll Console for character

View File

@ -1,6 +1,19 @@
;Screen Control Assembly Lanuage Routines for C02
;Skeleton Code for Systems with no Screen Control
SUBROUTINE _SCREEN
SMTEXT EQU $00 ;Default Text Screen
SMWIDE EQU $FF ;Wide Text Screen (Undefined)
;Set Screen Mode
SETSCR: CMP SMTEXT ;If Not Default Text
BEQ GETPOS ;Return Error
;Else Return 0
;Get Screen Mode
GETSCR: LDA #0 ;Return 0 (Default Text Mode)
RTS
;Clear the Screen
CLRSCR: RTS ;No Action
@ -17,3 +30,4 @@ GETPOS: LDA #$FF ;Return Error
;Get Screen Size
GETSIZ EQU GETPOS ;Return Error

View File

@ -1,6 +1,11 @@
/********************************************
* screen - Screen Control Routines for C02 *
********************************************/
/***********************************
* Screen Control Routines for C02 *
***********************************/
/* Screen Modes for getscr() and setscr() *
* Invalid Modes have value $FF */
#define SMTEXT $00 //System Default Text Mode
#define SMWIDE $FF //Wide Screen Text Mode (Usuallu 80 Columns)
/* Clear the Screen */
void clrscn();
@ -18,7 +23,17 @@ char getpos();
* height in rows */
char getsiz();
/* Move Cursor to Specified Position *
* Args: column - screen column (0 = left) *
* row - screen line (0 = top) */
/* Get Screen Mode *
* Returns: char mode - Current Screen Mode */
char getscr();
/* Move Cursor to Specified Position *
* Args: char col - screen column (0 = left) *
* char row - screen line (0 = top) */
void setpos();
/* Set Screen Mode *
* Args: char mode - screen mode *
* 0 = default text mode *
* Returns: $FF if Mode Invalid */
char setscr();

View File

@ -3,15 +3,17 @@
; external zero page locations SRCLO and SRCHI
; and external locations RANDOM, RDSEED, TEMP0, TEMP1, and TEMP2.
SUBROUTINE STDLIB
;abs(n) - Get ABSolute Value
;Args: A = Number to get Absolute Value Of
;Affects: C, N, Z
;Returns: A = Absolute Value of Argument
ABS: CMP #$80 ;If Negative (High Bit Set)
BCC ABSX ; Carry will Already be Set
BCC .ABSX ; Carry will Already be Set
EOR #$FF ; One's Complement
ADC #$00 ; and Increment (Carry set by CMP)
ABSX: RTS
.ABSX RTS
;max(m,n) - Get MAXimum of Two Numbers
;Args: A,Y = Numbers to Compare
@ -20,9 +22,9 @@ ABSX: RTS
;Returns: A = Larger of the Two Arguments
MAX: STY TEMP0 ;Save Second Parameter
CMP TEMP0 ;If First Parameter
BCC MAXX ; Greater than Second Parameter
BCC .MAXX ; Greater than Second Parameter
TYA ;Copy Second Parameter into Accumulator
MAXX: RTS
.MAXX RTS
;min(m,n) - Get MINimum Get MAXimum of Two Numbers
;Args: A,Y = Numbers to Compare
@ -31,9 +33,9 @@ MAXX: RTS
;Returns: A = Smaller of the Two Arguments
MIN: STY TEMP0 ;Save Second Parameter
CMP TEMP0 ;If First Parameter
BCS MINX ; Less than Second Parameter
BCS .MINX ; Less than Second Parameter
TYA ;Copy Second Parameter into Accumulator
MINX: RTS
.MINX RTS
;mult(m,n) - MULTiply Two Numbers
;Args: A = Multiplicand
@ -48,13 +50,13 @@ MULT: STA TEMP0 ;Store Multiplicand
STY TEMP1 ;Store Multiplier
;Multiply TEMP0 times TEMP1
MULTT: LDA #$00 ;Initialize Accumulator
BEQ MULTE ;Enter Loop
MULTA: CLC
BEQ .MULTE ;Enter Loop
.MULTA CLC
ADC TEMP0 ;Add Multiplicand
MULTL: ASL TEMP0 ;Shift Multiplicand Left
MULTE: LSR TEMP1 ;Shift Multiplier Right
BCS MULTA ;If Bit Shifted Out, Add Multiplicand
BNE MULTL ;Loop if Any 1 Bits Left
.MULTL ASL TEMP0 ;Shift Multiplicand Left
.MULTE LSR TEMP1 ;Shift Multiplier Right
BCS .MULTA ;If Bit Shifted Out, Add Multiplicand
BNE .MULTL ;Loop if Any 1 Bits Left
LDY TEMP2 ;Load Y with MSB
TAX ;and Copy LSB to X
RTS
@ -73,13 +75,13 @@ DIV: STA TEMP0 ;Store Dividend
DIVT: LDA #$00 ;Clear Accumulator
LDX #$07 ;Load Loop Counter
CLC
DIVL: ROL TEMP0 ;Shift Bit Out of Dividend
.DIVL ROL TEMP0 ;Shift Bit Out of Dividend
ROL ; into Accumulator
CMP TEMP1 ;If Accumulator
BCC DIVS ; >= Divisor
BCC .DIVS ; >= Divisor
SBC TEMP1 ;Subtract Divisor
DIVS: DEX ;Decrement Counter
BPL DIVL ; and Loop
.DIVS DEX ;Decrement Counter
BPL .DIVL ; and Loop
ROL TEMP0 ;Shift Result into Dividend
TAY ;Copy Remainder to Y Register
LDA TEMP0 ;Load Result into Accumulator
@ -90,9 +92,9 @@ DIVS: DEX ;Decrement Counter
;Affects A,N,Z,C
RAND: LDA RANDOM ;Load Last Result
ASL ;Shift the Seed
BCC RANDX ;If a one was shifted out
BCC .RANDX ;If a one was shifted out
EOR #$1D ; Twiddle the bite
RANDX: STA RANDOM ;Save the Seed
.RANDX STA RANDOM ;Save the Seed
RTS
;Seed Pseudo-Random Number Generator
@ -100,25 +102,71 @@ RANDX: STA RANDOM ;Save the Seed
;Affects A,N,Z,C
;Sets RANDOM
RANDS: ORA #$00 ;If Passed Value not 0
BNE RANDX ; Store in Seed and Return
BNE .RANDX ; Store in Seed and Return
LDA RDSEED ;Load System Generated Seed
BNE RANDX ;If Not 0, Store and Return
BNE .RANDX ;If Not 0, Store and Return
ADC #$01 ;Else Add 1 or 2
BNE RANDX ; then Store and Return
BNE .RANDX ; then Store and Return
;Return A Shifted Y Bytes to the Left
;Affects A,Y,N,Z,C
;Affects A,Y,N,Z,C
SHIFTL: ASL ;Shift Byte to Left
DEY ;Decrement Counter
BNE SHIFTL ; and Loop if Not 0
;swap(byte) - Swap Low and High Nybbles in Byte
;Args: A = Byte to Swap
;Affects Y,N,Z,C
;Returns: A = Swapped Byte
SWAP: LDY #4 ;Set Count to 4 and Rotate Left
;rotatl(byte,count) - Rotate byte by count Bits to the Left
;Args = Byte to Rotate
;Y = Number of Bits to Rotate
;Affects X,Y,N,Z,C
;Returns: A = Rotated Byte
ROTATL: INY ;Pre-Increment Counter
.ROTALL DEY ;Decrement Counter
BEQ .ROTATX ;If Not Zero
ASL ; Shift Left One Bit
ADC #0 ; Copy Carry into Bit 0
BNE .ROTALL ; If Not Zero, Loop
.ROTATX RTS
;rotatr(byte,count) - Shift byte by count Bits to the Right
;Args = Byte to Rotate
;Y = Number of Bits to Rotate
;Affects Y,N,Z,C
;Returns: A = Rotated Byte
ROTATR: INY ;Pre-Increment Counter
.ROTALR DEY ;Decrement Counter
BEQ .ROTATX ;If Not Zero
LSR ; Shift Right One Bit
BCC .ROTATS ; If Carry Set
ORA #$80 ; Copy Carry into Bit 7
.ROTATS BNE .ROTALR ; If Not Zero, Loop
RTS
;Return A Shifted Y Bytes to the Right
;Affects A,Y,N,Z,C
SHIFTR: LSR ;Shift Byte to Right
DEY ;Decrement Counter
BNE SHIFTR ; and Loop if Not 0
SHFTL4: LDY #4; ;Set Count to 4 and Shift Left
;shiftl(byte,count) - Shift byte by Count bits to the Left
;Args = Byte to Shift
;Y = Number of Bits to Rotate
;Affects Y,N,Z,C
;Returns: A = Shifted Byte
SHIFTL: INY ;Pre-Increment Counter
.SHIFLL DEY ;Decrement Counter
BEQ .SHIFTX ;If Not Zero
ASL ; Shift Byte to Left
BNE .SHIFLL ; and Loop if Not 0
.SHIFTX RTS
SHFTR4: LDY #4; ;Set Count to 4 and Shift Right
;shiftr(byte,count) - Shift byte by Count bits to the Right
;Args = Byte to Shift
;Y = Number of Bits to Rotate
;Affects Y,N,Z,C
;Returns: A = Shifted Byte
SHIFTR: INY ;Pre-Increment Counter
.SHIFLR DEY ;Decrement Counter
BEQ .SHIFTX ;If Not Zero
LSR ; Shift Byte to Right
BNE .SHIFLR ; and Loop if Not 0
RTS
;atoc(&s) - ASCII string TO Character
@ -130,11 +178,11 @@ SHIFTR: LSR ;Shift Byte to Right
; Y = Number of Digits
ATOC: JSR SETSRC ;Initialize Source String
STY TEMP0 ;Initialize Result
ATOCL: LDA (SRCLO),Y ;Get Next Character
.ATOCL LDA (SRCLO),Y ;Get Next Character
CMP #$30 ;If Less Than '0'
BCC ATOCX ; Exit
BCC .ATOCX ; Exit
CMP #$3A ;If Greater Than '9'
BCS ATOCX ; Exit
BCS .ATOCX ; Exit
AND #$0F ;Convert to Binary Nybble
STA TEMP1 ; and Save It
LDA TEMP0 ;Load Result
@ -145,8 +193,8 @@ ATOCL: LDA (SRCLO),Y ;Get Next Character
ADC TEMP1 ;Add Saved Nybble
STA TEMP0 ; and Store Result
INY ;Increment Index
BPL ATOCL ; and Loop
ATOCX: LDA TEMP0 ;Load Result
BPL .ATOCL ; and Loop
.ATOCX LDA TEMP0 ;Load Result
RTS ;And Return
;ctoa(n) - Character TO ASCII string
@ -161,19 +209,19 @@ CTOA: JSR SETDST ;Initialize Source String
LDY #0 ;Initialize Index into String
JSR CUBCD ;Convert Accumulator to Unpacked BCD
LDA TEMP2 ;Get MSB
BEQ CTOA1 ;If Not Zero
JSR CTOAN ; Convert Low Nybble
CTOA1: LDA TEMP1 ;Get Low Byte
BNE CTOA2 ;If Not Zero
BEQ .CTOA1 ;If Not Zero
JSR .CTOAN ; Convert Low Nybble
.CTOA1 LDA TEMP1 ;Get Low Byte
BNE .CTOA2 ;If Not Zero
CMP TEMP2 ; and Hundreds
BEQ CTOA3 ; not Zero
CTOA2: JSR CTOAN ; Convert It
CTOA3: LDA TEMP0 ;Get Low Byte
JSR CTOAN ;and Convert Low Nybble
BEQ .CTOA3 ; not Zero
.CTOA2 JSR .CTOAN ; Convert It
.CTOA3 LDA TEMP0 ;Get Low Byte
JSR .CTOAN ;and Convert Low Nybble
LDA #$00
BEQ CTOAX ;Terminate String
CTOAN: ORA #$30 ;Convert to ASCII digit
CTOAX: STA (DSTLO),Y ;Store in String
BEQ .CTOAX ;Terminate String
.CTOAN ORA #$30 ;Convert to ASCII digit
.CTOAX STA (DSTLO),Y ;Store in String
INY ;and Increment Offset
TYA ;Copy String Length to Accumulator
RTS
@ -207,23 +255,22 @@ UPBCD: LDA TEMP1 ;Get Low Byte
; TEMP2 = Hundreds Digit
;Returns: A = Hundreds Digit
; X = 0
CVBCD: STA TEMP0 ;Save Binary Value
CVBCDT: LDA #0 ;Clear BCD Bytes
STA TEMP1
STA TEMP2
LDX #8 ;Process 8 bits of Binary
PHP ;Save Status Register
SEI ;Disable Interupts
SED ;Set Decimal Mode
CVBCDL: ASL TEMP0 ;Shift High Bit into Carry
LDA TEMP1 ;Add BCD Low Byte to Itself
ADC TEMP1 ; Plus Bit Shifted out of Binary
STA TEMP1 ; Effectively Multiplying It by 2
LDA TEMP2 ;Add BCD MSB to Itself
ADC TEMP2 ; Plus Bit Shifted out of Low Byte
STA TEMP2 ; Effectively Multiplying It by 2
DEX ;Decrement Counter and
BNE CVBCDL ; Process Next Bit
PLP ;Restore Status Register
CVBCD: STA TEMP0 ;Save Binary Value
CVBCDT: LDA #0 ;Clear BCD Bytes
STA TEMP1
STA TEMP2
LDX #8 ;Process 8 bits of Binary
PHP ;Save Status Register
SEI ;Disable Interupts
SED ;Set Decimal Mode
.CVBCDL ASL TEMP0 ;Shift High Bit into Carry
LDA TEMP1 ;Add BCD Low Byte to Itself
ADC TEMP1 ; Plus Bit Shifted out of Binary
STA TEMP1 ; Effectively Multiplying It by 2
LDA TEMP2 ;Add BCD MSB to Itself
ADC TEMP2 ; Plus Bit Shifted out of Low Byte
STA TEMP2 ; Effectively Multiplying It by 2
DEX ;Decrement Counter and
BNE .CVBCDL ; Process Next Bit
PLP ;Restore Status Register
RTS

View File

@ -1,6 +1,6 @@
/************************************************
* template - Template Library Routines for C02 *
************************************************/
/***************************************************
* template.a02 - Template Module Routines for C02 *
***************************************************/
/* Function Description *
* Args: a - First Argument *

20
include/via.h02 Normal file
View File

@ -0,0 +1,20 @@
/* MOS 6522 VIA Registers */
struct via {
char iorb; //Input/Output Register B
char iora; //Input/Output Register A
char ddrb; //Data Direction Register B
char ddra; // Data Direction Register A
char t1cl; //T1 Low-Order Counter
char t1ch; //T1 High-Order Counter
char t1ll; //T1L-L | T1 Low-Order Latches
char t1lh; //T1 High-Order Latches
char t2cl; //T2 Low-Order Latches
char t2ch; //T2 High-Order Counter
char sr; //Shift Register
char acr; //Auxiliary Control Register
char pcr; //Peripheral Control Register
char ifr; //Interrupt Flag Register
char ier; //Interrupt Enable Register
char nhra; //Input/Output Register A (No Handshake)
}

View File

@ -100,4 +100,6 @@ NEWLIN: LDX #0 ;Store 0
STX $D3 ;in Cursor Column and
JMP $E8C3 ;Execute NXTLINE Routine
INCLUDE "../include/prbyte.a02" ;PRBYTE and PRHEX routines
;Print Zero-Terminated String
PUTSTR: TXA ;Copy LSB to Accumulator
JMP $CB1E ;Execute STROUT Routine

37
include/vic/keydef.a02 Normal file
View File

@ -0,0 +1,37 @@
;PETSCII Key Code Definitions
;for Commmodore 64 Computer
KEYBCK EQU $00 ;Backspace [N/A]
KEYBRK EQU $03 ;Break (RUN/STOP)
KEYCLR EQU $93 ;Clear (Shift-CLR/HOME)
KEYCPY EQU $00 ;Copy [N/A]
KEYDEL EQU $14 ;Delete
KEYDN EQU $11 ;Cursor Down
KEYESC EQU $00 ;Escape [N/A]
KEYFN1 EQU $85 ;F1 (F1/F2)
KEYFN2 EQU $89 ;F2 (Shift-F1/F2)
KEYFN3 EQU $86 ;F3 (F3/F4)
KEYFN4 EQU $8A ;F4 (Shift-F3/F4)
KEYFN5 EQU $87 ;F5 (F5/F6)
KEYFN6 EQU $8B ;F6 (Shift-F5/F6)
KEYFN7 EQU $88 ;F7 (F7/F8)
KEYFN8 EQU $8C ;F8 (Shift-F7/F8)
KEYFN9 EQU $00 ;F9 [N/A]
KEYFNA EQU $00 ;F10 [N/A]
KEYFNB EQU $00 ;F11 [N/A]
KEYFNC EQU $00 ;F12 [N/A]
KEYHLP EQU $84 ;Help [N/A]
KEYHOM EQU $13 ;Home (CLR/HOME)
KEYINS EQU $94 ;Insert (Shift-INS/DEL)
KEYLFT EQU $9D ;Cursor Left
KEYLNF EQU $00 ;Line Feed [N/A]
KEYRGT EQU $1D ;Cursor Right
KEYRTN EQU $0D ;Return
KEYRTS EQU $8D ;Shift-Return
KEYRUN EQU $00 ;Run (Shift-RUN/STOP)
KEYRVF EQU $92 ;Reverse Off
KEYRVS EQU $12 ;Reverse On
KEYSPS EQU $A0 ;Shifted Space
KEYTAB EQU $09 ;Tab
KEYTAS EQU $00 ;Shift-Tab [N/A]
KEYUP EQU $91 ;Cursor Up

37
include/vic/keydef.h02 Normal file
View File

@ -0,0 +1,37 @@
/* PETSCII Key Code Definitions *
* for Commodore 64 Computer */
#define KEYBCK $00 //Backspace
#define KEYBRK $03 //Break (RUN/STOP)
#define KEYCLR $93 //Clear (Shift-CLR/HOME)
#define KEYCPY $00 //Copy [N/A]
#define KEYDEL $14 //Delete
#define KEYDN $11 //Cursor Down
#define KEYESC $00 //Escape [N/A]
#define KEYFN1 $85 //Function Key 1 (F1/F2)
#define KEYFN2 $89 //Function Key 2 (Shift-F1/F2)
#define KEYFN3 $86 //Function Key 3 (F3/F4)
#define KEYFN4 $8A //Function Key 4 (Shift-F3/F4)
#define KEYFN5 $87 //Function Key 5 (F5/F6)
#define KEYFN6 $8B //Function Key 6 (Shift-F5/F6)
#define KEYFN7 $88 //Function Key 7 (F7/F8)
#define KEYFN8 $8C //Function Key 8 (Shift-F7/F8) [HELP on C16]
#define KEYFN9 $00 //Function Key 9 [N/A]
#define KEYFNA $00 //Function Key 10 [N/A]
#define KEYFNB $00 //Function Key 11 [N/A]
#define KEYFNC $00 //Function Key 12 [N/A]
#define KEYHLP $84 //Help [N/A]
#define KEYHOM $13 //Home (CLR/HOME)
#define KEYINS $94 //Insert (Shift-INS/DEL)
#define KEYLFT $9D //Cursor Left
#define KEYLNF $00 //Line Feed (N/A)
#define KEYRGT $1D //Cursor Right
#define KEYRTN $0D //Return
#define KEYRTS $8D //Shift-Return
#define KEYRUN $00 //Run (Shift-RUN/STOP)
#define KEYRVF $92 //Reverse Off
#define KEYRVS $12 //Reverse On
#define KEYSPS $A0 //Shifted Space
#define KEYTAB $09 //Tab
#define KEYTAS $00 //Shift-Tab [N/A]
#define KEYUP $91 //Cursor Up

View File

@ -1,5 +1,20 @@
;Screen Control Assembly Lanuage Routines for VIC-20
SUBROUTINE _SCREEN
SMTEXT EQU $00 ;Default Text Screen
SMWIDE EQU $FF ;Wide Text Screen (Undefined)
;Set Screen Mode
SETSCR: CMP SMTEXT ;If Default Text Screen
BEQ GETSCR ;Return Return 0
LDA #$FF ;Else Return ERROR
RTS
;Else Return 0
;Get Screen Mode
GETSCR: LDA #0 ;Return 0 (Default Text Mode)
RTS
;Clear the Screen
CLRSCR EQU $E55F ;Aliased to CLSR Routine

View File

@ -2,6 +2,10 @@
* Screen Control Functions for VIC-20 *
***************************************/
/* Screen Modes for getscr() and setscr() */
#define SMTEXT $00 //System Default Text Mode
#define SMWIDE $FF //Wide Screen Text Mode (Unsupported)
/* Clear the Screen */
void clrscn();
@ -13,6 +17,10 @@ void crsrhm();
( cursor row */
char getpos();
/* Get Screen Mode *
* Returns: char mode - Current Screen Mode */
char getscr();
/* Get Screen Size *
* Returns: width in columns *
* height in rows */
@ -22,3 +30,9 @@ char getsiz();
* Args: column - screen column (0 = left) *
* row - screen line (0 = top) */
void setpos();
/* Set Screen Mode *
* Args: char mode - screen mode *
* 0 = default text mode *
* Returns: $FF if Mode Invalid */
char setscr();

View File

@ -16,3 +16,4 @@ BASIC: DC $0C, $10 ;Pointer to Next Line
DC $00, $00 ;End of Basic Program
INCLUDE "../include/vic.a02" ;Include VIC 20 Common Code
INCLUDE "../include/prbyte.a02" ;PRBYTE and PRHEX routines

View File

@ -16,3 +16,4 @@ BASIC: DC $0C, $04 ;Pointer to Next Line
DC $00, $00 ;End of Basic Program
INCLUDE "../include/vic.a02" ;Include VIC 20 Common Code
INCLUDE "../include/prbyte.a02" ;PRBYTE and PRHEX routines

View File

@ -16,3 +16,4 @@ BASIC: DC $0C, $12 ;Pointer to Next Line
DC $00, $00 ;End of Basic Program
INCLUDE "../include/vic.a02" ;Include VIC 20 Common Code
INCLUDE "../include/prbyte.a02" ;PRBYTE and PRHEX routines

455
src/c02.c
View File

@ -1,227 +1,228 @@
/**************************************************************
* C02 Compiler - (C) 2013 Curtis F Kaylor *
* *
* C02 is a simpified C-like language designed for the 6502 *
* *
* This Compiler generates crasm compatible assembly language *
* *
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "common.h" //Common Code used by all Modules
#include "files.h" //Open and Close Files
#include "asm.h" //Write out Assembly Language
#include "parse.h" //General Code Parsing
#include "vars.h" //Variable Parsing, Lookup, and Allocation
#include "expr.h" //Expression Parsing
#include "label.h" //Label Parsing, Generation, and Lookup
#include "cond.h" //Conditional Parsing
#include "stmnt.h" //Statement Compiling Code
#include "dclrtn.h" //Statement Compiling Code
#include "include.h" //Include File Parsing
/* Initilize Compiler Variables */
void init(void) {
initim(); //Initialize Elapsed Time
DEBUG("Initializing Compiler Variables\n",0)
concnt = 0; //Number of Constants Defined
varcnt = 0; //Number of Variables in Table
lblcnt = 0; //Number of Labels in stack
padcnt = 0; //Number of Padding Bytes at End
curcol = 0; //Current Column in Source Code
curlin = 0; //Current Line in Source Code
alcvar = TRUE; //Allocate Variables Flag
inblck = FALSE; //Multiline Block Flag
infunc = FALSE; //Inside Function Definition
xstmnt[0] = 0; //Expected Statement
nxtwrd[0] = 0; //Next Word (from DEFINE lookup)
nxtptr = 0; //Pointer to next character in nxtwrd
vrwrtn = FALSE; //Variables Written Flag
rambas = 0; //RAM Base Address
wrtbas = 0; //Write Base Address
zpaddr = 0; //Current Zero-Page Address
invasc = FALSE; //Invert ASCII Flag
mskasc = FALSE; //Set High Bit Flag
fcase = FALSE; //First Case Statement Flag
wrtofs[0] = 0; //Write Offset
xsnvar[0] = 0; //Assigned X Variable Name
ysnvar[0] = 0; //Assigned Y Variable Name
subcnt = 0; //Include Subdirectories
strcpy(cputyp, CPUARG); //Set CPU Type to Default Value
strcpy(incdir, "../include/");
}
/* Parse Pointer Dereference Assignment */
void ppntr(void) {
lsrtrn = FALSE; //Clear RETURN flag
if (xstmnt[0]) ERROR("Expected '%s' statement\n", xstmnt, EXIT_FAILURE)
prcasp(';');
}
/* Reads and parses the next Word in Source File */
void pword(void) {
lsrtrn = FALSE; //Clear RETURN flag
getwrd();
DEBUG("Parsing Word '%s'\n", word)
if (xstmnt[0]) {
if (wordis(xstmnt)) xstmnt[0] = 0; //Clear xstmnt
else ERROR("Expected '%s' statement\n", xstmnt, EXIT_FAILURE)
}
if (!pmodfr() && !ptype(MTNONE)) pstmnt(); //Parse Statement
}
/* Process a directive */
void pdrctv(void) {
skpchr(); //skip '#'
CCMNT('#');
getwrd(); //read directive into word
DEBUG("Processing directive '%s'\n", word)
if (wordis("DEFINE")) pdefin(); //Parse Define
else if (wordis("INCLUDE")) pincfl(); //Parse Include File
else if (wordis("ERROR")) ERROR("Error \n", 0, EXIT_FAILURE)
else if (wordis("PRAGMA")) pprgma();
else ERROR("Illegal directive %s encountered\n", word, EXIT_FAILURE)
}
void prolog(void) {
DEBUG("Writing Assembly Prolog\n", 0)
asmlin(CPUOP,cputyp);
setcmt("Program ");
addcmt(srcnam);
cmtlin();
}
void epilog(void) {
if (!vrwrtn) wvrtbl(); //Write Variable Table
if (padcnt) {
SCMNT("PADDING BYTES")
sprintf(word, "$%hhX", padcnt);
asmlin(STROP, word);
}
}
/* Compile Source Code*/
void compile(void) {
DEBUG("Starting Compilation\n", 0)
prolog();
phdrfl(); //Process Header File specified on Command Line
skpchr();
DEBUG("Parsing Code\n", 0)
while (TRUE) {
skpspc();
if (match(EOF)) break; //Stop Parsing (End of File)
else if (match('}')) endblk(TRUE); //End Multi-Line Program Block
else if (match('#')) pdrctv(); //Parse Directive
else if (match('/')) skpcmt(TRUE); //Skip Comment
else if (match('*')) ppntr(); //Parse Pointer
else if (isalph()) pword(); //Parse Word
else ERROR("Unexpected character '%c'\n", nxtchr, EXIT_FAILURE)
}
epilog();
}
/* Display "Usage" text and exit*/
void usage(void) {
printf("Usage: c02 sourcefile.c02\n");
exit(EXIT_FAILURE);
}
/* Parse Command Line Option */
int popt(int arg, int argc, char *argv[]) {
char argstr[32]; //Argument String
char opt; //Option
char optarg[32]; //Option Argument
strncpy (argstr, argv[arg], 31);
if (strlen(argstr) != 2) ERROR("malformed option %s\n", argstr, EXIT_FAILURE)
opt = toupper(argstr[1]);
if (strchr("CHS", opt)) {
if (++arg >= argc) ERROR("Option -%c requires an argument\n", opt, EXIT_FAILURE)
strncpy(optarg, argv[arg], 31);
}
DEBUG("Processing Command Line Option -%c\n", argstr[1])
switch (opt) {
case 'C':
strcpy(cputyp, optarg);
DEBUG("CPU Type set to '%s'\n", cputyp)
break;
case 'H':
strcpy(hdrnam, optarg);
DEBUG("Header Name set to '%s'\n", hdrnam)
break;
case 'S':
strcpy(subdir[subcnt], optarg);
DEBUG("subdir[%d] ", subcnt)
DEBUG("set to '%s'\n", subdir[subcnt])
subcnt++;
break;
default:
ERROR("Illegal option -%c\n", opt, EXIT_FAILURE)
}
return arg;
}
/* Parse Command Line Arguments *
* Sets: srcnam - Source File Name (from first arg) *
* outnam - Output File Name (from optional second arg) */
void pargs(int argc, char *argv[]) {
int arg;
srcnam[0] = 0;
outnam[0] = 0;
DEBUG("Parsing %d arguments\n", argc)
if (argc == 0) usage(); //at least one argument is required
for (arg = 1; arg<argc; arg++) {
DEBUG("Parsing argument %d\n", arg);
if (argv[arg][0] == '-') arg = popt(arg, argc, argv); //Process Command Line Option
else if (srcnam[0] == 0) strcpy(srcnam, argv[arg]); //set Source File Name to first arg
else if (outnam[0] == 0) strcpy(outnam, argv[arg]); //set Out File Name to second arg
else ERROR("Unexpected argument '%s'\n", argv[arg], EXIT_FAILURE)
}
if (srcnam[0]) DEBUG("srcnam set to '%s'\n", srcnam)
else ERROR("Error: Source file not specified\n", 0, EXIT_FAILURE)
if (outnam[0]) DEBUG("outnam set to '%s'\n", outnam)
}
/* Validate CPU Type *
* Uses: cputype *
* Sets: cmos */
void chkcpu(void) {
if (strcmp(cputyp, "6502") == 0) cmos = FALSE;
else if (strcmp(cputyp, "65C02") == 0) cmos = TRUE;
else ERROR("Invalid CPU Type %s\n", cputyp, EXIT_FAILURE)
}
int main(int argc, char *argv[]) {
debug = TRUE; //Output Debug Info
gencmt = TRUE; //Generate Assembly Language Comments
printf("C02 Compiler (C) 2012 Curtis F Kaylor\n" );
init(); //Initialize Global Variables
pargs(argc, argv); //Parse Command Line Arguments
chkcpu(); //Validate CPU Type
opnsrc(); //Open Source File
opnout(); //Open Output File
opnlog(); //Open Log File
setsrc(); //Set Input to Source File
compile();
logstc();
logcon();
loglab();
clssrc(); //Close Source File
clsout(); //Close Output File
clslog(); //Close Log File
}
/**************************************************************
* C02 Compiler - (C) 2013 Curtis F Kaylor *
* *
* C02 is a simpified C-like language designed for the 6502 *
* *
* This Compiler generates crasm compatible assembly language *
* *
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "common.h" //Common Code used by all Modules
#include "files.h" //Open and Close Files
#include "asm.h" //Write out Assembly Language
#include "parse.h" //General Code Parsing
#include "vars.h" //Variable Parsing, Lookup, and Allocation
#include "expr.h" //Expression Parsing
#include "label.h" //Label Parsing, Generation, and Lookup
#include "cond.h" //Conditional Parsing
#include "stmnt.h" //Statement Compiling Code
#include "dclrtn.h" //Statement Compiling Code
#include "include.h" //Include File Parsing
/* Initilize Compiler Variables */
void init(void) {
DEBUG("Initializing Compiler Variables\n",0)
concnt = 0; //Number of Constants Defined
varcnt = 0; //Number of Variables in Table
lblcnt = 0; //Number of Labels in stack
padcnt = 0; //Number of Padding Bytes at End
curcol = 0; //Current Column in Source Code
curlin = 0; //Current Line in Source Code
alcvar = TRUE; //Allocate Variables Flag
inblck = FALSE; //Multiline Block Flag
infunc = FALSE; //Inside Function Definition
xstmnt[0] = 0; //Expected Statement
nxtwrd[0] = 0; //Next Word (from DEFINE lookup)
nxtptr = 0; //Pointer to next character in nxtwrd
vrwrtn = FALSE; //Variables Written Flag
rambas = 0; //RAM Base Address
wrtbas = 0; //Write Base Address
zpaddr = 0; //Current Zero-Page Address
invasc = FALSE; //Invert ASCII Flag
mskasc = FALSE; //Set High Bit Flag
fcase = FALSE; //First Case Statement Flag
wrtofs[0] = 0; //Write Offset
xsnvar[0] = 0; //Assigned X Variable Name
ysnvar[0] = 0; //Assigned Y Variable Name
subcnt = 0; //Include Subdirectories
strcpy(cputyp, CPUARG); //Set CPU Type to Default Value
strcpy(incdir, "../include/");
}
/* Parse Pointer Dereference Assignment */
void ppntr(void) {
lsrtrn = FALSE; //Clear RETURN flag
if (xstmnt[0]) ERROR("Expected '%s' statement\n", xstmnt, EXIT_FAILURE)
prcasp(';');
}
/* Reads and parses the next Word in Source File */
void pword(void) {
lsrtrn = FALSE; //Clear RETURN flag
getwrd();
DEBUG("Parsing Word '%s'\n", word)
if (xstmnt[0]) {
if (wordis(xstmnt)) xstmnt[0] = 0; //Clear xstmnt
else ERROR("Expected '%s' statement\n", xstmnt, EXIT_FAILURE)
}
if (!pmodfr() && !ptype(MTNONE)) pstmnt(); //Parse Statement
}
/* Process a directive */
void pdrctv(void) {
skpchr(); //skip '#'
CCMNT('#');
getwrd(); //read directive into word
DEBUG("Processing directive '%s'\n", word)
if (wordis("DEFINE")) pdefin(); //Parse Define
else if (wordis("INCLUDE")) pincfl(); //Parse Include File
else if (wordis("ERROR")) ERROR("Error \n", 0, EXIT_FAILURE)
else if (wordis("PRAGMA")) pprgma();
else ERROR("Illegal directive %s encountered\n", word, EXIT_FAILURE)
}
void prolog(void) {
DEBUG("Writing Assembly Prolog\n", 0)
asmlin(CPUOP,cputyp);
setcmt("Program ");
addcmt(srcnam);
cmtlin();
}
void epilog(void) {
if (!vrwrtn) wvrtbl(); //Write Variable Table
if (padcnt) {
SCMNT("PADDING BYTES")
sprintf(word, "$%hhX", padcnt);
asmlin(STROP, word);
}
}
/* Compile Source Code*/
void compile(void) {
DEBUG("Starting Compilation\n", 0)
prolog();
phdrfl(); //Process Header File specified on Command Line
skpchr();
DEBUG("Parsing Code\n", 0)
while (TRUE) {
skpspc();
if (match(EOF)) break; //Stop Parsing (End of File)
else if (match('}')) endblk(TRUE); //End Multi-Line Program Block
else if (match('#')) pdrctv(); //Parse Directive
else if (match('/')) skpcmt(TRUE); //Skip Comment
else if (match('*')) ppntr(); //Parse Pointer
else if (isalph()) pword(); //Parse Word
else ERROR("Unexpected character '%c'\n", nxtchr, EXIT_FAILURE)
}
epilog();
}
/* Display "Usage" text and exit*/
void usage(void) {
printf("Usage: c02 sourcefile.c02\n");
exit(EXIT_FAILURE);
}
/* Parse Command Line Option */
int popt(int arg, int argc, char *argv[]) {
char argstr[32]; //Argument String
char opt; //Option
char optarg[32]; //Option Argument
strncpy (argstr, argv[arg], 31);
if (strlen(argstr) != 2) ERROR("malformed option %s\n", argstr, EXIT_FAILURE)
opt = toupper(argstr[1]);
if (strchr("CHS", opt)) {
if (++arg >= argc) ERROR("Option -%c requires an argument\n", opt, EXIT_FAILURE)
strncpy(optarg, argv[arg], 31);
}
DEBUG("Processing Command Line Option -%c\n", argstr[1])
switch (opt) {
case 'D':
debug = TRUE;
DEBUG("Debug output enable\n", 0)
break;
case 'C':
strcpy(cputyp, optarg);
DEBUG("CPU Type set to '%s'\n", cputyp)
break;
case 'H':
strcpy(hdrnam, optarg);
DEBUG("Header Name set to '%s'\n", hdrnam)
break;
case 'S':
strcpy(subdir[subcnt], optarg);
DEBUG("subdir[%d] ", subcnt)
DEBUG("set to '%s'\n", subdir[subcnt])
subcnt++;
break;
default:
ERROR("Illegal option -%c\n", opt, EXIT_FAILURE)
}
return arg;
}
/* Parse Command Line Arguments *
* Sets: srcnam - Source File Name (from first arg) *
* outnam - Output File Name (from optional second arg) */
void pargs(int argc, char *argv[]) {
int arg;
srcnam[0] = 0;
outnam[0] = 0;
DEBUG("Parsing %d arguments\n", argc)
if (argc == 0) usage(); //at least one argument is required
for (arg = 1; arg<argc; arg++) {
DEBUG("Parsing argument %d\n", arg);
if (argv[arg][0] == '-') arg = popt(arg, argc, argv); //Process Command Line Option
else if (srcnam[0] == 0) strcpy(srcnam, argv[arg]); //set Source File Name to first arg
else if (outnam[0] == 0) strcpy(outnam, argv[arg]); //set Out File Name to second arg
else ERROR("Unexpected argument '%s'\n", argv[arg], EXIT_FAILURE)
}
if (srcnam[0]) DEBUG("srcnam set to '%s'\n", srcnam)
else ERROR("Error: Source file not specified\n", 0, EXIT_FAILURE)
if (outnam[0]) DEBUG("outnam set to '%s'\n", outnam)
}
/* Validate CPU Type *
* Uses: cputype *
* Sets: cmos */
void chkcpu(void) {
if (strcmp(cputyp, "6502") == 0) cmos = FALSE;
else if (strcmp(cputyp, "65C02") == 0) cmos = TRUE;
else ERROR("Invalid CPU Type %s\n", cputyp, EXIT_FAILURE)
}
int main(int argc, char *argv[]) {
debug = FALSE; //Do Not Output Debug Info by Default
gencmt = TRUE; //Generate Assembly Language Comments
printf("C02 Compiler (C) 2012 Curtis F Kaylor\n" );
init(); //Initialize Global Variables
pargs(argc, argv); //Parse Command Line Arguments
chkcpu(); //Validate CPU Type
opnsrc(); //Open Source File
opnout(); //Open Output File
opnlog(); //Open Log File
setsrc(); //Set Input to Source File
compile();
logstc();
logcon();
loglab();
clssrc(); //Close Source File
clsout(); //Close Output File
clslog(); //Close Log File
}

View File

@ -1,60 +1,44 @@
/*************************************
* C02 Common Definitions & Routines *
*************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include "common.h"
struct timespec curtim; //Current Time
/* Error - Print Input File name & position and exit */
void exterr(int errnum) {
fprintf(stderr, "Line %d Column %d of File %s\n", curlin, curcol, inpnam);
exit(errnum);
}
/* Error - print "Expected" error message *
and exit with general failure code *
Args: expected - Description of what was expected */
void expctd(char *expstr) {
fprintf(stderr, "Expected %s, but found '%c'\n", expstr, nxtchr);
exterr(EXIT_FAILURE);
}
/* Print current position in file */
void prtpos(void) { if (inpnam[0]) printf("(%s: %d,%d) ", inpnam, curlin, curcol); }
/* Initialize elapsed time counter */
void initim(void) {
timespec_get (&curtim, TIME_UTC);
bgntim = curtim.tv_sec;
}
/* Print elapsed time */
void prttim(void) {
timespec_get (&curtim, TIME_UTC);
printf("[%d", curtim.tv_sec - bgntim);
printf(".%06d]",curtim.tv_nsec/1000);
}
/* Set comment to string */
void setcmt(char *s) { strcpy(cmtasm, s); }
/* Append string to comment */
void addcmt(char *s) {
if (strlen(cmtasm)+strlen(s)<73) strcat(cmtasm, s);
}
/* Append character to comment */
void chrcmt(char c) {
if (strlen(cmtasm)>72) return;
if (cmtasm[0] == 0 && c == ' ') return;
int i = strlen(cmtasm);
cmtasm[i++] = c;
cmtasm[i] = 0;
}
/*************************************
* C02 Common Definitions & Routines *
*************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "common.h"
/* Error - Print Input File name & position and exit */
void exterr(int errnum) {
fprintf(stderr, "Line %d Column %d of File %s\n", curlin, curcol, inpnam);
exit(errnum);
}
/* Error - print "Expected" error message *
and exit with general failure code *
Args: expected - Description of what was expected */
void expctd(char *expstr) {
fprintf(stderr, "Expected %s, but found '%c'\n", expstr, nxtchr);
exterr(EXIT_FAILURE);
}
/* Print current position in file */
void prtpos(void) { if (inpnam[0]) printf("(%s: %d,%d) ", inpnam, curlin, curcol); }
/* Set comment to string */
void setcmt(char *s) { strcpy(cmtasm, s); }
/* Append string to comment */
void addcmt(char *s) {
if (strlen(cmtasm)+strlen(s)<73) strcat(cmtasm, s);
}
/* Append character to comment */
void chrcmt(char c) {
if (strlen(cmtasm)>72) return;
if (cmtasm[0] == 0 && c == ' ') return;
int i = strlen(cmtasm);
cmtasm[i++] = c;
cmtasm[i] = 0;
}

View File

@ -1,98 +1,96 @@
/*************************************
* C02 Common Definitions & Routines *
*************************************/
#define FNAMLEN 255 //Maximum File Name Length
#define LINELEN 255 //Maximum Input/Output Line Length
#define CONLEN 6 //Maximum Constant Name Length
#define MAXCON 255 //Maximum Number of Constants
#define STCLEN 6 //Maximum Struct Name Length
#define MAXSTC 32 //Maximum Number of Stuctures
#define STMLEN 6 //Maximum Struct Member Name Length
#define MAXSTM 255 //Maximum Number of Stucture Members
#define VARLEN 6 //Maximum Variable Name Length
#define MAXVAR 255 //Maximum Number of Variables
#define MAXTRM 16 //Maximum Terms in Stack
#define DATASPC 4096 //Space to Allocate for Variable Data
#define SUBMAX 4 //Maximum Number of Sub Directories
#define LABLEN 6 //Maximum Program Label Length
#define MAXLAB 255 //Maximum Number of Program Labels
#define LBLLEN 6 //Maximum Label Length
#define LBLFMT "L_%04d" //Label Format
#define LABSFX ":" //Label Suffix
#define MAXLBL 15 //Maximum Number of Labels (Nesting Depth)
#define LOCPFX "." //Local Variable Prefix
#define CPUOP "PROCESSOR" //Target CPU Pseudo-Operator
#define CPUARG "6502" //Target CPU Operand
#define ORGOP "ORG" //Origin Pseudo-Op
#define EQUOP "EQU" //Equate Pseudo-Op
#define BYTEOP "BYTE" //Define Byte Pseudo-Op
#define STROP "DS" //Define String Pseudo-Op
#define ALNOP "ALIGN" //Align Pseudo-Op
#define USEGOP "SEG.U" //Uninitalized Segment Pseudo-Op
#define LOCOP "SUBROUTINE" //Local Variable Boundary Pseudo-Op
#define ASMFMT "%-7s %-3s %-12s %s\n" //Assembly Language Line printf Format
/* Internal defines */
#define TRUE -1
#define FALSE 0
void initim(); //Initialize elapsed time counter
void prtpos(); //Print current file name and position
void prttim(); //Print elapsed time
#define DEBUG(fmt, val) {if (debug) {prtpos(); prttim(); printf(fmt, val);}}
#define DETAIL(fmt, val) {if (debug) printf(fmt, val);}
#define ERROR(fmt, val, err) {fprintf(stderr, fmt, val);exterr(err);}
int debug; //Print Debug Info (TRUE or FALSE)
int cmos; //Flag: Use 65C02 Instruction Set
int gencmt; //Generate Assembly Language Comments
char asmcmt[LINELEN]; //Processed Assembly Language Comment
int curcol, curlin; //Position in Source Code
int savcol, savlin; //Save Position in Source Code
int bgntim; //Starting Time
int nxtchr; //Next Character of Source File to Process
int nxtupc; //Next Character Converted to Uppercase
int savchr; //Holds nxtchr when switching input files
int wrdlen; //Length of Parsed Word
char word[LINELEN]; //Word parsed from source file
char uword[LINELEN]; //Word converted to uppercase
int pstlen; //Length of Parsed String
char pstrng[LINELEN]; //String parsed fron source file
char cmtasm[LINELEN]; //Assembly Language Comment Text
char cputyp[LINELEN]; //CPU Type
char hdrnam[FNAMLEN]; //Header File Name
char incdir[FNAMLEN]; //Include File Directory
char inpnam[FNAMLEN]; //Input File Name
char subdir[SUBMAX][FNAMLEN]; //Include File SubDirectory
int subcnt; //Number of Include Directories
int subidx; //Index into subdir[]
int alcvar; //Allocate Variables Flag
int inblck; //Multiline Block Flag
int infunc; //Inside Function Definition Flag
int lsrtrn; //Last Statement was a Return Flag
int fcase; //First Case Statement Flag
int padcnt; //Number of Padding Bytes at End of Program
void exterr(int errnum); //Print current file name & position and exit
void expctd(char *expected); //Print Expected message and exit
void addcmt(char *s); //Append string to comment
void chrcmt(char c); //Append character to comment
void setcmt(char *s); //Set comment to string
#define SCMNT(str) if (gencmt) {setcmt(str);}
#define ACMNT(str) if (gencmt) {addcmt(str);}
#define CCMNT(chr) if (gencmt) {chrcmt(chr);}
#define LCMNT(str) if (gencmt) {setcmt(str); cmtlin();}
/*************************************
* C02 Common Definitions & Routines *
*************************************/
#define FNAMLEN 255 //Maximum File Name Length
#define LINELEN 255 //Maximum Input/Output Line Length
#define CONLEN 6 //Maximum Constant Name Length
#define MAXCON 255 //Maximum Number of Constants
#define STCLEN 6 //Maximum Struct Name Length
#define MAXSTC 32 //Maximum Number of Stuctures
#define STMLEN 6 //Maximum Struct Member Name Length
#define MAXSTM 255 //Maximum Number of Stucture Members
#define VARLEN 6 //Maximum Variable Name Length
#define MAXVAR 255 //Maximum Number of Variables
#define MAXTRM 16 //Maximum Terms in Stack
#define DATASPC 4096 //Space to Allocate for Variable Data
#define SUBMAX 4 //Maximum Number of Sub Directories
#define LABLEN 6 //Maximum Program Label Length
#define MAXLAB 255 //Maximum Number of Program Labels
#define LBLLEN 6 //Maximum Label Length
#define LBLFMT "L_%04d" //Label Format
#define LABSFX ":" //Label Suffix
#define MAXLBL 15 //Maximum Number of Labels (Nesting Depth)
#define LOCPFX "." //Local Variable Prefix
#define CPUOP "PROCESSOR" //Target CPU Pseudo-Operator
#define CPUARG "6502" //Target CPU Operand
#define ORGOP "ORG" //Origin Pseudo-Op
#define EQUOP "EQU" //Equate Pseudo-Op
#define BYTEOP "BYTE" //Define Byte Pseudo-Op
#define STROP "DS" //Define String Pseudo-Op
#define ALNOP "ALIGN" //Align Pseudo-Op
#define USEGOP "SEG.U" //Uninitalized Segment Pseudo-Op
#define LOCOP "SUBROUTINE" //Local Variable Boundary Pseudo-Op
#define ASMFMT "%-7s %-3s %-12s %s\n" //Assembly Language Line printf Format
/* Internal defines */
#define TRUE -1
#define FALSE 0
void prtpos(); //Print current file name and position
#define DEBUG(fmt, val) {if (debug) {prtpos(); printf(fmt, val);}}
#define DETAIL(fmt, val) {if (debug) printf(fmt, val);}
#define ERROR(fmt, val, err) {fprintf(stderr, fmt, val);exterr(err);}
int debug; //Print Debug Info (TRUE or FALSE)
int cmos; //Flag: Use 65C02 Instruction Set
int gencmt; //Generate Assembly Language Comments
char asmcmt[LINELEN]; //Processed Assembly Language Comment
int curcol, curlin; //Position in Source Code
int savcol, savlin; //Save Position in Source Code
int bgntim; //Starting Time
int nxtchr; //Next Character of Source File to Process
int nxtupc; //Next Character Converted to Uppercase
int savchr; //Holds nxtchr when switching input files
int wrdlen; //Length of Parsed Word
char word[LINELEN]; //Word parsed from source file
char uword[LINELEN]; //Word converted to uppercase
int pstlen; //Length of Parsed String
char pstrng[LINELEN]; //String parsed fron source file
char cmtasm[LINELEN]; //Assembly Language Comment Text
char cputyp[LINELEN]; //CPU Type
char hdrnam[FNAMLEN]; //Header File Name
char incdir[FNAMLEN]; //Include File Directory
char inpnam[FNAMLEN]; //Input File Name
char subdir[SUBMAX][FNAMLEN]; //Include File SubDirectory
int subcnt; //Number of Include Directories
int subidx; //Index into subdir[]
int alcvar; //Allocate Variables Flag
int inblck; //Multiline Block Flag
int infunc; //Inside Function Definition Flag
int lsrtrn; //Last Statement was a Return Flag
int fcase; //First Case Statement Flag
int padcnt; //Number of Padding Bytes at End of Program
void exterr(int errnum); //Print current file name & position and exit
void expctd(char *expected); //Print Expected message and exit
void addcmt(char *s); //Append string to comment
void chrcmt(char c); //Append character to comment
void setcmt(char *s); //Set comment to string
#define SCMNT(str) if (gencmt) {setcmt(str);}
#define ACMNT(str) if (gencmt) {addcmt(str);}
#define CCMNT(chr) if (gencmt) {chrcmt(chr);}
#define LCMNT(str) if (gencmt) {setcmt(str); cmtlin();}

View File

@ -1,454 +1,457 @@
/***********************************
* C02 Expression Parsing Routines *
***********************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "common.h"
#include "asm.h"
#include "parse.h"
#include "vars.h"
#include "label.h"
#include "expr.h"
/* Push Term and Operator onto Stack */
void pshtrm(void) {
if (trmidx >= MAXTRM) ERROR("Maximum Function Call/Array Index Depth Exceeded", 0, EXIT_FAILURE)
oprstk[trmidx] = oper; //Put Current Operator on Stack
strcpy(trmstk[trmidx], term); //Put Current Term on Stack
trmidx++; //Increment Stack Pointer
DEBUG("expr.pshtrm: Pushed term %s ", term)
DETAIL("and operator '%onto stack'\n", oper)
}
/* Pop Term and Operator off Stack */
void poptrm(void) {
trmidx--; //Decrement Stack Pointer
strcpy(term, trmstk[trmidx]); //Restore Current Term from Stack
oper = oprstk[trmidx]; //Restore Current Operator from Stack
DEBUG("expr.pshtrm: Popped term %s ", term)
DETAIL("and operator '%c' off stack\n", oper)
}
/* Parse value (literal or identifier) *
* Args: alwreg - allow registers *
8 alwcon - allow constants *
* Sets: value - the value (as a string) *
* valtyp - value type */
void prsval(int alwreg, int alwcon) {
DEBUG("expr.prsval: Parsing value\n", 0)
skpspc();
if (islpre()) prslit(); //Parse Literal
else if (isalph()) prsvar(alwreg, alwcon); //Parse Variable
else if (isbtop()) prsbop(); //Parse Byte Operator
else expctd("literal or variable");
DEBUG("expr.prsval: Parsed value %s ", value)
DETAIL("of type %d\n", valtyp)
skpspc();
}
/* Process Unary Minus */
void prcmns(void) {
DEBUG("Processing unary minus", 0)
asmlin("LDA", "#$00"); //Handle Unary Minus
}
/* Parse array index *
* Args: clbrkt - require closing bracket *
* Sets: value - array index or *
* "" if no index defined */
void prsidx(int clbrkt) {
expect('[');
prsval(TRUE, TRUE); //Parse Value, Allow Registers & Constants
DEBUG("expr.prsidx: Parsed array index '%s'\n", value)
if (clbrkt) expect(']');
}
/* Process Simple Array Index *
* Uses: term - array variable name *
* valtyp - array index value type *
* value - array index as string *
* word - array index raw string *
* Sets: term - modified variable name */
void prcsix(void) {
DEBUG("expr.prcsix: Processing simple array index %s\n", word);
if (valtyp == LITERAL) {
strcat(term, "+");
strcat(term, word);
}
else if (strcmp(value, "Y")==0)
strcat(term, ",Y");
else {
if (strcmp(value, "A")==0) asmlin("TAX", "");
else if (strcmp(value, "X")!=0) asmlin("LDX", value);
strcat(term, ",X");
}
DEBUG("expr.prcsix: Set term to %s\n", term);
}
/* Process Expression Array Index */
void prcxix(void) {
DEBUG("expr.prcxix: Processing Expression Array Index", 0)
pshtrm(); //Push Array Variable onto Term Stack
if (trmcnt) asmlin("PHA", ""); //Save Accumulator if not first term
prcftm(FALSE); //Process First Term of Expression
prsrxp(']'); //Parse Rest of Expression
asmlin("TAX", ""); //Transfer Result of Expression to Index Register
if (trmcnt) asmlin("PLA", ""); //Restore Accumator if not first term
poptrm(); //Pop Array Variable off Term Stack
strcat(term, ",X");
DEBUG("expr.prcxix: Set term to %s\n", term);
}
/* Check for, Parse, and Process Index */
void chkidx(void) {
//DEBUG("Checking for Array Index with valtyp=%d\n", valtyp)
if (valtyp == ARRAY) {
if (look('-')) {
prcmns();
prcxix();
}
else {
prsidx(FALSE);
if (valtyp > REGISTER) prcxix();
else if (look(']')) prcsix();
else prcxix();
}
}
}
/* Parse Pointer *
* Sets: term - Compiled Pointer */
void prsptr(void) {
DEBUG("Parsing pointer\n", 0)
expect('*'); //Pointer Dereference Operator
prsvar(FALSE,FALSE); //Parse Variable to Dereference
strcpy(term, value);
if (varble.modifr != MTZP) ERROR("Illegal dereference of non-pointer variable %s.\n", value, EXIT_FAILURE)
DEBUG("expr.prsptr: Set term to %s\n", term);
}
/* Process Pointer Index *
* Sets: term - Compiled Pointer */
void prcptx(char *index) {
DEBUG("expr.prcptx: Processing Dereferenced Pointer %s ", term)
DETAIL("index [%s]\n", index)
if (strcmp(index,"X")==0) ERROR("Illegal use of register X\n", 0, EXIT_FAILURE);
if (strcmp(index,"A")==0) asmlin("TAY", "");
else if (strcmp(index,"Y") != 0) asmlin("LDY", index);
}
/* Process Pointer *
* Sets: term - Compiled Pointer */
int prcptr(void) {
prsptr();
DEBUG("expr.prcptr: Dereferencing Pointer %s\n", value);
if (valtyp == ARRAY) {
prsidx(TRUE);
prcptx(value);
sprintf(word, "(%s),Y", term);
} else if (cmos) {
sprintf(word, "(%s)", term);
} else {
asmlin("LDY","0");
sprintf(word, "(%s),Y", term);
}
strcpy(term, word);
DEBUG("expr.prcptr: Set term to %s\n", term);
return FALSE; //Return Value Not an Integer
}
/* Parse Term in Expression *
* Sets: term - the term (as a string) *
* Returns: TRUE if term is an integer */
int prstrm(int alwint) {
DEBUG("Parsing term\n", 0)
if (match('*')) return prcptr(); //Parse and Deference Pointer
prsval(FALSE, TRUE); //Parse Value - Disallow Registers, Allow Constants
if (valtyp == FUNCTION) ERROR("Function call only allowed in first term\n", 0, EXIT_FAILURE)
strcpy(term, value);
if (valtyp == VARIABLE && prcivr(alwint)) return TRUE;
DEBUG("expr.prstrm: Parsed term %s\n", term)
chkidx(); //Check for Array Index
skpspc();
return FALSE;
}
/* Process Address Reference
* Args: adract = Address Action (adacts) *
* symbol = Symbol to Process */
void prcadr(int adract, char* symbol) {
DEBUG("Processing address '%s'\n", word)
strcpy(word,"#>(");
strcat(word,symbol);
strcat(word,")");
if (adract == ADPUSH) { asmlin("LDA", word); asmlin("PHA", ""); }
else asmlin("LDY", word);
strcpy(word,"#<(");
strcat(word,symbol);
strcat(word,")");
if (adract == ADPUSH) { asmlin("LDA", word); asmlin("PHA", ""); }
else asmlin("LDX", word);
}
/* Parse and Compile Address of Operator *
* Args: adract = Address Action */
void prsadr(int adract) {
DEBUG("Parsing address\n", 0)
if (isnpre()) prsnum(0xFFFF);
else {
getwrd();
if (fndlab(word)) strcpy(value, word);
else prsvrw(FALSE, TRUE);
}
if (adract) prcadr(adract, value); //Compile Address Reference
else strcpy(word, value); //Save for Calling Routine
}
/* Parse and Create Anonymous String *
* Args: adract = Address Action *
* alwstr = Allow String */
void prsstr(int adract, int alwstr) {
if (!alwstr) ERROR("Illegal String Reference", 0, EXIT_FAILURE)
DEBUG("Parsing anonymous string\n", 0)
newlbl(vrname); //Generate Variable Name
value[0] = 0; //Use Variable Size 0
setvar(MTNONE, VTCHAR); //Set Variable Name, Type, and Size
prsdts(); //Parse Data String
setdat(); //Set Variable Data
varcnt++; //Increment Variable Counter
if (adract) prcadr(adract, vrname); //Compile Address Reference
else strcpy(word, vrname); //Save for Calling Routine
}
/* Check for and Process Address or String *
* Args: adract = Address Action *
* alwstr = Allow String */
int chkadr(int adract, int alwstr) {
DEBUG("Checking for Address or String\n", 0)
int result = TRUE;
if (look('&')) prsadr(adract);
else if (match('"')) prsstr(adract, alwstr);
else result = FALSE;
skpspc();
return result;
}
/* Parse Byte Operator */
void prsbop(void) {
char byteop = getnxt();
CCMNT(byteop);
DEBUG("Parsing byte operator '%c'\n", byteop)
if (chkadr(FALSE, FALSE)) {
sprintf(value, "%c(%s)", byteop, word);
valtyp = LITERAL;
} else {
reqvar(FALSE);
if (vartyp != VTINT) ERROR("Integer Value Expected\n", 0, EXIT_FAILURE)
if (byteop == '>') strcat(value, "+1");
vartyp = VTCHAR;
}
DEBUG("Set value to \"%s\"\n", value)
}
/* Parse Function Argument or Return Values */
void prsfpr(char trmntr) {
int pusha = 0; int pushy = 0; //A and Y Arguments Pushed
if (!chkadr(ADLDYX, TRUE) && isxpre() || match('.')) {
if (look('.')) pusha = 255;
else {if (prsxpf(0)) goto prsfne;}
if (look(',') && !chkadr(ADLDYX, TRUE)) {
if (look('.')) {
pushy = -1;
}
else {
if (look('(')) {
if (pusha==0) {pusha = 1; asmlin("PHA","");} //Save A on Stack
prsxpr(')'); asmlin("TAY", ""); //Evaluate Expression, and Copy to Y
}
else {
if (prstrm(TRUE)) goto prsfne;
asmlin("LDY", term);
}
}
if (look(',')) {
if (look('(')) {
if (pusha==0) {pusha = 1; asmlin("PHA","");} //Save A on Stack
if (pushy==0) {pushy = 1; asmlin("PHA",""); asmlin("PHY","");} //Save Y on Stack
prsxpr(')'); asmlin("TAX", ""); //Evaluate Expression, and Copy to X
}
else {
prsval(FALSE, TRUE); //Parse Value - Disallow Registers, Allow Constants
if (valtyp > VARIABLE) ERROR("Illegal Value Function Argument\n", 0, EXIT_FAILURE);
if (valtyp == VARIABLE && vartyp != VTCHAR) ERROR("Illegal Variable Type\n", 0, EXIT_FAILURE);
asmlin("LDX", value);
}
}
}
}
prsfne:
if (pushy==1) {asmlin("PLA",""); asmlin("TAY","");} //Pull Y Off Stack
if (pusha==1) asmlin("PLA",""); //Pull A Off Stack
expect(trmntr);
}
/* Parse function call */
void prsfnc(char trmntr) {
DEBUG("Processing Function Call '%s'\n", term)
//int argexp = FALSE; //Expression(s) in second and third argument
pshtrm(); //Push Function Name onto Term Stack
skpchr(); //skip open paren
CCMNT('(');
prsfpr(')'); //Parse Function Parameters
expect(trmntr);
poptrm(); //Pop Function Name off Term Stack
asmlin("JSR", term);
skpspc();
}
/* Process Integer Variable */
void prcvri(void) {
DEBUG("Processing Integer Variable '%s'\n", value)
asmlin("LDX", value);
strcat(value, "+1");
asmlin("LDY", value);
}
/* Process Integer Variable in Term *
* Args: alwint = Allow Integer-Like Variable *
* Returns: Integer-Like Variable Processed - TRUE/FALSE */
int prcivr(int alwint) {
switch (vartyp) {
case VTINT:
if (!alwint) ERROR("Illegal Use of Integer Variable %s\n", word, EXIT_FAILURE)
prcvri();
return TRUE;
case VTARRAY:
if (!alwint) ERROR("Illegal Reference to Array %s\n", word, EXIT_FAILURE)
prcadr(ADNONE, term);
return TRUE;
case VTSTRUCT:
if (!alwint) ERROR("Illegal Reference to Struct %s\n", word, EXIT_FAILURE)
prcadr(ADNONE, term);
return TRUE;
default:
return FALSE;
}
}
/* Process first term of expression */
int prcftm(int alwint) {
DEBUG("Processing first term '%s'\n", value)
strcpy(term, value);
if (valtyp == VARIABLE && prcivr(alwint)) return TRUE;
if (valtyp == FUNCTION) prsfnc(0); //Parse Expression Function
else if (wordis("A")) return FALSE;
else if (wordis("X")) asmlin("TXA", "");
else if (wordis("Y")) asmlin("TYA", "");
else { chkidx(); asmlin("LDA", term); }
return FALSE;
}
/* Parse first term of expession *
* First term can include function calls */
int prsftm(int alwint) {
DEBUG("Parsing first term\n", 0)
if (match('*')) {
prcptr(); //Parse and Deference Pointer
asmlin("LDA", term);
return FALSE;
}
prsval(TRUE, TRUE); //Parse Value, Allow Registers & Constants
return prcftm(alwint);
}
/* Process Arithmetic or Bitwise Operator *
* and the term that follows it */
void prcopr(void) {
DEBUG("Processing operator '%c'\n", oper)
switch(oper) {
case '+': asmlin("CLC", ""); asmlin("ADC", term); break; //Addition
case '-': asmlin("SEC", ""); asmlin("SBC", term); break; //Subtraction
case '&': asmlin("AND", term); break; //Bitwise AND
case '!': //For systems that don't have pipe in character set
case '|': asmlin("ORA", term); break; //Bitwise OR
case '^': asmlin("EOR", term); break; //Bitwise XOR
default: ERROR("Unrecognized operator '%c'\n", oper, EXIT_FAILURE)
}
oper = 0;
}
/* Parse Remainder of Expression */
void prsrxp(char trmntr) {
skpspc();
while (isoper()) {
trmcnt++; //Increment Expression Depth
prsopr(); //Parse Operator
prstrm(FALSE); //Parse Term
prcopr(); //Process Operator
trmcnt--; //Decrement Expression Depth
}
expect(trmntr);
}
int prsxpp(char trmntr, int alwint) {
DEBUG("Parsing expression\n", 0)
skpspc();
trmcnt = 0; //Initialize Expression Depth
if (match('-')) prcmns(); //Process Unary Minus
else if (prsftm(alwint)) return TRUE; //Parse First Term
prsrxp(trmntr); //Parse Remainder of Express
return FALSE;
}
/* Parse and compile expression */
void prsxpr(char trmntr) {
prsxpp(trmntr, FALSE);
}
/* Parse and compile function parameter expression *
* Returns: TRUE if Integer Expression */
int prsxpf(char trmntr) {
return prsxpp(trmntr, TRUE);
}
/* Parse and Compile Integer Expression *
* (Address, Integer Literal, Variable, *
* Struct Member, or Function) *
* Args: trmntr - expression terminator *
* asmxpr - assemble expression *
* Sets: value - Parsed Value or Symbol */
void prsxpi(char trmntr, int asmxpr) {
skpspc();
DEBUG("Parsing integer expression\n", 0)
if (!chkadr(TRUE, FALSE)) {
if (isnpre()) {
DEBUG("Parsing Integer Literal\n", 0)
int number = prsnum(0xFFFF); //Parse Number into value
if (asmxpr) {
sprintf(value, "#%d", number & 0xFF); asmlin("LDX", value);
sprintf(value, "#%d", number >> 8); asmlin("LDY", value);
}
} else if (isalph()) {
prsvar(FALSE, TRUE);
if (valtyp == FUNCTION) {
strcpy(term, value);
DEBUG("expr.prsxpi: Set term to %s\n", term)
prsfnc(0); //Parse Expression Function
} else if (valtyp == STRUCTURE) {
prsmbr(value);
if (vartyp != VTINT) ERROR("Illegal Member %s In Integer Expression", value, EXIT_FAILURE)
} else if (valtyp == VARIABLE && vartyp == VTINT) {
if (asmxpr) prcvri(); //Process Integer Variable
} else {
ERROR("Illegal Variable %s In Integer Expression", value, EXIT_FAILURE)
}
} else {
ERROR("Expected Integer Value or Function\n", 0, EXIT_FAILURE);
}
}
expect(trmntr);
}
/***********************************
* C02 Expression Parsing Routines *
***********************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "common.h"
#include "asm.h"
#include "parse.h"
#include "vars.h"
#include "label.h"
#include "expr.h"
/* Push Term and Operator onto Stack */
void pshtrm(void) {
if (trmidx >= MAXTRM) ERROR("Maximum Function Call/Array Index Depth Exceeded", 0, EXIT_FAILURE)
oprstk[trmidx] = oper; //Put Current Operator on Stack
strcpy(trmstk[trmidx], term); //Put Current Term on Stack
trmidx++; //Increment Stack Pointer
DEBUG("expr.pshtrm: Pushed term %s ", term)
DETAIL("and operator '%onto stack'\n", oper)
}
/* Pop Term and Operator off Stack */
void poptrm(void) {
trmidx--; //Decrement Stack Pointer
strcpy(term, trmstk[trmidx]); //Restore Current Term from Stack
oper = oprstk[trmidx]; //Restore Current Operator from Stack
DEBUG("expr.pshtrm: Popped term %s ", term)
DETAIL("and operator '%c' off stack\n", oper)
}
/* Parse value (literal or identifier) *
* Args: alwreg - allow registers *
8 alwcon - allow constants *
* Sets: value - the value (as a string) *
* valtyp - value type */
void prsval(int alwreg, int alwcon) {
DEBUG("expr.prsval: Parsing value\n", 0)
skpspc();
if (islpre()) prslit(); //Parse Literal
else if (isalph()) prsvar(alwreg, alwcon); //Parse Variable
else if (isbtop()) prsbop(); //Parse Byte Operator
else expctd("literal or variable");
DEBUG("expr.prsval: Parsed value %s ", value)
DETAIL("of type %d\n", valtyp)
skpspc();
}
/* Process Unary Minus */
void prcmns(void) {
DEBUG("Processing unary minus", 0)
asmlin("LDA", "#$00"); //Handle Unary Minus
}
/* Parse array index *
* Args: clbrkt - require closing bracket *
* Sets: value - array index or *
* "" if no index defined */
void prsidx(int clbrkt) {
expect('[');
prsval(TRUE, TRUE); //Parse Value, Allow Registers & Constants
DEBUG("expr.prsidx: Parsed array index '%s'\n", value)
if (clbrkt) expect(']');
}
/* Process Simple Array Index *
* Uses: term - array variable name *
* valtyp - array index value type *
* value - array index as string *
* word - array index raw string *
* Sets: term - modified variable name */
void prcsix(void) {
DEBUG("expr.prcsix: Processing simple array index %s\n", word);
if (valtyp == LITERAL) {
strcat(term, "+");
strcat(term, word);
}
else if (strcmp(value, "Y")==0)
strcat(term, ",Y");
else {
if (strcmp(value, "A")==0) asmlin("TAX", "");
else if (strcmp(value, "X")!=0) asmlin("LDX", value);
strcat(term, ",X");
}
DEBUG("expr.prcsix: Set term to %s\n", term);
}
/* Process Expression Array Index */
void prcxix(void) {
DEBUG("expr.prcxix: Processing Expression Array Index", 0)
pshtrm(); //Push Array Variable onto Term Stack
if (trmcnt) asmlin("PHA", ""); //Save Accumulator if not first term
prcftm(FALSE); //Process First Term of Expression
prsrxp(']'); //Parse Rest of Expression
asmlin("TAX", ""); //Transfer Result of Expression to Index Register
if (trmcnt) asmlin("PLA", ""); //Restore Accumator if not first term
poptrm(); //Pop Array Variable off Term Stack
strcat(term, ",X");
DEBUG("expr.prcxix: Set term to %s\n", term);
}
/* Check for, Parse, and Process Index */
void chkidx(void) {
//DEBUG("Checking for Array Index with valtyp=%d\n", valtyp)
if (valtyp == ARRAY) {
if (look('-')) {
prcmns();
prcxix();
}
else {
prsidx(FALSE);
if (valtyp > REGISTER) prcxix();
else if (look(']')) prcsix();
else prcxix();
}
}
}
/* Parse Pointer *
* Sets: term - Compiled Pointer */
void prsptr(void) {
DEBUG("Parsing pointer\n", 0)
expect('*'); //Pointer Dereference Operator
prsvar(FALSE,FALSE); //Parse Variable to Dereference
strcpy(term, value);
if (varble.modifr != MTZP) ERROR("Illegal dereference of non-pointer variable %s.\n", value, EXIT_FAILURE)
DEBUG("expr.prsptr: Set term to %s\n", term);
}
/* Process Pointer Index *
* Sets: term - Compiled Pointer */
void prcptx(char *index) {
DEBUG("expr.prcptx: Processing Dereferenced Pointer %s ", term)
DETAIL("index [%s]\n", index)
if (strcmp(index,"X")==0) ERROR("Illegal use of register X\n", 0, EXIT_FAILURE);
if (strcmp(index,"A")==0) asmlin("TAY", "");
else if (strcmp(index,"Y") != 0) asmlin("LDY", index);
}
/* Process Pointer *
* Sets: term - Compiled Pointer */
int prcptr(void) {
prsptr();
DEBUG("expr.prcptr: Dereferencing Pointer %s\n", value);
if (valtyp == ARRAY) {
prsidx(TRUE);
prcptx(value);
sprintf(word, "(%s),Y", term);
} else if (cmos) {
sprintf(word, "(%s)", term);
} else {
asmlin("LDY","0");
sprintf(word, "(%s),Y", term);
}
strcpy(term, word);
DEBUG("expr.prcptr: Set term to %s\n", term);
return FALSE; //Return Value Not an Integer
}
/* Parse Term in Expression *
* Sets: term - the term (as a string) *
* Returns: TRUE if term is an integer */
int prstrm(int alwint) {
DEBUG("Parsing term\n", 0)
if (match('*')) return prcptr(); //Parse and Deference Pointer
prsval(FALSE, TRUE); //Parse Value - Disallow Registers, Allow Constants
if (valtyp == FUNCTION) ERROR("Function call only allowed in first term\n", 0, EXIT_FAILURE)
strcpy(term, value);
if (valtyp == VARIABLE && prcivr(alwint)) return TRUE;
DEBUG("expr.prstrm: Parsed term %s\n", term)
chkidx(); //Check for Array Index
skpspc();
return FALSE;
}
/* Process Address Reference
* Args: adract = Address Action (adacts) *
* symbol = Symbol to Process */
void prcadr(int adract, char* symbol) {
DEBUG("Processing address '%s'\n", word)
strcpy(word,"#>(");
strcat(word,symbol);
strcat(word,")");
if (adract == ADPUSH) { asmlin("LDA", word); asmlin("PHA", ""); }
else asmlin("LDY", word);
strcpy(word,"#<(");
strcat(word,symbol);
strcat(word,")");
if (adract == ADPUSH) { asmlin("LDA", word); asmlin("PHA", ""); }
else asmlin("LDX", word);
}
/* Parse and Compile Address of Operator *
* Args: adract = Address Action */
void prsadr(int adract) {
DEBUG("expr.prsadr: Parsing address\n", 0)
if (isnpre()) prsnum(0xFFFF);
else {
getwrd();
if (fndlab(word)) strcpy(value, word);
else prsvrw(FALSE, TRUE);
}
if (adract) prcadr(adract, value); //Compile Address Reference
else strcpy(word, value); //Save for Calling Routine
}
/* Parse and Create Anonymous String *
* Args: adract = Address Action *
* alwstr = Allow String */
void prsstr(int adract, int alwstr) {
if (!alwstr) ERROR("Illegal String Reference", 0, EXIT_FAILURE)
DEBUG("Parsing anonymous string\n", 0)
newlbl(vrname); //Generate Variable Name
value[0] = 0; //Use Variable Size 0
setvar(MTNONE, VTCHAR); //Set Variable Name, Type, and Size
prsdts(); //Parse Data String
setdat(); //Set Variable Data
varcnt++; //Increment Variable Counter
if (adract) prcadr(adract, vrname); //Compile Address Reference
else strcpy(word, vrname); //Save for Calling Routine
}
/* Check for and Process Address or String *
* Args: adract = Address Action *
* alwstr = Allow String */
int chkadr(int adract, int alwstr) {
DEBUG("expr.chkadr: Checking for Address or String\n", 0)
int result = TRUE;
if (look('&')) prsadr(adract);
else if (match('"')) prsstr(adract, alwstr);
else result = FALSE;
skpspc();
return result;
}
/* Parse Byte Operator */
void prsbop(void) {
char byteop = getnxt();
CCMNT(byteop);
DEBUG("Parsing byte operator '%c'\n", byteop)
if (chkadr(FALSE, FALSE)) {
sprintf(value, "%c(%s)", byteop, word);
valtyp = LITERAL;
} else {
reqvar(FALSE);
if (vartyp != VTINT) ERROR("Integer Value Expected\n", 0, EXIT_FAILURE)
if (byteop == '>') strcat(value, "+1");
vartyp = VTCHAR;
}
DEBUG("Set value to \"%s\"\n", value)
}
/* Parse Function Argument or Return Values */
void prsfpr(char trmntr) {
int pusha = 0; int pushy = 0; //A and Y Arguments Pushed
DEBUG("expr.prsfpr: Parsing Function Argument or Return Values\n", 0)
if (!chkadr(ADLDYX, TRUE) && isxpre() || match('.')) {
DEBUG("expr.prsfpr: Parsing Accumulator Expression\n", 0);
if (look('.')) pusha = 255;
else {if (prsxpf(0)) goto prsfne;}
if (look(',') && !chkadr(ADLDYX, TRUE)) {
if (look('.')) {
pushy = -1;
}
else {
if (look('(')) {
if (pusha==0) {pusha = 1; asmlin("PHA","");} //Save A on Stack
prsxpr(')'); asmlin("TAY", ""); //Evaluate Expression, and Copy to Y
}
else {
if (prstrm(TRUE)) goto prsfne;
asmlin("LDY", term);
}
}
if (look(',')) {
if (look('(')) {
if (pusha==0) {pusha = 1; asmlin("PHA","");} //Save A on Stack
if (pushy==0) {pushy = 1; asmlin("PHA",""); asmlin("PHY","");} //Save Y on Stack
prsxpr(')'); asmlin("TAX", ""); //Evaluate Expression, and Copy to X
}
else {
prsval(FALSE, TRUE); //Parse Value - Disallow Registers, Allow Constants
if (valtyp > VARIABLE) ERROR("Illegal Value Function Argument\n", 0, EXIT_FAILURE);
if (valtyp == VARIABLE && vartyp != VTCHAR) ERROR("Illegal Variable Type\n", 0, EXIT_FAILURE);
asmlin("LDX", value);
}
}
}
}
prsfne:
if (pushy==1) {asmlin("PLA",""); asmlin("TAY","");} //Pull Y Off Stack
if (pusha==1) asmlin("PLA",""); //Pull A Off Stack
expect(trmntr);
}
/* Parse function call */
void prsfnc(char trmntr) {
DEBUG("Processing Function Call '%s'\n", term)
//int argexp = FALSE; //Expression(s) in second and third argument
pshtrm(); //Push Function Name onto Term Stack
skpchr(); //skip open paren
CCMNT('(');
prsfpr(')'); //Parse Function Parameters
expect(trmntr);
poptrm(); //Pop Function Name off Term Stack
asmlin("JSR", term);
skpspc();
}
/* Process Integer Variable */
void prcvri(void) {
DEBUG("Processing Integer Variable '%s'\n", value)
asmlin("LDX", value);
strcat(value, "+1");
asmlin("LDY", value);
}
/* Process Integer Variable in Term *
* Args: alwint = Allow Integer-Like Variable *
* Returns: Integer-Like Variable Processed - TRUE/FALSE */
int prcivr(int alwint) {
switch (vartyp) {
case VTINT:
if (!alwint) ERROR("Illegal Use of Integer Variable %s\n", word, EXIT_FAILURE)
prcvri();
return TRUE;
case VTARRAY:
if (!alwint) ERROR("Illegal Reference to Array %s\n", word, EXIT_FAILURE)
prcadr(ADNONE, term);
return TRUE;
case VTSTRUCT:
if (!alwint) ERROR("Illegal Reference to Struct %s\n", word, EXIT_FAILURE)
prcadr(ADNONE, term);
return TRUE;
default:
return FALSE;
}
}
/* Process first term of expression */
int prcftm(int alwint) {
DEBUG("Processing first term '%s'\n", value)
strcpy(term, value);
if (valtyp == VARIABLE && prcivr(alwint)) return TRUE;
if (valtyp == FUNCTION) prsfnc(0); //Parse Expression Function
else if (wordis("A")) return FALSE;
else if (wordis("X")) asmlin("TXA", "");
else if (wordis("Y")) asmlin("TYA", "");
else { chkidx(); asmlin("LDA", term); }
return FALSE;
}
/* Parse first term of expession *
* First term can include function calls */
int prsftm(int alwint) {
DEBUG("Parsing first term\n", 0)
if (match('*')) {
prcptr(); //Parse and Deference Pointer
asmlin("LDA", term);
return FALSE;
}
prsval(TRUE, TRUE); //Parse Value, Allow Registers & Constants
return prcftm(alwint);
}
/* Process Arithmetic or Bitwise Operator *
* and the term that follows it */
void prcopr(void) {
DEBUG("Processing operator '%c'\n", oper)
switch(oper) {
case '+': asmlin("CLC", ""); asmlin("ADC", term); break; //Addition
case '-': asmlin("SEC", ""); asmlin("SBC", term); break; //Subtraction
case '&': asmlin("AND", term); break; //Bitwise AND
case '!': //For systems that don't have pipe in character set
case '|': asmlin("ORA", term); break; //Bitwise OR
case '^': asmlin("EOR", term); break; //Bitwise XOR
default: ERROR("Unrecognized operator '%c'\n", oper, EXIT_FAILURE)
}
oper = 0;
}
/* Parse Remainder of Expression */
void prsrxp(char trmntr) {
skpspc();
while (isoper()) {
trmcnt++; //Increment Expression Depth
prsopr(); //Parse Operator
prstrm(FALSE); //Parse Term
prcopr(); //Process Operator
trmcnt--; //Decrement Expression Depth
}
expect(trmntr);
}
int prsxpp(char trmntr, int alwint) {
DEBUG("Parsing expression\n", 0)
skpspc();
trmcnt = 0; //Initialize Expression Depth
if (match('-')) prcmns(); //Process Unary Minus
else if (prsftm(alwint)) return TRUE; //Parse First Term
prsrxp(trmntr); //Parse Remainder of Express
return FALSE;
}
/* Parse and compile expression */
void prsxpr(char trmntr) {
prsxpp(trmntr, FALSE);
}
/* Parse and compile function parameter expression *
* Returns: TRUE if Integer Expression */
int prsxpf(char trmntr) {
DEBUG("expr.prsxpf: Parsing Function Expression\n", 0)
return prsxpp(trmntr, TRUE);
}
/* Parse and Compile Integer Expression *
* (Address, Integer Literal, Variable, *
* Struct Member, or Function) *
* Args: trmntr - expression terminator *
* asmxpr - assemble expression *
* Sets: value - Parsed Value or Symbol */
void prsxpi(char trmntr, int asmxpr) {
skpspc();
DEBUG("Parsing integer expression\n", 0)
if (!chkadr(TRUE, FALSE)) {
if (isnpre()) {
DEBUG("Parsing Integer Literal\n", 0)
int number = prsnum(0xFFFF); //Parse Number into value
if (asmxpr) {
sprintf(value, "#%d", number & 0xFF); asmlin("LDX", value);
sprintf(value, "#%d", number >> 8); asmlin("LDY", value);
}
} else if (isalph()) {
prsvar(FALSE, TRUE);
if (valtyp == FUNCTION) {
strcpy(term, value);
DEBUG("expr.prsxpi: Set term to %s\n", term)
prsfnc(0); //Parse Expression Function
} else if (valtyp == STRUCTURE) {
prsmbr(value);
if (vartyp != VTINT) ERROR("Illegal Member %s In Integer Expression", value, EXIT_FAILURE)
} else if (valtyp == VARIABLE && vartyp == VTINT) {
if (asmxpr) prcvri(); //Process Integer Variable
} else {
ERROR("Illegal Variable %s In Integer Expression", value, EXIT_FAILURE)
}
} else {
ERROR("Expected Integer Value or Function\n", 0, EXIT_FAILURE);
}
}
expect(trmntr);
}

View File

@ -177,7 +177,7 @@ void pincdr(void) {
void phdwrd(void) {
getwrd();
if (match(':')) prslab();
else if (!ptype(MTNONE))
else if (!pmodfr() && !ptype(MTNONE))
ERROR("Unexpected word '%s' in header\n", word, EXIT_FAILURE)
}

View File

@ -270,10 +270,12 @@ void addvar(int m, int t) {
if (fndvar(vrname)) ERROR("Duplicate declaration of variable '%s\n", vrname, EXIT_FAILURE)
if (t == VTVOID) ERROR("Illegal Variable Type\n", 0, EXIT_FAILURE)
if (m & MTZP) {
setlbl(vrname);
sprintf(word, "$%hhX", zpaddr++);
if (t == VTINT) zpaddr++; //int uses two bytes
asmlin(EQUOP, word);
if (alcvar) {
setlbl(vrname);
sprintf(word, "$%hhX", zpaddr++);
if (t == VTINT) zpaddr++; //int uses two bytes
asmlin(EQUOP, word);
}
strcpy(value, "*"); //Set Variable to Non Allocated
}
else if (m & MTALS) {

27
test/README.md Normal file
View File

@ -0,0 +1,27 @@
C02 Test Directory Contents
===========================
Compile and Run Batch Files
---------------------------
| c02.bat | Compile .c02 file into .asm file |
| a02.bat | Assemble .asm file into .bin file |
| a1.bat | Compile/Assemble .c02 file to .asc Monitor Format |
| a2.bat | Compile/Assemble .c02 file to .dsk and run AppleWin |
| c64.bat | Compile/Assemble .c02 file to .prg and run x64 |
| o1.bat | Compile/Assemble .c02 file to .tap for Oricutron |
| orao.bat | Compile/Assemble .c02 file to .wav for Orao Emulator |
| p65.bat | Compile/Assemble .c02 file to .bin for py65m |
| v8k.bat | Compile/Assemble .c02 file to .prg and run xvic |
| x16.bat | Compile/Assemble .c02 file to .prg and run x16emu |
C02 Test/Demo Programs
----------------------
| hello.c02 | Print "HELLO WORLD" using prtstr() |
| echo.c02 | Echo typed characters to screen |
| echohex.c02 | Display Hex Codes for types characters |
| conds.c02 | Test Conditional operators |
| loops.c02 | Test Loop and Conditional keywords |
| scrntst.c02 | Test module screen.h02 functions |
| sdeftest.c02 | Test module stddef.h02 functions |

14
test/a02.bat Normal file
View File

@ -0,0 +1,14 @@
@ECHO OFF
IF "%1" == "" (
ECHO Usage: %0 a02file
GOTO :EXIT
)
SET ASMEXT=""
IF EXIST %1.a02 SET ASMEXT=a02
IF EXIST %1.asm SET ASMEXT=asm
IF "%ASMEXT%" == "" (
ECHO Assembly File %1 Not Found
GOTO :EXIT
)
ECHO Assembling File %1.%ASMEXT%
..\a02.exe %1.%ASMEXT% %1.bin %1.lst >%1.out

View File

@ -10,7 +10,7 @@ ECHO Compiling File %1.c02
IF ERRORLEVEL 1 EXIT /B
ECHO Assembling File %1.asm
dasm %1.asm -f1 -o%1.obj -l%1.lst -s%1.sym
..\a02 -p %1.asm %1.obj %1.lst
IF ERRORLEVEL 1 EXIT /B
ECHO Converting Object File

View File

@ -9,7 +9,7 @@ ECHO Compiling File %1.c02
IF ERRORLEVEL 1 EXIT /B
ECHO Assembling File %1.asm
dasm %1.asm -f3 -o%1.obj -l%1.lst -s%1.sym
..\a02 %1.asm %1.obj %1.lst
IF ERRORLEVEL 1 EXIT /B
ECHO Building Disk Image

10
test/c02.bat Normal file
View File

@ -0,0 +1,10 @@
@ECHO OFF
IF EXIST %1.c02 GOTO COMPILE
ECHO File %1.c02 not found
GOTO EOF
:COMPILE
ECHO Compiling File %1.c02
..\c02.exe -h header %1 >%1.dbg
:EOF

View File

@ -1,18 +1,20 @@
@REM Compile and Run C02 Program for C64
@ECHO OFF
IF EXIST %1.c02 GOTO COMPILE
ECHO File %1.c02 not found
GOTO EOF
ECHO File %1.c02 not found
GOTO EOF
:COMPILE
ECHO Compiling File %1.c02 for Commodore 64
..\c02.exe -h c64 -s c64 -s cbm %1 >%1.dbg
..\c02.exe -d -h c64 -s c64 -s cbm %1 >%1.dbg
IF %ERRORLEVEL% NEQ 0 GOTO EOF
ECHO Assembling File %1.asm
C:\Programs\dasm %1.asm -f1 -o%1.prg -l%1.lst -s%1.sym
ECHO Assembling File %1.asm
..\a02.exe -p %1.asm %1.prg %1.lst >%1.out
IF %ERRORLEVEL% NEQ 0 GOTO EOF
ECHO Starting Emulator
@start C:\Programs\WinVICE\x64.exe -config x64.ini %1.prg
start C:\Programs\WinVICE\x64.exe -config x64.ini %1.prg
:EOF

View File

@ -3,65 +3,57 @@
****************************************/
//Specify System Header using -H option
#include <stddef.h02>
#include <stdlib.h02>
#include <stdio.h02>
char allok;
void passed() {putstr(" PASS");}
void passln() {passed(); newlin();}
void failed() {putstr(" FAIL"); allok = $00;}
void failln() {failed(); newlin();}
main:
allok = #TRUE;
allok = $FF; //TRUE
putstr("TEST CONDITIONALS"); newlin();
putstr(" 1<>1"); if (1<>1) failed(); else passed();
putstr(" 1<>2"); if (1<>2) passln(); else failln();
putstr(" 1==1"); if (1==1) passed(); else failed();
putstr(" 1==2"); if (1==2) failln(); else passln();
putstr("1+1=2"); if (1+1 == 2) passed(); else failed();
putstr(" 2<1"); if (2<1) failln(); else passln();
putstr(" 1<1"); if (1<1) failed(); else passed();
putstr(" 1<2"); if (1<2) passln(); else failln();
putstr(" 1<=1"); if (1<=1) passed(); else failed();
putstr(" 1<=2"); if (1<=2) passln(); else failln();
putstr(" 2<=1"); if (2<=1) failed(); else passed();
putstr(" 2>1"); if (2>1) passln(); else failln();
putstr(" 1>1"); if (1>1) failed(); else passed();
putstr(" 1>2"); if (1>2) failln(); else passln();
putstr(" 1>=1"); if (1>=1) passed(); else failed();
putstr(" 1>=2"); if (1>=2) failln(); else passln();
putstr(" 2>=1"); if (2>=1) passed(); else failed();
putstr(" !0:+"); if (!0:+) failln(); else passln();
putstr("$FF:+"); if ($FF:+) failed(); else passed();
putstr(" $FF"); if ($FF) passln(); else failln();
putstr("$FF:-"); if ($FF:-) passed(); else failed();
putstr(" !$FF"); if (!$FF) failln(); else passln();
putstr("$00:+"); if ($00:+) passed(); else failed();
putstr(" $00"); if ($00) failln(); else passln();
putstr("$00:-"); if ($00:-) failed(); else passed();
putstr(" !$00"); if (!$00) passln(); else failln();
putstr(" 1!0"); if (1|0) passed(); else failed();
putstr(" !1!0"); if (!1|0) failln(); else passln();
putstr(" 1&0"); if (1&0) failed(); else passed();
putstr(" !1&0"); if (!1&0) passln(); else failln();
putstr(" 1^1"); if (1^1) failed(); else passed();
putstr(" !1^1"); if (!1^1) passln(); else failln();
if (allok) putstr("ALL TESTS PASSED"); newlin();
getchr();
goto exit;
putln("Test Conditionals");
puts(" 1<>1"); if (1<>1) failed(); else passed();
puts(" 1<>2"); if (1<>2) passln(); else failln();
puts(" 1==1"); if (1==1) passed(); else failed();
puts(" 1==2"); if (1==2) failln(); else passln();
puts("1+1=2"); if (1+1 == 2) passed(); else failed();
puts(" 2<1"); if (2<1) failln(); else passln();
puts(" 1<1"); if (1<1) failed(); else passed();
puts(" 1<2"); if (1<2) passln(); else failln();
puts(" 1<=1"); if (1<=1) passed(); else failed();
puts(" 1<=2"); if (1<=2) passln(); else failln();
puts(" 2<=1"); if (2<=1) failed(); else passed();
puts(" 2>1"); if (2>1) passln(); else failln();
puts(" 1>1"); if (1>1) failed(); else passed();
puts(" 1>2"); if (1>2) failln(); else passln();
puts(" 1>=1"); if (1>=1) passed(); else failed();
puts(" 1>=2"); if (1>=2) failln(); else passln();
puts(" 2>=1"); if (2>=1) passed(); else failed();
puts(" !0:+"); if (!0:+) failln(); else passln();
puts("$FF:+"); if ($FF:+) failed(); else passed();
puts(" $FF"); if ($FF) passln(); else failln();
puts("$FF:-"); if ($FF:-) passed(); else failed();
puts(" !$FF"); if (!$FF) failln(); else passln();
puts("$00:+"); if ($00:+) passed(); else failed();
puts(" $00"); if ($00) failln(); else passln();
puts("$00:-"); if ($00:-) failed(); else passed();
puts(" !$00"); if (!$00) passln(); else failln();
puts(" 1!0"); if (1|0) passed(); else failed();
puts(" !1!0"); if (!1|0) failln(); else passln();
puts(" 1&0"); if (1&0) failed(); else passed();
puts(" !1&0"); if (!1&0) passln(); else failln();
puts(" 1^1"); if (1^1) failed(); else passed();
puts(" !1^1"); if (!1^1) passln(); else failln();
puts(" atoc(\"0\")"); if (atoc("0")) failln(); else passln();
puts(" atoc(\"1\")"); if (atoc("1")) passln(); else failln();
puts(" atoc(\"127\"):+"); if (atoc("127"):+) passln(); else failln();
puts(" atoc(\"128\"):-"); if (atoc("128"):-) passln(); else failln();
if (allok) putln("All Tests Passed");
getc();
goto exit;
void passed() {puts(" Pass");}
void passln() {passed(); newlin();}
void failed() {puts(" Fail"); allok = #FALSE;}
void failln() {failed(); newlin();}

View File

@ -11,6 +11,8 @@
char key; //Key value
main:
putstr("TYPE KEYS TO ECHO"); newlin();
putstr("ESCAPE/STOP TO END"); newlin();
while() {
key = getchr();
select (key) {

View File

@ -1,6 +1,7 @@
/*******************************************************
* ECHOHEX - Test/Demo program for C02 Standard Header *
* Displays ASCII Code of Typed Keys to Screen *
* RETURN/ENTER moves to new line *
* ESCAPE/STOP key Ends Program *
*******************************************************/
@ -9,9 +10,12 @@
char key; //Key value
main:
putstr("PRESS KEYS TO DISPLAY"); newlin();
putstr("ESCAPE/STOP TO END"); newlin();
while() {
key = getchr();
prbyte(key);
putchr(' ');
if (key==#RTNKEY) newlin();
if (key==#ESCKEY) goto exit;
}

12
test/hello.c02 Normal file
View File

@ -0,0 +1,12 @@
/*****************************************************
* HELLO - Test/Demo program for C02 Standard Header *
* Prints "HELLO WORLD" and exits *
*****************************************************/
//Specify System Header using -H option
main:
putstr("HELLO WORLD");
newlin();
goto exit;

87
test/ints.c02 Normal file
View File

@ -0,0 +1,87 @@
/****************************************************
* INTS - Test Integer Variables and Function Calls */
//Specify System Header using -H option
#include <screen.h02>
#include <stddef.h02>
#include <stdlib.h02>
#include <intlib.h02>
#include <stdio.h02>
#include <stdiox.h02>
#include <string.h02>
#include <test.h02>
char n; //Number of Characters
char r[255]; //Test Array
char s[128]; //Test String
const char istr = "9876";
const char t = "CONST STRING.";
alias int nmi = $FFFA; //NMI Vector
alias int rst = $FFFC; //Reset Vector
alias int brk = $FFFE; //Break Vector
int addr; //Various Addresses
int eoj; //End of Job
const int less = $789A;
const int more = $BCDE;
int yx, dd; //Function Arguments and Variables
char aa, xx, yy;
struct record {char name[8], index; int addr;};
struct record rec;
main:
eoj = getend();
setdst(&rec.name); strcpy("FRED");
rec.index = $AB;
rec.addr = $CDEF;
newlin();
/* Print Vector Contents */
setdst(nmi); printf("NMI=$%w%n");
setdst(rst); printf("RST=$%w%n");
setdst(brk); printf("BRK=$%w%n%n");
/* Print Contents of EOJ */
setdst(eoj); printf("EOJ=$%w%n%n");
anykey();
/* Test Function Call Arguments */
putln("ADDR=49152"); addr = 49152; setdst(&49152); cmpdst(addr);
putln("ADDR=&T"); addr = &t; setdst(t); cmpdst(addr);
putln("ADDR=&REC"); addr = &rec; setdst(&rec); cmpdst(addr);
putln("ADDR=&REC.NAME"); addr = &rec.name; setdst(&rec.name); cmpdst(addr);
putln("ADDR=&REC.INDEX"); addr = &rec.index; setdst(&rec.index); cmpdst(addr);
putln("ADDR=&REC.ADDR"); addr = &rec.addr; setdst(&rec.addr); cmpdst(addr);
anykey();
puts("GOTO (EOJ)");
goto (eoj);
failln();
goto exit;
end:
passln();
goto exit;
int getend() {
return &end;
}
void prtwrd(., yy, xx) {
putchr('$'); puthex(yy); puthex(xx);
}
void cmpdst(yx) {
dd = getdst();
prtwrd(yx); putchr('='); prtwrd(dd);
if (>yx == >dd and <yx == <dd) passln(); else failln();
newlin();
}

55
test/keydefs.c02 Normal file
View File

@ -0,0 +1,55 @@
/**********************************************
* KEYDEFS - Test/Demo for keydefs.h02 module *
**********************************************/
//Specify System Header using -H option
#include <keydef.h02>
char key; //Key value
main:
putstr("PRESS KEYS TO SEE DEFINITIONS"); newlin();
while() {
key = getchr();
if (!key) continue;
select (key) {
case #KEYBCK: putstr("BACKSPACE");
case #KEYBRK: putstr("BREAK");
case #KEYCLR: putstr("CLEAR");
case #KEYCPY: putstr("COPY");
case #KEYDEL: putstr("DELETE");
case #KEYDN : putstr("DOWN");
case #KEYESC: putstr("ESCAPE");
case #KEYFN1: putstr("F1");
case #KEYFN2: putstr("F2");
case #KEYFN3: putstr("F3");
case #KEYFN4: putstr("F4");
case #KEYFN5: putstr("F5");
case #KEYFN6: putstr("F6");
case #KEYFN7: putstr("F7");
case #KEYFN8: putstr("F8");
case #KEYFN9: putstr("F9");
case #KEYFNA: putstr("F10");
case #KEYFNB: putstr("F11");
case #KEYFNC: putstr("F12");
case #KEYHLP: putstr("HELP");
case #KEYHOM: putstr("HOME");
case #KEYINS: putstr("INSERT");
case #KEYLFT: putstr("LEFT");
case #KEYRGT: putstr("RIGHT");
case #KEYRTN: putstr("RETURN");
case #KEYRTS: putstr("SHIFT-RETURN");
case #KEYRUN: putstr("RUN");
case #KEYRVF: putstr("RVS-OFF");
case #KEYRVS: putstr("RVS-ON");
case #KEYSPS: putstr("SHIFT-SPACE");
case #KEYTAB: putstr("TAB");
case #KEYTAS: putstr("SHIFT-TAB");
case #KEYUP : putstr("UP");
case ' ': putstr("SPACE");
default: if (key > ' ' and key <> #DELKEY) putchr(key);
}
putstr(" ["); prbyte(key); putstr("] ");
if (key == #ESCKEY) break;
}
goto exit;

View File

@ -6,118 +6,115 @@
#include <stddef.h02>
#include <stdio.h02>
char i, b;
const char failed = " Test Failed!";
char aa,ii; //Function Variables
char b; //Comparison Variable
char i; //Loop Counter
void putlin() {putstr(); newlin();}
void failed() {putlin(" FAILED");}
void passed() {putlin(" PASSED");}
main:
putlin("TESTING LOOPS");
/* Test If/Goto Loop */
puts("IF ");
i = 0;
ifloop:
prbyte(i);
putc(' ');
i++;
if (i < 10) goto ifloop;
newlin();
/* Test If/Goto Loop */
putstr("IF ");
i = 0;
ifloop:
putchr('0'+i);
i++;
if (i < 8) goto ifloop;
if (i=8) passed(); else failed();
/* Test While Loop */
puts("WHILE ");
i = 0;
while (i < 10) {
prbyte(i);
putc(' ');
i++;
}
newlin();
/* Test Block If */
putstr("BLOCK ");
b = 1;
if (b>0) {
prhex(b);
putstr(" > ");
prhex(0);
passed();
}
else failed();
/* Test Do Loop */
puts("DO ");
i = 0;
do {
prbyte(i);
putc(' ');
i++;
} while (i<10);
newlin();
putstr(" IF ");
b = 0;
if (b>0) failed();
else {
putchr('0'+i);
putstr(" = ");
prhex(0);
passed();
}
/* Test For Loop */
puts("FOR ");
i = 0;
for (i=0;i<10;i++) {
prbyte(i);
putc(' ');
}
newlin();
/* Test While Loop */
putstr("WHILE ");
i = 0;
while (i < 8) {
putchr('0'+i);
i++;
}
if (i=8) passed(); else failed();
/* While with Break */
puts("BREAK ");
i = 0;
while ($FF) {
if (i = 10) break;
prbyte(i);
putc(' ');
i++;
}
newlin();
/* Test Do Loop */
putstr("DO ");
i = 0;
do {
putchr('0'+i);
i++;
} while (i<8);
if (i=8) passed(); else failed();
/* For with Continue */
puts("CONT ");
for (i=0;i<10;i++) {
if (i & 1) continue;
prbyte(i);
putc(' ');
}
newlin();
/* Test For Loop */
putstr("FOR ");
i = 0;
for (i=0;i<8;i++) {
putchr('0'+i);
}
if (i=8) passed(); else failed();
/* While with Break */
putstr("BREAK ");
i = 0;
while ($FF) {
if (i = 8) break;
putchr('0'+i);
i++;
}
if (i=8) passed(); else failed();
/* For with Continue */
putstr("CONT ");
for (i=0;i<16;i++) {
if (i & 1) { continue; i=$FF;}
putchr('A'+i);
}
if (i=16) passed(); else failed();
/* Test Do with Break and Continue*/
i = 0;
puts("DO BC ");
do {
i++;
if (!i&1) continue;
if (i>15) break;
prbyte(i);
putc(' ');
} while ($FF);
newlin();
i = 0;
putstr("DO BC ");
do {
i++;
if (!i&1) {continue; i=$FF;}
if (i>16) break;
putchr('A'+i);
} while ($FF);
if (i=17) passed(); else failed();
newlin();
/* Test Block If */
putln("BLOCK IF");
b = 1;
if (b>0) {
prbyte(b);
puts(" is greater than ");
prbyte(0);
newlin();
}
else
putln(&failed);
b = 0;
if (b>0) {
putln(&failed);
}
else {
prbyte(b);
puts(" is equal to ");
prbyte(0);
newlin();
}
newlin();
/* Test If/Else in For Loop */
putln("FOR/IF/ELSE");
for(i = 0;i<4;i++) {
prbyte(i);
if (i & 1)
putln(" is odd");
else
putln(" is even");
}
newlin();
goto exit;
/* Test If/Else, Select in For Loop */
for(i = 0;i<4;i++) {
select (i) {
case 0: putstr("FOR "); b=0;
case 1: putstr(" IF "); b=1;
case 2: putstr(" ELSE "); b=2;
case 3: putstr(" SELECT "); b=3;
default: putstr(" ERROR! "); b=$FF;
}
putchr('0'+i);
if (i & 1) putstr("-ODD "); else putstr("-EVEN");
if (i=b) passed(); else failed();
}
putlin("ALL TESTS COMPLETE");
goto exit;

35
test/orao.bat Normal file
View File

@ -0,0 +1,35 @@
@REM Compile and Assemble Program for Orao
@ECHO OFF
SET ORAOBIN=C:\Programs\OraoEmulator\bin
SET ORAOTAP=C:\Programs\OraoEmulator\tap
SET ORAOWAV=C:\Programs\OraoPy\wav
SET ORAOTOOLS=C:\Programs\OraoEmulator\tools
IF EXIST %1.c02 GOTO COMPILE
ECHO File %1.c02 not found
EXIT /B
:COMPILE
ECHO Compiling File %1.c02
..\c02.exe -h orao -s orao %1 >%1.dbg
IF ERRORLEVEL 1 EXIT /B
ECHO Assembling File %1.asm
dasm %1.asm -f1 -o%1.obj -l%1.lst -s%1.sym
IF ERRORLEVEL 1 EXIT /B
ECHO Creating Binary File
%ORAOTOOLS%\obj2bin %1.obj %ORAOBIN%\%1.bin
IF ERRORLEVEL 1 EXIT /B
ECHO Building Tape Image
%ORAOTOOLS%\maketap %ORAOTAP%\%1.tap %ORAOBIN%\%1.bin
IF ERRORLEVEL 1 EXIT /B
ECHO Building WAV File
%ORAOTOOLS%\orao2wav %ORAOBIN%\%1.bin
IF ERRORLEVEL 1 EXIT /B
MOVE %ORAOBIN%\%1.wav %ORAOWAV%
DEL %1.obj

71
test/scrntst.c02 Normal file
View File

@ -0,0 +1,71 @@
/************************************
* SCRNTST - Test C02 screen module *
************************************/
//use -h amd -s options on command line
#include <screen.h02>
char col, row, wdth, hght;
char mode, modex;
char a, c, f, i, m;
char aa, yy;
const char modes = {#SMTEXT, #SMWIDE};
void prtaxy(aa,yy) {
if (aa & $F0) prbyte(aa); else prhex(aa);
putchr('X');
if (yy & $F0) prbyte(yy); else prhex(yy);
}
void putlin() {putstr(); newlin();}
main:
for (modex=0; modex<@modes; modex++) {
mode = modes[modex];
if (mode == $FF) continue; //Unsupported Mode
if (setscr(mode)=$FF) putlin("ERROR IN SETSCR()");
m = getscr();
if (m <> mode) putlin("ERROR IN GETSCR()");
putstr("MODE="); prbyte(m); newlin();
wdth, hght = getsiz(); //Get Screen Width & Height
prtaxy(wdth,hght); newlin();
for (i=1; i<6; i++) putchr('.');
col, row = getpos(); //Get Cursor Position
prtaxy(col,row);
crsrhm(); prtaxy(getpos());
getchr(); newlin(); //Wait For keypress
clrscr(); //Clear Screen
col, row = getpos(); //Get Cursor Position
prtaxy(col, row);
f = (col == 255) ? 0 : $FF;
getchr();
if (f) clrscr(); else newlin();
if (wdth:- or hght:-) goto exit;
for (c='@'; c<'`'; c++) {
if (!f) newlin();
for (row=hght-2; row; row--) {
if (!f) putchr(' ');
for (col=wdth-2; col; col--) {
if (f) setpos(col,row);
putchr(c);
}
if (!f) newlin();
if (getkey() == #ESCKEY) goto exit;
}
if (!f) getchr();
}
if (f) getchr(); //Wait For keypress
newlin();
} //for modex
goto exit;

80
test/sdeftest.c02 Normal file
View File

@ -0,0 +1,80 @@
/**************************************
* SDEFTEST - Test Library stddef.h02 *
**************************************/
//use -h option on command line
#include <stddef.h02>
char lo,hi;
char aa,hh,ll,xx,yy;
int dstadr,srcadr;
void clrdst() {dstlo=0; dsthi=0;}
void clrreg() {return 0,0,0;}
void clrtmp() {temp0=0; temp1=0; temp2=0; temp3=0;}
void clrsrc() {srclo=0; srchi=0;}
void prskey() {putstr(" PRESS ANY KEY"); newlin(); getchr(); newlin();}
void prtcma(aa) {putchr(','); prbyte(aa);}
void prtdhl() {ll=dstlo; hh=dsthi; putstr(" DSTHI,LO="); prbyte(hh); prtcma(ll); newlin();}
void prtdst() {prbyte(dsthi);prbyte(dstlo); newlin();}
void prtlin() {putstr(); newlin();}
void prtreg(aa,yy,xx) {putstr(" A,X,Y="); prbyte(aa); prtcma(yy); prtcma(xx); newlin();}
void prtsav() {putstr(" TEMP1,2="); prtcma(temp1); prtcma(temp2); newlin();}
void prtshl() {ll=srclo; hh=srchi; putstr(" SRCHI,LO="); prbyte(hh); prtcma(ll); newlin();}
void prtsrc() {prbyte(srchi);prbyte(srclo); newlin();}
void prttmp() {putstr(" TEMP0,1,2="); prbyte(temp0); prtcma(temp1); prtcma(temp2); newlin();}
void prtwrd(.,yy,xx) {prbyte(yy); prbyte(xx); newlin();}
void setreg(aa,yy,xx) {}
main:
newlin();
putstr("#TRUE="); prbyte(#TRUE);
putstr(", #FALSE="); prbyte(#FALSE); newlin();
newlin();
prtlin("SAVREG($A,$B,$C)"); clrtmp(); savreg($A,$B,$C); prttmp();
prtlin("RESREG()"); clrreg(); prtreg(resreg());
prtlin("SAVRXY($D,$E,$F)"); clrtmp(); savrxy($D,$E,$F); prttmp();
prtlin("RESRXY()"); clrreg(); prtreg(resrxy());
newlin();
prtlin("SAVRXY(&$1234)"); putstr(" ADDTXY(&$5678)=$");
savrxy(&$1234); prtwrd(addtxy(&$5678));
prtlin("SAVRXY(&$1234)"); putstr(" SUBTXY(&$68AC)=$");
savrxy(&$1234); prtwrd(subtxy(&$68AC));
newlin();
putstr("DECRXY(&$0000)=$"); prtwrd(decrxy(&$0000));
putstr("INCRXY(&$FFFF)=$"); prtwrd(incrxy(&$FFFF));
newlin();
prskey();
prtlin("SETSRC(&$1234)"); clrsrc(); setsrc(&$1234); savsrc();
prtshl(); prtlin("SAVSRC()"); prtsav();
prtlin("RESSRC()"); clrsrc(); ressrc(); srcadr=getsrc();
prtshl(); putstr("GETSRC()="); prtwrd(srcadr);
prtlin("SETDSS()"); clrdst(); ressrc(); setdss(); prtdhl();
newlin();
prtlin("SETDST(&$5678)"); clrdst(); setdst(&$5678);savdst();
prtdhl(); prtlin("SAVDST()"); prtsav();
prtlin("RESDST()"); clrdst(); resdst(); dstadr=getdst();
prtdhl(); putstr("GETSRC()="); prtwrd(dstadr);
prtlin("SETSRD()"); clrsrc(); resdst(); setsrd(); prtshl();
newlin();
prskey();
prtlin("SETSRC(&$0FFF)"); putstr(" ADDSRA($FF)=$");
setsrc(&$0FFF); addsra($FF); prtsrc();
prtlin("SETSRC(&$1234)"); putstr(" ADDSRC(&$CDEF)=$");
setsrc(&$1234); addsrc(&$CDEF); prtsrc();
prtlin("SETDST(&$0FFF)"); putstr(" ADDDSA($FF)=$");
setdst(&$0FFF); adddsa($FF); prtdst();
prtlin("SETDST(&$1234)"); putstr(" ADDDST(&$CDEF)=$");
setdst(&$1234); adddst(&$CDEF); prtdst();
newlin();
goto exit;

231
test/slibtest.c02 Normal file
View File

@ -0,0 +1,231 @@
/**************************************************
* TESTSLIB - Test Library stdlib.h02 for py65mon *
**************************************************/
//Specify System Header using -H option
#include <stddef.h02>
#include <stdlib.h02>
char aa, yy, xx;
void prtcma(aa) {putchr(','); prbyte(aa);}
void prtlin() {putstr(); newlin();}
void prtok() {prtlin(" OK");}
void prtopr(aa,yy,xx) {prbyte(aa); putchr(yy); prbyte(xx); putchr("=");}
main:
tstabs: //Test abs()
char onum, anum, cnum;
putstr("ABS()");
onum = 0;
do { //test abs() positive numbers
anum = abs(onum);
if (onum <> anum) goto abserr;
onum++;
} while (onum < $80);
do { //test abs() negative numbers
anum = abs(onum);
cnum = -onum;
if (anum <> cnum) goto abserr;
onum++;
} while (onum);
prtok();
tstmnx: //Test min() and max()
char lnum, rnum, nnum, xnum;
putstr("MAX(), MIN()");
lnum = 0; do {
rnum = 0; do {
xnum = max(lnum,rnum);
nnum = min(lnum,rnum);
if (lnum > rnum) {
if (xnum <> lnum) maxerr();
if (nnum <> rnum) minerr();
} else {
if (xnum <> rnum) maxerr();
if (nnum <> lnum) minerr();
}
} while (rnum);
} while (lnum);
prtok();
tstmlt: //Test mult()
char mltplr, mltpnd, acmlsb, acmmsb, acmlst;
char prodct, ovrflw;
putstr("MULT()");
mltplr = 1;
do {
if (!mltplr & $F) putchr('.');
mltpnd = 1; acmlst = 0;
acmlsb = 0; acmmsb = 0;
do {
acmlsb = acmlsb + mltplr;
if (acmlsb<acmlst) acmmsb++;
acmlst = acmlsb;
prodct,ovrflw = mult(mltplr,mltpnd);
if (prodct <> acmlsb) goto mlterr;
mltpnd++;
} while (mltpnd);
mltplr++;
} while (mltplr);
prtok();
tstdiv: //Test div()
char maxmpd, divdnd, divisr, quotnt;
putstr("DIV()");
mltplr = 255;
maxmpd = 1;
drloop:
mltpnd = 1;
acmlsb = 0;
ddloop:
acmlsb = acmlsb + mltplr;
prodct = mult(mltplr, mltpnd);
quotnt = div(prodct, mltpnd);
if (quotnt <> mltplr) goto derror;
mltpnd++;
if (mltpnd < maxmpd) goto ddloop;
mltplr>>;
maxmpd<<;
if (mltplr <> 0) goto drloop;
prtok();
tstrnd: //Test rand() and rands()
char countr, rndnum, rndtbl[255];
putstr("RAND()");
rands(1); //Seed Random Number Generator;
countr = 0;
riloop:
rndtbl[countr] = 0;
countr++;
if (countr <> 0) goto riloop;
rnloop:
rndnum = rand();
if (rndtbl[rndnum] > 0) goto rnderr;
rndtbl[rndnum] = $FF;
countr++;
if (countr < 255) goto rnloop;
prtok();
tstros: //Test rotatl(), rotatr(), swap()
char lbyte, rbyte, obyte, sbyte, tbyte, scount;
putstr("ROTATL(), SHIFTL()");
obyte = 0;
do {
if (!obyte & $F) putchr('.');
scount = 0; sbyte = obyte; tbyte = obyte;
do {
rbyte = rotatl(obyte, scount); if (rbyte <> tbyte) goto rtlerr;
lbyte = shiftl(obyte, scount); if (lbyte <> sbyte) goto shlerr;
sbyte<<;
temp0 = tbyte; tbyte<<; if (temp0:-) tbyte++;
scount++; if (scount == 8) scount = $F8;
} while (scount);
obyte ++;
} while (obyte);
prtok();
putstr("ROTATR(), SHIFTR()");
obyte = 0;
do {
if (!obyte & $F) putchr('.');
scount = 0; sbyte = obyte; tbyte = obyte;
do {
rbyte = rotatr(obyte, scount); if (rbyte <> tbyte) goto rtrerr;
lbyte = shiftr(obyte, scount); if (lbyte <> sbyte) goto shrerr;
sbyte>>;
temp0 = tbyte; tbyte>>; if (temp0 & 1) tbyte = tbyte | $80;
scount++; if (scount == 8) scount = $F8;
} while (scount);
obyte ++;
} while (obyte);
prtok();
putstr("SWAP()");
lbyte=0; do {
rbyte = 0; do {
obyte = lbyte & $f0; obyte = rbyte & $0f + lbyte;
tbyte = lbyte & $0f; tbyte = rbyte & $f0 + lbyte;
sbyte = swap(obyte);
if (sbyte <> tbyte) goto swperr;
rbyte = rbyte + $11;
} while (rbyte & $0f);
} while (lbyte & $0f);
prtok();
tstc2a: //Test ctoa();
char srcchr, dstchr, tststr[4];
putstr("ATOC(), CTOA()");
srcchr = 0; do {
ctoa(srcchr, &tststr);
dstchr = atoc(&tststr);
if (srcchr <> dstchr) goto c2aerr;
srcchr++;
} while (srcchr);
prtok();
goto exit;
abserr:
putstr("ABS("); prbyte(onum); putstr(")="); prbyte(anum); prtcma(cnum); newlin();
goto exit;
maxerr:
putstr("MAX("); prbyte(lnum); prtcma(rnum); putstr(")="); prbyte(xnum); newlin();
goto exit;
minerr:
putstr("MIN("); prbyte(lnum); prtcma(rnum); putstr(")="); prbyte(nnum); newlin();
goto exit;
mlterr:
newlin(); prtopr(mltplr,'*',mltpnd); prbyte(prodct); prtcma(acmlsb); newlin();
goto exit;
derror:
newlin(); prtopr(divdnd,'/',divisr); prbyte(quotnt); prtcma(mltplr); newlin();
goto exit;
rnderr:
newlin(); putstr("RAND()="); prbyte(rndnum); prtcma(countr); newlin();
goto exit;
rtlerr:
newlin(); putstr("ROTATL("); prbyte(obyte); prtcma(scount); putstr(")=");
prbyte(rbyte); prtcma(tbyte); newlin();
goto exit;
rtrerr:
newlin(); putstr("ROTATR("); prbyte(obyte); prtcma(scount); putstr(")=");
prbyte(rbyte); prtcma(tbyte); newlin();
goto exit;
shlerr:
newlin(); putstr("SHIFTL("); prbyte(obyte); prtcma(scount); putstr(")=");
prbyte(lbyte); prtcma(sbyte); newlin();
goto exit;
shrerr:
newlin(); putstr("SHIFTR("); prbyte(obyte); prtcma(scount); putstr(")=");
prbyte(lbyte); prtcma(sbyte); newlin();
goto exit;
swperr:
newlin(); putstr("SWAP("); prbyte(obyte); putstr(")=");
prbyte(sbyte); prtcma(tbyte); newlin();
goto exit;
c2aerr:
putstr("CTOA("); prbyte(srcchr); putstr(")="); prbyte(dstchr); newlin();
goto exit;

105
test/testilib.c02 Normal file
View File

@ -0,0 +1,105 @@
/****************************************************
* INTS - Test Integer Variables and Function Calls */
//Specify System Header using -H option
#include <screen.h02>
#include <stddef.h02>
#include <stdlib.h02>
#include <intlib.h02>
#include <stdio.h02>
#include <stdiox.h02>
#include <string.h02>
#include <test.h02>
char size;
char s[128]; //Test String
int ivar,ival; //Integer Variables
int icmp,itot,ires; //Function Variables
int less, more; //Test Values for imin() and imax()
int yx, dd; //Function Arguments and Variables
void cpival(icmp) {
if (>ival <> >icmp or <ival <> <icmp) {
putwrd(ival); puts("<>"); putwrd(icmp);
failln();
goto exit;
}
}
/* Test imin() and imax() */
void minmax() {
newlin();
puts("LESS=$"); putwrd(less); puts(",MORE=$"); putwrd(more); newlin();
puts(" IMIN()=$"); setsrc(less);
ival = imin(more); putwrd(ival); newlin();
cpival(less);
puts(" IMAX()=$"); setsrc(less);
ival = imax(more); putwrd(ival); newlin();
cpival(more);
}
/* Test cvibcd() and upbcdi() */
void intbcd(ival) {
newlin(); puts("CVIBCD($"); putwrd(ival); puts(")=$");
cvibcd(ival); puthex(temp2); puthex(temp1); puthex(temp0);
}
/* Test itoa() and atoi() */
void itaati(ivar) {
newlin();
puts("ITOA($"); putwrd(ivar); puts(")=\"");
setdst(s); size = itoa(ivar); puts(s); putln("\"");
puts("ATOI(\""); puts(s); puts("\")=$");
ival = atoi(s); putwrd(ival); newlin();
//cpival(ivar);
}
/* Test iadd() and isub() */
void addsub(ivar) {
newlin();
putint(ival); putchr('+'); putint(ivar); putchr('=');
setsrc(ival); itot = iadd(ivar); putint(itot); newlin();
putint(itot); putchr('-'); putint(ivar); putchr('=');
setsrc(itot); ires = isub(ivar); putint(ires); newlin();
cpival(ires);
}
/* Test imult() and idiv() */
void mltdiv(ivar) {
newlin();
putint(ival); putchr('X'); putint(ivar); putchr('=');
setsrc(ival); itot = imult(ivar); putint(itot); newlin();
putint(itot); putchr('/'); putint(ivar); putchr('=');
setsrc(itot); ires = idiv(ivar); putint(ires); newlin();
cpival(ires);
}
main:
less = $009A; more = $00DE; minmax();
less = $789A; more = $78DE; minmax();
less = $7800; more = $BC00; minmax();
less = $789A; more = $BCDE; minmax();
anykey();
itaati(&0);
itaati(&234);
itaati(&256);
itaati(&456);
itaati(&23456);
itaati(&$FFFF);
anykey();
ival = &23; addsub(&34);
ival = &1234; addsub(&5678);
ival = &23456; addsub(&34567);
ival = &$7700; addsub(&$6600);
ival = &$7FFF; addsub(&$8000);
anykey();
//ival = &123; mltdiv(&234);
goto exit;

View File

@ -1,53 +0,0 @@
/************************************
* TESTHDR - Test C02 screen module *
************************************/
//use -h amd -s options on command line
#include <screen.h02>
char col, row, wdth, hght;
char c, f, i, aa, yy;
void prtaxy(aa,yy) {
if (aa & $F0) prbyte(aa); else prhex(aa);
putchr('X');
if (yy & $F0) prbyte(yy); else prhex(yy);
}
main:
wdth, hght = getsiz(); //Get Screen Width & Height
prtaxy(wdth,hght); newlin();
for (i=1; i<6; i++) putchr('.');
col, row = getpos(); //Get Cursor Position
prtaxy(col,row);
crsrhm(); prtaxy(getpos());
getchr(); newlin(); //Wait For keypress
clrscr(); //Clear Screen
col, row = getpos(); //Get Cursor Position
prtaxy(col, row);
f = (col == 255) ? 0 : $FF;
getchr();
if (f) clrscr(); else newlin();
if (wdth:- or hght:-) goto exit;
for (c='@'; c<'`'; c++) {
if (!f) newlin();
for (row=hght-2; row; row--) {
if (!f) putchr(' ');
for (col=wdth-2; col; col--) {
if (f) setpos(col,row);
putchr(c);
}
if (!f) newlin();
if (getkey() == #ESCKEY) goto exit;
}
if (!f) getchr();
}
if (f) getchr(); //Wait For keypress
newlin();
goto exit;

View File

@ -1,82 +0,0 @@
/************************************************
* TESTSD - Test Library stddef.h02 for py65mon *
************************************************/
//use -h option on command line
#include <stddef.h02>
const char txtstr = {
"#TRUE=",", #FALSE=",
"SAVREG($A,$B,$C)", " TEMP0,1,2=",
"RESREG()", " A,X,Y=",
"SETSRC(&$1234)"," SRCLO,HI=", " GETSRC()=",
"SETDST(&$5678)"," DSTLO,HI=", " GETDST()="
};
char txtidx;
char aa,xx,yy;
main:
txtidx = 0;
newlin();
prttxt(); prbyte(#TRUE);
prttxt(); prbyte(#FALSE);
newlin(); newlin();
temp0=0; temp1=0; temp3 = 0;
prtlin(); savreg($A,$B,$C);
prttxt(); prbyte(temp0);
prtcma(); prbyte(temp1);
prtcma(); prbyte(temp2);
newlin();
setreg(0,0,0);
prtlin(); aa,yy,xx = resreg();
prttxt(); prbyte(aa);
prtcma(); prbyte(yy);
prtcma(); prbyte(xx);
newlin(); newlin();
srclo = 0; srchi = 0;
prtlin(); setsrc(&$1234);
prttxt(); prbyte(srclo);
prtcma(); prbyte(srchi);
newlin();
prttxt(); setreg(0,0,0);
getsrc(); prtwrd();
newlin(); newlin();
dstlo = 0; dsthi = 0;
prtlin(); setdst(&$5678);
prttxt(); prbyte(dstlo);
prtcma(); prbyte(dsthi);
newlin();
prttxt(); setreg(0,0,0);
getdst(); prtwrd();
newlin(); newlin();
goto exit;
void setreg(aa,yy,xx) {}
void prtwrd(aa,yy,xx) {
prbyte(yy);
prbyte(xx);
}
void prtcma() {prchr(',');}
void prtlin() {prttxt(); newlin();}
void prttxt() {
while (txtstr[txtidx]) {
//prbyte(txtidx);prchr(' ');
prchr(txtstr[txtidx]);
txtidx++;
}
txtidx++;
}

View File

@ -1,220 +0,0 @@
/************************************************
* TESTSL - Test Library stdlib.h02 for py65mon *
************************************************/
//Specify System Header using -H option
#include <stddef.h02>
#include <stdlib.h02>
main:
tstabs: //Test abs()
char onum, anum, cnum;
prchr('A');
prchr('B');
prchr('S');
prchr(' ');
//test abs() positive numbers
onum = 0;
aploop:
anum = abs(onum);
if (onum <> anum) goto abserr;
onum++;
if (onum < $80) goto aploop;
//test abs() negative numbers
anloop:
anum = abs(onum);
cnum = -onum;
if (anum <> cnum) goto abserr;
onum++;
if (onum > $00) goto anloop;
prchr('O');
prchr('K');
newlin();
tstmlt: //Test mult()
char mltplr, mltpnd, acmlsb, acmmsb, acmlst;
char prodct, ovrflw;
mltplr = 1;
mrloop:
prbyte(mltplr);
mltpnd = 1; acmlst = 0;
acmlsb = 0; acmmsb = 0;
mdloop:
acmlsb = acmlsb + mltplr;
if (acmlsb<acmlst) acmmsb++;
acmlst = acmlsb;
prodct,ovrflw = mult(mltplr,mltpnd);
if (prodct <> acmlsb) goto merror;
//if (ovrflw <> acmmsb) goto merror;
mltpnd++;
if (mltpnd > 0) goto mdloop;
mltplr++;
if (mltplr > 0) goto mrloop;
newlin();
prchr('M');
prchr('U');
prchr('L');
prchr('T');
prchr(' ');
prchr('O');
prchr('K');
newlin();
tstdiv: //Test div()
char maxmpd, divdnd, divisr, quotnt;
mltplr = 255;
maxmpd = 1;
drloop:
prbyte(mltplr);
mltpnd = 1;
acmlsb = 0;
ddloop:
prbyte(mltpnd);
acmlsb = acmlsb + mltplr;
prodct = mult(mltplr, mltpnd);
quotnt = div(prodct, mltpnd);
if (quotnt <> mltplr) goto derror;
mltpnd++;
if (mltpnd < maxmpd) goto ddloop;
newlin();
mltplr>>;
maxmpd<<;
if (mltplr <> 0) goto drloop;
newlin();
prchr('D');
prchr('I');
prchr('V');
prchr(' ');
prchr('O');
prchr('K');
newlin();
tstrnd: //Test rand() and rands()
char countr, rndnum, rndtbl[255];
rands(1); //Seed Random Number Generator;
countr = 0;
riloop:
rndtbl[countr] = 0;
countr++;
if (countr <> 0) goto riloop;
rnloop:
rndnum = rand();
if (rndtbl[rndnum] > 0) goto rnderr;
rndtbl[rndnum] = $FF;
prbyte(rndnum);
prchr(' ');
countr++;
if (countr < 255) goto rnloop;
newlin();
prchr('R');
prchr('A');
prchr('N');
prchr('D');
prchr(' ');
prchr('O');
prchr('K');
newlin();
tstc2a: //Test ctoa();
char srcchr, dstchr, tststr[4];
srcchr = 0;
caloop:
prbyte(srcchr);
prchr(' ');
ctoa(srcchr, &tststr);
dstchr = atoc(&tststr);
if (srcchr <> dstchr) goto c2aerr;
srcchr++;
if (srcchr <> 0) goto caloop;
newlin();
prchr('C');
prchr('T');
prchr('O');
prchr('A');
prchr(' ');
prchr('O');
prchr('K');
newlin();
goto exit;
abserr:
prchr('A');
prchr('B');
prchr('S');
prchr('(');
prbyte(onum);
prchr(')');
prchr('=');
prbyte(anum);
prchr(',');
prbyte(cnum);
newlin();
goto exit;
merror:
newlin();
prbyte(mltplr);
prchr('*');
prbyte(mltpnd);
prchr('=');
//prbyte(ovrflw);
prbyte(prodct);
prchr(',');
//prbyte(acmmsb);
prbyte(acmlsb);
newlin();
goto exit;
derror:
newlin();
prbyte(divdnd);
prchr('/');
prbyte(divisr);
prchr('=');
prbyte(quotnt);
prchr(',');
prbyte(mltplr);
newlin();
goto exit;
rnderr:
prchr('R');
prchr('A');
prchr('N');
prchr('D');
prchr('(');
prchr(')');
prchr('=');
prbyte(rndnum);
prchr(',');
prbyte(countr);
newlin();
goto exit;
c2aerr:
prchr('C');
prchr('T');
prchr('O');
prchr('A');
prchr('(');
prbyte(srcchr);
prchr(')');
prchr('=');
prbyte(dstchr);
newlin();
goto exit;

View File

@ -8,8 +8,8 @@ ECHO Compiling File %1.c02 for VIC 20 +8k
..\c02.exe -h vic8k -s vic -s cbm %1 >%1.dbg
IF %ERRORLEVEL% NEQ 0 GOTO EOF
ECHO Assembling File %1.asm
C:\Programs\dasm %1.asm -f1 -o%1.prg -l%1.lst -s%1.sym
..\a02.exe -p %1.asm %1.prg %1.lst >%1.out
REM C:\Programs\dasm %1.asm -f1 -o%1.prg -l%1.lst -s%1.sym
IF %ERRORLEVEL% NEQ 0 GOTO EOF
ECHO Starting Emulator

272
test/xmemtest.c02 Normal file
View File

@ -0,0 +1,272 @@
/**************************************
* TESTXMEM - Test Library xmemory.h02 *
**************************************/
//use -h option on command line
#include <screen.h02>
#include <stddef.h02>
#include <stdlib.h02>
#include <intlib.h02>
#include <stdio.h02>
#include <stdiox.h02>
#include <xmemory.h02>
char aa; //Function Arguments
alias char banked = $A000; //Beginning of Banked Memory
int icount;
char i; //Index Variable
char chrctr; //Get/Put Character
int intger; //Get/Put Integer
char r[255],w[255]; //Read/Write Arrays
char ibank, ipage, ibyte; //Index Bank, Page, and Byte
char lbank, lpage, lbyte; //Logical Bank, Page, and Byte
char mbank, mpage, mbyte; //Memory Bank, Page, and Byte
char pbank, ppage, pbyte; //Physical Bank, Page, and Byte
char sbank, spage, sbyte; //Starting Bank, Page, and Byte
char ebank, epage, ebyte; //Starting Bank, Page, and Byte
void passed() { putln("PASSED");}
void paddrs(aa) {
if (aa) newlin(); else puts(", ");
printf(setdst(xgetpa()),"PA=$%h%w, ");
printf(setdst(xgetla()),"LA=$%h%w ");
}
void perror() {
printf(); //Implied Arguments
paddrs(#FALSE);
newlin();
goto exit;
}
/* Test xclcpa() and xclcla() */
void tstlpl(sbank,spage,sbank) {
ibank=sbank; ipage=spage; ibyte=sbyte;
while (ibank<=#XLBANK) {
putc('.');
while() {
while() {
//printf(setdst(ibank,ipage,ibyte),"%n ORIGINAL: $%h%w");
pbank,ppage,pbyte = xclcpa(ibank,ipage,ibyte);
//printf(setdst()," PHYSICAL: $%h%w");
lbank,lpage,lbyte = xclcla(pbank,ppage,pbyte);
//printf(setdst(),", LOGICAL: $%h%w");
if (lbank<>ibank or lpage<>ipage or ibyte<>lbyte)
perror(setdst(ibank,ipage,ibyte),"%nERROR IN BANK $%h ADDRESS $%w");
if (getkey()==#ESCKEY) goto exit;
ibyte=ibyte+$10; if (!ibyte) break;
} ipage++; if (!ipage) break;
} ibank++; if (!ibank) break;
}
}
/* Test xgetla() and xsetla() */
void tstgsl(ibank,ipage,ibank) {
while (ibank<=#XLBANK) {
putc('.');
while() {
while() {
//printf(setdst(ibank,ipage,ibyte),"%n SET: $%h%w");
xsetla(ibank,ipage,ibyte);
lbank,lpage,lbyte = xgetla();
//printf(setdst(),", GOT: $%h%w");
if (lbank<>ibank or lpage<>ipage or ibyte<>lbyte)
perror(setdst(ibank,ipage,ibyte),"%nERROR IN BANK $%h ADDRESS $%w");
if (getkey()==#ESCKEY) goto exit;
ibyte=ibyte+$10; if (!ibyte) break;
} ipage++; if (!ipage) break;
} ibank++; if (!ibank) break;
}
}
/* Test xincpa() */
void tstipa(ibank,ipage,ibank) {
xsetla(ibank,ipage,ibyte); //Set Logical Address to 0
while (ibank<=#XLBANK) {
putc('.');
while() {
//clrscr();
while() {
pbank,ppage,pbyte = xgetpa(ibank,ipage,ibyte);
//printf(setdst(),"$%h%w:");
lbank,lpage,lbyte = xgetla(); //Get Logical Address
//printf(setdst(),"$%h%w ");
if (lbank<>ibank or lpage<>ipage or ibyte<>lbyte)
perror(setdst(ibank,ipage,ibyte),"%nERROR IN BANK $%h ADDRESS $%w");
xincpa(); //Increment Physical Address
ibyte++; if (!ibyte) break;
} ipage++; if (!ipage) break;
if (getkey()==#ESCKEY) goto exit;
} ibank++; if (!ibank) break;
}
}
/* Test xgetc() and xputc() */
void tstgpc(sbank,spage,sbyte) {
while() {
//printf(setdst(),"$%h%w");
putc('.');
ibank=sbank; ipage=spage; ibyte=sbyte;
xsetla(ibank,ipage,ibyte);
i=0; do { xputc(i); i++; } while (i);
xsetla(ibank,ipage,ibyte);
i=0; do {
if (xgetc()<>i) perror(setdst(xgetpa()),"%nERROR IN BANK $%h ADDRESS $%w");
i++;
} while (i);
sbank++;spage++;sbyte++;
if (!sbank or sbank>#XLBANK) break;
}
}
/* Test xgeti() and xputi() */
void tstgpi(sbank,spage,sbyte) {
while() {
//*printf(setdst(),"$%h%w");
putc('.');
ibank=sbank; ipage=spage; ibyte=sbyte;
//Write 256 Integers
xsetla(ibank,ipage,ibyte);
i=0; do {
mpage=i;mbyte=i^$FF;
xputi(.,mpage,mbyte);
i++;
} while (i);
//Read 256 Integers
xsetla(ibank,ipage,ibyte);
i=0; do {
mpage=i;mbyte=i^$FF;
intger = xgeti();
if (<intger<>mbyte or >intger<>mpage)
perror(setdst(xgetpa()),"%nERROR IN BANK $%h ADDRESS $%w");
i++;
} while (i);
//Set Next Start Address
sbank++;spage++;sbyte++;
if (!sbank or sbank>#XLBANK) break;
}
}
/* Test xgetl() and xputl() */
void tstgpl(sbank,spage,sbyte) {
while() {
//*printf(setdst(),"$%h%w");
putc('.');
ibank=sbank; ipage=spage; ibyte=sbyte;
//Write 256 Integers
xsetla(ibank,ipage,ibyte);
i=0; do {
mbyte=i; mpage=i^$FF; mbank = -i;
xputi(mbank,mpage,mbyte);
i++;
} while (i);
//Read 256 Integers
xsetla(ibank,ipage,ibyte);
i=0; do {
mbyte=i; mpage=i^$FF; mbank = -i;
intger = xgeti();
if (<intger<>mbyte or >intger<>mpage)
perror(setdst(xgetpa()),"%nERROR IN BANK $%h ADDRESS $%w");
i++;
} while (i);
//Set Next Start Address
sbank++;spage++;sbyte++;
if (!sbank or sbank>#XLBANK) break;
}
}
/* Test xread() and xwrite() */
void tstxrw(sbank,spage,epage) {
i=0; do {w[i]=i;i++;} while (i); //Fill Write Array
ibank=sbank;
while (ibank<=#XLBANK) {
putc('.');
//Write 256,1-255 bytes of Array
ipage=spage; xsetla(ibank,0,ipage);
do {
//paddrs(#TRUE);
//inline $ff;
xwrite(ipage,&w);
//if (banked=61) perror("MEMORY OVERWRITE ERROR!");
ipage++;
} while (ipage<>epage);
//paddrs(#TRUE);
//Read 256,1-255 bytes of Array
ipage=spage; xsetla(ibank,0,ipage);
do {
//printf(ipage,"%n%h:");
//inline $ff;
//paddrs(#TRUE);
xread(ipage,&r);
i=0; do {
//printf(r[i],"%h."); printf(w[i],"%h,");
if (r[i]<>w[i]) perror(i,"ERROR IN INDEX %d");
i++;
} while(i<>ipage);
ipage++;
} while (ipage<>epage);
ibank++; if (!ibank) break;
}
}
/* Test xload() and xsave() */
void tstxls(sbank,spage,sbyte) {
setsrc(&$F000); //Most Systems have ROM from $F000 to $FFFF
xsetla(sbank,spage,sbyte);
xsave(&$1000); //Save through $FFFF
setdst(&$8000); //There's usually free RAM here
xsetla(sbank,spage,sbyte);
xload(&$1000); //Load bytes saved from $F000 to $FFFF
srcptr = &$F000; dstptr = &$8000; icount = &$1000;
while (<icount or >icount) {
//putwrd(srcptr); putchr(':'); puthex(*srcptr); putspc();
//putwrd(dstptr); putchr(':'); puthex(*dstptr); putspc();
if (*srcptr <> *dstptr) perror("ERROR IN XLOAD() AND/OR XSAVE()\n");
if (!<icount) putc('.');
srcptr++; dstptr++; icount--;
}
}
main:
if (!#XLBANK) perror("Extended Memory Not Supported");
/*
puts("TESTING XCLCPA() AND XCLCLA()");
tstlpl($00,$00,$00);
passed();
//XGETPA() AND XSETPA() NOT DIRECTLY TESTED
//VALID VALUES ARE SYSTEM DEPENDENT
puts("TESTING XGETLA() AND XSETLA()");
tstgsl($00,$00,$00);
passed();
puts("TESTING XINCPA().............");
tstipa($00,$00,$00);
passed();
puts("TESTING XPUTC() AND XGETC()..");
tstgpc($00,$00,$00);
passed();
puts("TESTING XPUTI() AND XGETI()..");
tstgpi($00,$00,$00);
passed();
puts("TESTING XREAD() AND XWRITE().");
tstxrw($00,$00,$7F);
passed();
*/
puts("TESTING XLOAD() AND XSAVE().");
tstxls($00,$00,$00);
passed();
goto exit;

View File

@ -1,3 +1,14 @@
@ECHO Assembling File %1.asm
dasm %1.asm -f3 -o%1.bin -l%1.lst -s%1.sym
@ECHO OFF
IF "%1" == "" (
ECHO Usage: %0 a02file
GOTO :EXIT
)
SET ASMEXT=""
IF EXIST %1.a02 SET ASMEXT=a02
IF EXIST %1.asm SET ASMEXT=asm
IF "%ASMEXT%" == "" (
ECHO Assembly File %1 Not Found
GOTO :EXIT
)
ECHO Assembling File %1.%ASMEXT%
..\a02.exe -d %1.%ASMEXT% %1.bin %1.lst >%1.out

18
work/a02inc.a02 Normal file
View File

@ -0,0 +1,18 @@
;A02 Assembler Test Include File
TRUE: EQU $FF
FALSE: .EQU $00
one equ 1
two .equ 1 + 1
three equ one + one + one
four .equ three + 1
PNTR: EQU $80
.local EQU 99
STRUCT EQU $0FFF
.END ;Return to Main File
IGNORE EQU $9999 ;This will Not be Assembled

103
work/a02test.a02 Normal file
View File

@ -0,0 +1,103 @@
;A02 Assembler Test File
INCLUDE "a02inc.a02"
start ORG $0400 ;Start of Code
SUBROUTINE
flags: CLC
SEC
CLI
SEI
CLV
CLD
.local SED
SUBROUTINE
rgstr: DEX
DEY
INX
INY
TAX
TAY
TSX
TXA
TXS
TYA
SUBROUTINE
retrn: RTI
RTS
SUBROUTINE
stack: PHA
PHP
PHX
PHY
PLA
PLP
PLX
PLY
SUBROUTINE
other: NOP
BRK
SUBROUTINE
branch: BCC rgstr
BCS flags
.loop BEQ retrn
BNE jump
BMI .next
BPL .loop
BRA branch
.next BVC +127
BVS -128
SUBROUTINE
jump JMP .next
JMP (words )
JMP (pntr,x)
.next JSR retrn
SUBROUTINE
memory: ADC #$98 ;Immediate
AND TABLE,Y ;Absolute,Y
CMP PNTR,Y ;Absolute,Y (Zero Page Address)
EOR (PNTR,X) ;(Indirect,X)
LDA (PNTR),Y ;(Indirect),Y
ORA (PNTR) ;(Indirect)
ASL ;Accumulator
DEC PNTR ;ZeroPage
INC PNTR,X ;ZeroPage,X
LSR BYTES ;Absolute
ROL BYTES,X ;Absolute,X
ROR $ABCD,X ;Absolute,X
CPX #$76 ;Immediate
CPY PNTR ;ZeroPage
STY PNTR,X ;ZeroPage,X
STZ $CDEF ;Absolute
LDY $CDEF,X ;Absolute,X
TRB PNTR ;ZeroPage
TSB $1234 ;Absolute
SUBROUTINE
exprsn LDA #PNTR+1 ;Immediate
LDA PNTR+1 ;ZeroPage
LDA (PNTR+2) ;Indirect
LDA (PNTR+4,X) ;(Indirect,X)
LDA (PNTR+6),Y ;(Indirect),Y
LDA STRUCT ;Absolute
LDX #<STRUCT ;LSB Immediate
LDY #>STRUCT ;MSB Immediate
LDA STRUCT+1
LDX #<STRUCT+1
LDY #>STRUCT+1
LDA STRUCT+2
LDX #<(STRUCT+2)
LDY #>(STRUCT+2)
BYTES byte 99, %10101010,'~' ;Bytes
.byte $12,$34
HEXES hex 01,23,45,67,89 ;Hexadecimal
.hex ,AB,CD,EF,1A,2B,3C,D4,E5,F6
WORDS word $3456
Align 256
TABLE .word $1357,$9BDF,$2468
TEXT byte "ABCDEFGHIJKLMNOPQRSTUVWXYZ",0
END ;Nothing after this will be Assembled
STY (STRUCT),X ;Illegal Addressing Mode
DC.W ;Unsupported Pseudo-Op

View File

@ -1,3 +1,3 @@
@ECHO Compiling File %1.c02
..\c02.exe %1 >%1.dbg
..\c02.exe -c 65C02 %1 >%1.dbg

View File

@ -1,8 +0,0 @@
OP VALUE
= 1
< 2
<= 3
> 4
>= 5
<> 6

258
work/opcodes.a02 Normal file
View File

@ -0,0 +1,258 @@
PROCESSOR 6502
ORG $1000
X00 BRK ;00
X01 ORA ($10,X) ;01
X02 BYTE $02 ;NOP #IMD
X03 BYTE $03 ;NOP
X04 TSB $40 ;04
X05 ORA $50 ;05
X06 ASL $60 ;06
X07 RMB 0,$70 ;07
X08 PHP ;08
X09 ORA #$90 ;09
X0A ASL ;0A
X0B BYTE $0B ;NOP
X0C TSB $CBA9 ;0C
X0D ORA $DCBA ;0D
X0E ASL $EDCB ;0E
X0F BBR0 $F0,X00 ;0F
X10 BPL X11 ;10
X11 ORA ($11),Y ;11
X12 BYTE $12 ;NOP #IMD
X13 BYTE $13 ;NOP
X14 TRB $51 ;14
X15 ORA $61,X ;15
X16 ASL $71,X ;16
X17 RMB1 $71 ;17
X18 CLC ;18
X19 ORA $A987,Y ;19
X1A BYTE $1A ;1A
X1B BYTE $1B ;1A
X1C TRB $CBA9 ;1C
X1D ORA $DCBA,X ;1D
X1E ASL $EDCB,X ;1E
X1F BBR 1,$F1,X11 ;1F
X20 JSR $0123 ;20
X21 AND ($12,X) ;21
X22 BYTE $22 ;NOP #IMD
X23 BYTE $23 ;NOP
X24 BIT $42 ;24
X25 AND $52 ;25
X26 ROL $62 ;26
X27 RMB 2,$72 ;27
X28 PLP ;28
X29 AND #$92 ;29
X2A ROL ;2A
X2B BYTE $2B ;2B
X2C BIT $CBDA ;2C
X2D AND $DCBA ;2D
X2E ROL $EDCB ;2E
X2F BBR2 $F2,X22 ;2F
X30 BMI X33 ;30
X31 AND ($13),Y ;31
X32 BYTE $32 ;NOP #IMD
X33 BYTE $33 ;NOP
X34 BIT $43,X ;34
X35 AND $53,X ;35
X36 ROL $63,X ;36
X37 RMB3 $73 ;37
X38 SEC ;38
X39 AND $9876,Y ;39
X3A DEC ;3A
X3B BYTE $3B ;NOP
X3C BIT $CBA9,X ;3C
X3D AND $DCBA,X ;3D
X3E ROL $EDCB,X ;3E
X3F BBR 3,$F3,X33 ;3F
X40 RTI ;40
X41 EOR ($14,X) ;41
X42 BYTE $42 ;NOP #IMD
X43 BYTE $43 ;NOP
X44 BYTE $44 ;NOP $ZP
X45 EOR $54 ;45
X46 LSR $64 ;46
X47 RMB 4,$74 ;47
X48 PHA ;48
X49 EOR #$94 ;49
X4A LSR ;4A
X4B BYTE $4B ;NOP
X4C JMP $CBA9 ;4C
X4D EOR $DCBA ;4D
X4E LSR $EDCB ;4E
X4F BBR4 $F4,X44 ;4F
X50 BVC X55 ;50
X51 EOR ($15),Y ;51
X52 EOR ($25) ;52
X53 BYTE $53 ;NOP
X54 BYTE $54 ;NOP $ZP
X55 EOR $55,X ;55
X56 LSR $65,X ;56
X57 RMB5 $75 ;57
X58 CLI ;58
X59 EOR $9876,Y ;59
X5A PHY ;5A
X5B BYTE $5B ;NOP
X5C BYTE $5C ;NOP $ABSL
X5D EOR $CBA9,X ;5C
X5E LSR $DCBA,X ;5E
X5F BBR 5,$F5,X55 ;5F
X60 RTS ;60
X61 ADC ($16,X) ;61
X62 BYTE $62 ;NOP #IMD
X63 BYTE $63 ;NOP
X64 STZ $46 ;64
X65 ADC $56 ;65
X66 ROR $66 ;66
X67 RMB 6,$76 ;67
X68 PLA ;68
X69 ADC #$96 ;69
X6A ROR ;6A
X6B BYTE $6B ;NOP
X6C JMP ($CDBA) ;6C
X6D ADC $DCBA ;6D
X6E ROR $EDCB ;6E
X6F BBR6 $F6,X66 ;6F
X70 BVS X77 ;70
X71 ADC ($17),Y ;71
X72 ADC ($27) ;72
X73 BYTE $73 ;NOP
X74 STZ $47,X ;74
X75 ADC $57,X ;75
X76 ROR $67,X ;76
X77 RMB7 $77 ;77
X78 SEI ;78
X79 ADC $9875,Y ;79
X7A PLY ;7A
X7B BYTE $7B ;NOP
X7C JMP ($C7,X) ;7C
X7D ADC $DCBA,X ;7E
X7E ROR $DCBA,X ;7E
X7F BBR 7,$F1,X77 ;7F
X80 BRA X88 ;80
X81 STA ($18,X) ;81
X82 BYTE $82 ;NOP #IMD
X83 BYTE $83 ;NOP
X84 STY $48 ;84
X85 STA $58 ;85
X86 STX $68 ;86
X87 SMB0 $78 ;87
X88 DEY ;88
X89 BIT #$98 ;89
X8A TXA ;8A
X8B BYTE $8B ;NOP
X8C STY $CBA9 ;8C
X8D STA $DCBA ;8D
X8E STX $EDCB ;8E
X8F BBS 0,$F8,X88 ;8F
X90 BCC X99 ;90
X91 STA ($19),Y ;91
X92 STA ($29) ;92
X93 BYTE $93 ;NOP
X94 STY $49,X ;94
X95 STA $59,X ;95
X96 STX $69,Y ;96
X97 SMB1 $79 ;97
X98 TYA ;98
X99 STA $9876,Y ;99
X9A TXS ;9A
X9B BYTE $9B ;NOP
X9C STZ $CBA9 ;9C
X9D STA $DCBA,X ;90
X9E STZ $EDCB,X ;9E
X9F BBS1 $F9,X99 ;8F
XA0 LDY #$0A ;A0
XA1 LDA ($1A,X) ;A1
XA2 LDX #$2A ;A2
XA3 BYTE $A3 ;NOP
XA4 LDY $4A ;A4
XA5 LDA $5A ;A5
XA6 LDX $6A ;A6
XA7 SMB1 $7A ;A7
XA8 TAY ;A8
XA9 LDA #$9A ;A9
XAA TAX ;AA
XAB BYTE $AB ;NOP
XAC LDY $CBA9 ;AC
XAD LDA $DCBA ;AD
XAE LDX $EDCB ;AE
XAF BBS 2,$FA,XAA ;AF
XB0 BCS XBB ;B0
XB1 LDA ($1B),Y ;B1
XB2 LDA ($2B) ;B2
XB3 BYTE $B3 ;NOP
XB4 LDY $B4,X ;B4
XB5 LDA $B5,X ;BS
XB6 LDX $B6,Y ;B6
XB7 SMB3 $7B ;B7
XB8 CLV ;B8
XB9 LDA $9876,Y ;B9
XBA TSX ;BA
XBB BYTE $BB ;NOP
XBC STX $CBA9,Y ;BC
XBD LDA $DCBA,X ;BD
XBE LDX $EDCB,Y ;BE
XBF BBS3 $FB,XBB ;BF
XC0 CPY #$0C ;C0
XC1 CMP ($1C,X) ;C1
XC2 BYTE $C2 ;NOP #imd
XC3 BYTE $C3 ;NOP
XC4 CPY $4C ;C4
XC5 CMP $5C ;C5
XC6 DEC $6C ;C6
XC7 SMB4 $7C ;C7
XC8 INY ;C8
XC9 CMP #$9C ;C9
XCA DEX ;CA
XCB WAI ;CB
XCC CPY $CBA9 ;CC
XCD CMP $DCBA ;CD
XCE DEC $EDCB ;CE
XCF BBS 4,$FC,XCC ;8F
XD0 BNE XDD ;D0
XD1 CMP ($1D),Y ;D1
XD2 CMP ($2D) ;D2
XD3 BYTE $D3 ;NOP
XD4 BYTE $D4 ;NOP $ZP,X
XD5 CMP $5D,X ;D5
XD6 DEC $6D,X ;D6
XD7 SMB5 $7D ;D7
XD8 CLD ;D8
XD9 CMP $9876,Y ;D9
XDA PHX ;DA
XDB STP ;DB
XDC BYTE $DC ;NOP $ABSL
XDD CMP $DCBA,X ;DD
XDE DEC $EDCB,X ;DE
XDF BBS5 $FD,XDD ;8F
XE0 CPX #$0E ;E0
XE1 SBC ($1E,X) ;E1
XE2 BYTE $E2 ;NOP #IMD
XE3 BYTE $E3 ;NOP
XE4 CPX $4E ;E4
XE5 SBC $5E ;E5
XE6 INC $6E ;E6
XE7 SMB6 $7E ;E7
XE8 INX ;E8
XE9 SBC #$9E ;E9
XEA NOP ;EA
XEB BYTE $EB ;NOP
XEC CPX $CBA9 ;EC
XED SBC $DCBA ;ED
XEE INC $EDCB ;EE
XEF BBS 6,$FE,XEE ;8F
XF0 BEQ XFF ;F0
XF1 SBC ($1F),Y ;F1
XF2 SBC ($2F) ;F2
XF3 BYTE $F3 ;NOP
XF4 BYTE $F4 ;NOP $ZP,X
XF5 SBC $5F,X ;F5
XF6 INC $6F,X ;F6
XF7 SMB7 $7F ;F7
XF8 SED ;F8
XF9 SBC $9876,Y ;F9
XFA PLX ;FA
XFB BYTE $FB ;NOP
XFC BYTE $FC ;NOP $ABSL
XFD SBC $DCBA,X ;FD
XFE INC $EDCB,X ;FE
XFF BBS7 $FF,XFF ;8F