mirror of
https://github.com/RevCurtisP/C02.git
synced 2025-02-19 19:31:04 +00:00
Merge branch 'master' into x16vera
This commit is contained in:
commit
4da225525b
5
.gitignore
vendored
5
.gitignore
vendored
@ -24,4 +24,7 @@ output
|
||||
|
||||
#Deprecated Files
|
||||
*/oldclude
|
||||
*/*.zip
|
||||
*/*.zip
|
||||
|
||||
#Private Directories
|
||||
notes
|
3
Makefile
3
Makefile
@ -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
|
||||
|
68
README.md
68
README.md
@ -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
724
a02.c
Normal 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
115
a02.h
Normal 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
10
c02.ppj
@ -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"$@"
|
||||
|
||||
#
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
37
include/c64/keydef.a02
Normal 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
37
include/c64/keydef.h02
Normal 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
|
@ -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
|
||||
|
||||
|
@ -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
37
include/cbm/keydef.a02
Normal 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
37
include/cbm/keydef.h02
Normal 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
|
@ -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
|
||||
|
@ -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
37
include/keydef.a02
Normal 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
37
include/keydef.h02
Normal 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
39
include/orao/screen.a02
Normal 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
38
include/orao/screen.h02
Normal 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();
|
@ -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)
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
20
include/via.h02
Normal 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)
|
||||
}
|
@ -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
37
include/vic/keydef.a02
Normal 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
37
include/vic/keydef.h02
Normal 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
|
@ -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
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
@ -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
|
@ -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
455
src/c02.c
@ -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
|
||||
}
|
||||
|
104
src/common.c
104
src/common.c
@ -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;
|
||||
}
|
||||
|
194
src/common.h
194
src/common.h
@ -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();}
|
||||
|
911
src/expr.c
911
src/expr.c
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
10
src/vars.c
10
src/vars.c
@ -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
27
test/README.md
Normal 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
14
test/a02.bat
Normal 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
|
@ -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
|
||||
|
@ -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
10
test/c02.bat
Normal 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
|
14
test/c64.bat
14
test/c64.bat
@ -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
|
||||
|
104
test/conds.c02
104
test/conds.c02
@ -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();}
|
||||
|
@ -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) {
|
||||
|
@ -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
12
test/hello.c02
Normal 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
87
test/ints.c02
Normal 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
55
test/keydefs.c02
Normal 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;
|
205
test/loops.c02
205
test/loops.c02
@ -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
35
test/orao.bat
Normal 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
71
test/scrntst.c02
Normal 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
80
test/sdeftest.c02
Normal 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
231
test/slibtest.c02
Normal 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
105
test/testilib.c02
Normal 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;
|
@ -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;
|
@ -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++;
|
||||
}
|
220
test/testsl.c02
220
test/testsl.c02
@ -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;
|
||||
|
@ -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
272
test/xmemtest.c02
Normal 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;
|
||||
|
17
work/a02.bat
17
work/a02.bat
@ -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
18
work/a02inc.a02
Normal 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
103
work/a02test.a02
Normal 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
|
||||
|
@ -1,3 +1,3 @@
|
||||
@ECHO Compiling File %1.c02
|
||||
..\c02.exe %1 >%1.dbg
|
||||
..\c02.exe -c 65C02 %1 >%1.dbg
|
||||
|
||||
|
@ -1,8 +0,0 @@
|
||||
OP VALUE
|
||||
= 1
|
||||
< 2
|
||||
<= 3
|
||||
> 4
|
||||
>= 5
|
||||
<> 6
|
||||
|
258
work/opcodes.a02
Normal file
258
work/opcodes.a02
Normal 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
|
Loading…
x
Reference in New Issue
Block a user