Compare commits

...

7 Commits

Author SHA1 Message Date
Curtis F Kaylor f1b362e126 Added and debugged opcode address modes 2022-08-07 15:31:02 -04:00
Curtis F Kaylor a20695c93c Implemented and debugged more Peeudo-Ops 2022-08-07 00:17:06 -04:00
Curtis F Kaylor 847ea78c3f a02.c02 - Debugged fndsym() and evlsym() 2022-07-09 18:26:36 -04:00
Curtis F Kaylor b2820d2549 Added isalud() to ctype module 2022-07-09 18:25:34 -04:00
Curtis F Kaylor 122e4fcc00 a02.c02: modified and tested addsym() and prtsym() 2022-07-09 15:51:10 -04:00
Curtis F Kaylor 5748b176dc Added tests for parsing routines 2022-07-09 11:37:52 -04:00
Curtis F Kaylor a220bd0592 Modified intlib to use system vars intacc, intarg, and intovr 2022-04-04 19:47:16 -04:00
13 changed files with 1725 additions and 434 deletions

224
a02.c
View File

@ -1,7 +1,6 @@
/* Simple 6502 Assembler *
* for C02 Compiler *
* Uses DASM Syntax but *
* supports 65C02 Op Codes */
/* 6502 Assembler for C02 Compiler *
* Uses DASM Syntax but supports *
* 65C02 and Sweet 16 Opcodes */
#include <stdio.h>
#include <stdlib.h>
@ -15,13 +14,23 @@ int debug; //Ouput Debug Info
#define INCLEN 255
char incpath[INCLEN];
enum otypes {BINFIL, PRGFIL}; //Object File Types
enum otypes {BINFIL, APLFIL, ATRFIL, INTFIL, MSRFIL, PRGFIL}; //Object File Types
int obin[] = {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE}; //Is File Type Binary
int olen[] = {0, 8, 32, 0, 0}; //Hex Bytes per Line
char objtyp; //Object File Type
int objbin; //Binary Object File Flag
int objlen; //Text Object File Line Length
int objcnt; //Text Object File Byte Count
int chksum; //Text Object File Checksum
int orgadr; //Origin Address
int curadr; //Current Address
int endadr; //Address after Last Byte
int exeadr; //Execution Start Address
int lstadr; //List Address
char hdrtxt[MAXSTR]; //SREC Header Record Text
struct sym {int block; char name[MAXLBL+1]; int bytes, value, refrd;};
struct sym symbol; //Current Symbol
struct sym symtbl[MAXSYM]; //Global Symbol Table
@ -36,6 +45,7 @@ char cmmnt[MAXSTR]; //Assembly Line Comment
char mcode[MAXSTR]; //Generated Bytes
char strng[MAXSTR]; //Parsed String
int opridx; //Index into Operand
char cpdchr; //Last Character Copied into oprnd
@ -67,8 +77,13 @@ 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");
printf(" Opts: -d - Output debug info\n");
printf(" -h - SREC header record text\n");
printf(" -a - Apple-1 monitor format\n");
printf(" -p - Commodore PRG format\n");
printf(" -s - Motorola SREC format\n");
printf(" -x - Intel HEX format");
printf(" \n");
exit(EXIT_FAILURE);
}
@ -105,15 +120,18 @@ void xerror(char* format, char *s) {
/* Open File with Error Checking */
FILE * opnfil(char* name, char* mode, char* path) {
if (debug) printf("Opening file '%s' with mode '%s'\n", name, mode);
if (debug && strlen(path)) printf("using path list '%s'\n", path);
FILE *fp = fopen(name, mode);
if (!fp) {
char spec[256];
char *token = strtok(path, " ");
while (token) {
strcpy(spec, path); strcat(spec, "\\"); strcat(spec, name);
char spec[256], paths[256];
strcpy(paths, path);
char *token = strtok(paths, " ");
while (token != NULL) {
strcpy(spec, token); strcat(spec, "\\"); strcat(spec, name);
if (debug) printf("Opening file \"%s\" with mode \"%s\"\n", spec, mode);
fp = fopen(spec, mode); if (fp) break;
token = strtok(NULL, " ");
if (debug) printf("token = \"%s\"\n", token);
}
}
if (!fp) xerror("Error Opening File '%s'\n", name);
@ -121,6 +139,17 @@ FILE * opnfil(char* name, char* mode, char* path) {
return fp;
}
/* Open Object FIle */
FILE * opnobj(char* objnam, char* path) {
char mode[3] = "w";
objbin = obin[objtyp];
if (debug) printf("Set objbin to %d\n", objbin);
objlen = olen[objtyp];
if (debug) printf("Set objlen to %d\n", objlen);
if (objbin) strcat(mode, "b");
return opnfil(objnam, mode, path);
}
/* Skip Character in Input Line *
* Args: c - Character to Skip *
* Updates: linptr */
@ -205,11 +234,16 @@ int plabel(void) {
return found;
}
/* Append to Operand */
void aoprnd(int c) {
if (opridx < MAXSTR) oprnd[opridx++] = toupper(c);
}
/* Copy Character to Operand and Increment */
int cpychr(int c) {
if (c && toupper(*linptr) != c) return FALSE;
cpdchr = *linptr;
if (opridx < MAXSTR) oprnd[opridx++] = toupper(cpdchr);
aoprnd(cpdchr);
linptr++;
return TRUE;
}
@ -324,11 +358,66 @@ int evlopd(int maxsiz) {
return result;
}
/* Write Hex and Update Checksum */
void outhex(char prefix, int b) {
if (prefix) fputc(prefix, outfil);
fprintf(outfil, "%02X", b);
chksum += b;
} \
/* Write Hex Address */
void outadr(int w) {
outhex(0, w >> 8);
outhex(0, w & 0xFF);
}
/* Write Hex File Line Header */
void outhdr(int addr) {
chksum = 0;
int linlen = __min(objlen, endadr - curadr + 1);
if (debug) printf("outhdr: curadr=%04x, endadr=%04x, linlen=%04x\n", curadr, endadr, linlen);
switch (objtyp) {
case INTFIL: outhex(':', linlen); outadr(addr); outhex(0, 0); break;
default: outadr(addr); //Write Address
}
if (objtyp == APLFIL) fputc(':', outfil);
}
/* Write Checksum */
void outchk(void) {
if (objtyp == INTFIL) outhex(0, -chksum & 0xFF);
}
/* Write Hex File Line End */
void outend(void) {
if (objtyp = INTFIL) outchk(); //Write Checksum
fputs("\n", outfil);
objcnt = 0;
}
/* Write Hex File End of File */
void outeot(void) {
if (objcnt) outend();
if (objtyp = INTFIL); fputs(":00000001FF\n", outfil);
}
/* Write Byte to Hex Object File */
void outtxt(int b) {
if (objcnt == 0) outhdr(curadr - 1);
switch (objtyp) {
case APLFIL: outhex(' ', b); break;
default: outhex(0, b);
}
objcnt++;
if (objcnt == objlen) outend();
}
/* Write Byte to Output File */
void outbyt(int b) {
if (curadr > -1) curadr++;
if (passno != 2) return;
fputc(b & 0xFF, outfil);
if (objbin) fputc(b & 0xFF, outfil);
else outtxt(b);
sprintf(bytstr, "%02X ", b);
if (strlen(mcode) < 9) strcat(mcode, bytstr);
}
@ -339,6 +428,20 @@ void outwrd(int w) {
outbyt(w >> 8);
}
/* Write Atari 8-Bit EXE Block Header */
void atrhdr(int saddr, int eaddr) {
outwrd(0xFFFF); //Binary File Indicator
outwrd(saddr); //Start Address
outwrd(eaddr-1); //End Address
}
/* Write Atari 8-Bit EXE Ending Block */
void atrend(void) {
atrhdr(0x02E0, 0x02E2);
outbyt(0x4C); //JMP
outwrd(exeadr); //start address
}
/* Lookup Opcode */
int lkpopc(struct opc opl[]) {
if (debug) printf("Looking up Mnemonic %s\n", mnmnc);
@ -403,15 +506,23 @@ void asmequ(void) {
setsym(evlopd(0xFFFF), 0);
}
/* Assemble EXE Pseudo-Op */
void asmexe(void) {
exeadr = evlopd(0xFFFF);
}
/* Assemble ORG Pseudo-Op */
void asmorg(void) {
orgadr = evlopd(0xFFFF);
if (exeadr < 0) exeadr = orgadr;
if (passno == 1 && symbol.name[0]) {
symbol.value = orgadr;
symbol.bytes = 2;
}
if (passno == 2 && objtyp == PRGFIL)
outwrd(orgadr);
if (passno == 2 ) {
if (objtyp == PRGFIL) outwrd(orgadr);
if (objtyp == ATRFIL) atrhdr(orgadr, lstadr);
}
curadr = orgadr;
lstadr = orgadr;
}
@ -473,6 +584,7 @@ int asmpso(int dot) {
case 'M': asmens(); break; //ENDSubroutine
case 'I': asminf(); break; //INCLude
case '*': asmorg(); break; //ORG
case 'X': asmexe(); break; //EXEC
case 'P': asmprc(); break; //PROCessor
case 'E': asmend(); break; //END
case 'A': asmaln(); break; //ALIGn
@ -607,17 +719,76 @@ void dbgopc(void) {
}
}
/* Evaluate Register Operand *
* Returns: Register Number 0-15 */
int evlreg(void) {
char name[MAXSTR];
int result;
if (debug) puts("Evaluating Register Argument");
int rel = cpychr('@');
if (debug) printf("Set rel to %d\n", rel);
if (amode == INDCT && !rel) xerror("Indirect Argument Required\n", "");
if (amode == RGIND && rel) token = token + 0x20; //LD or ST relative
char pfx = 'R'; if (!cpychr(pfx)) pfx = 0;
if (debug) puts("Evaulating Register Number");
if (pfx && isalpha(*linptr)) return evlhex(0x0F);
if (isdigit(*linptr)) return evldec(0x0F);
if (!pword(FALSE, name)) xerror("Register Argument Required\n", "");
for (int i=0; name[i]; i++) if (opridx<MAXSTR) oprnd[opridx++] = name[i];
if (pfx) pfxstr(pfx, name);
if (debug) printf("Parsed Register Name %s \n", name);
if (strcmp(name, "ACC")==0) return 0; //Accumulator (R0)
if (strcmp(name, "PR")==0) return 14; //Prior Result (R14)
if (strcmp(name, "PC")==0) return 15; //Accumulator (R0)
xerror("Illegal Register %s\n", name);
}
/* Assemnble Register Instruction */
void asmreg(void){
if (debug) printf("Assembling Register Opcode %02x\n", token);
int regno = evlreg();
if (debug) printf("Register Number: %d\n", regno);
token = token | regno;
if (amode == ABSLT) {
if (debug) puts("Evaluating Absolure Argument");
skpspc();
if (!cpychr(',')) aoprnd(' '); //Skip optional comma
opval = evlopd(0xFFFF);
if (opval < 0) xerror("Absolute Argument Required\n", "");
}
}
/* Assemble Sweet 16 Opcode */
int asmswo(void) {
opval = -1;
if (lkpopc(swolst) == FALSE) return FALSE;
if (debug) printf("Assembling Sweet 16 Instruction %s, ", mnmnc);
if (debug) printf("Addressing Mode 0x%04X\n", amode);
skpspc();
switch (amode) {
case IMPLD: break; //Implied Instruction
case RELTV: asmbrn(TRUE); break; //Branch (Relative) Instruction
default: asmreg(); //Assemble Register Instruction
}
if (debug) printf("Writing OpCode $%02X\n", token);
outbyt(token);
if (debug) printf("Writing %s Operand %d\n", zpgabs[-zpage], opval);
if (opval >= 0) {if (amode == RELTV) outbyt(opval); else outwrd(opval);}
return TRUE;
}
/* Assemble Opcode */
int asmopc(int dot) {
opmod = 0;
if (asmpso(dot)) return TRUE; //Check For/Assemble Pseudo-Op
if (asmswo()) return TRUE; //Check for/Assemble Sweet-16 Instruction
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 (amode == 0x0004 || amode == 0x1004) asmzpr(); //Branch ZP (Relative)
else if (cpychr('#')) asmimd(); //Assemble Immediate Instruction
else if (cpychr('(')) asmind(); //Assemble Indirect Instruction
else asmiaz(); //Assemble Implied/Accumulator/Absolute/ZeroPage Instruction
if (debug) dbgopc();
@ -685,6 +856,13 @@ void clsinc(void) {
endasm = FALSE; //Clear End Flag for Return to Main File
}
/* Close Object File */
void clsobj() {
if (objbin) {if (objtyp == ATRFIL) atrend();}
else {if (objcnt) outeot();}
fclose(outfil);
}
/* Assemble Input File (Two Pass) *
* Args: pass - Assembly Pass (1 or 2) *
* Requires: inpfil - Input File Pointer *
@ -699,6 +877,8 @@ void asmfil(int pass) {
blknum = 0; // and Local Block Number
orgadr = -1; //Origin Address Not Set
curadr = orgadr; //Set Current Address to Origin
exeadr = -1; //Execution Address Not Set
objcnt = 0; //Initialize Object File Byte Count
if (debug) printf("Rewinding Input File\n");
rewind(inpfil); //Start at Beginning of Input File
while (TRUE) {
@ -720,6 +900,8 @@ void asmfil(int pass) {
lineno++;
if (incnam[0] && incfil == NULL) opninc(); //Open Include File
}
endadr = curadr; //Set End Address for Second Pass
if (debug) printf("End address set to %04x\n", endadr);
}
/* Parse Command Line Option */
@ -729,9 +911,14 @@ int pcoptn(char *argval) {
if (debug) printf(" Option '%c'\n", option);
switch(option) {
case 'D': debug = TRUE; break; //Enable debug Output
case 'A': objtyp = APLFIL; break; //Apple-1 Monitor Entry File
case 'E': objtyp = ATRFIL; break; //Atari 8-Bit EXE File
case 'P': objtyp = PRGFIL; break; //Commodore PRG File
case 'S': objtyp = MSRFIL; break; //Motorola SREC File
case 'X': objtyp = INTFIL; break; //Intel HEX File
default: xerror("Illegal Command Line Option %s\n", argval);
}
if (debug && objtyp) printf("Object type set to %d\n", objtyp);
return TRUE;
}
@ -766,12 +953,13 @@ int main(int argc, char *argv[]) {
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
outfil = opnobj(outnam, ""); //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
clsobj(); //Close Object File
exit(0); //Exit with No Errors
}

33
a02.h
View File

@ -4,15 +4,18 @@
#define MAXLBL 8 //Maximum Symbol Length
#define MAXSYM 1024 //Maximum Number of Labels
//#define NULL &0
#define FALSE 0
#define TRUE -1
/* Address Mode Bit Masks */
#define RGSTR 0x0000 //Register (Sweet 16)
#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 RGIND 0x0010 //Register or Imderect (Sweet 16)
#define ABSLT 0x0020 //Absolute
#define ABSLX 0x0040 //*Absolute,X [fixops()]
#define ABSLY 0x0080 //Absolute,Y
@ -24,13 +27,15 @@
char zpgabs[][9] = {"Absolute", "ZeroPage"};
/* Address Mode Descriptions */
struct amd {int amode; char desc[12];};
struct amd amdesc[] = {
{ACMLT, "Accumulator"},
{ACMLT, "Accumulator"},
{IMMDT, "Immediate"},
{ZPAGE, "Zero Page"},
{ZPAGX, "Zero Page,X"},
{ABSLT, "Absolute"},
{RGSTR, "Register"},
{ABSLX, "Absolute,X"},
{ABSLY, "Absolute,Y"},
{IMPLD, "Implied"},
@ -45,7 +50,8 @@ 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}, {"ENDS", 'M', 0}, {"", 0, 0}
{"ORG", '*', 0}, {"PROC", 'P', 0}, {"END", 'E', 0}, {"ENDS", 'M', 0}, {"EXEC", 'X', 0},
{"DW", 'W', 0}, {"", 0, 0}
};
struct opc opclst[] = {
@ -73,7 +79,7 @@ struct opc opclst[] = {
{"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},
{"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},
@ -113,3 +119,22 @@ struct opf opfix[] = {
{0,0,0}
};
/* Sweet 16 Address Modes
IMPLD - Implied (No Argument)
RGSTR - Register
INDCT - Register Indirect
ABSLT - Register Absolute
RKLTV - Relative (Branch)
RGIND - Register or Indirect
*/
/* Sweet 16 OpCodes */
struct opc swolst[] = {
{"RTN", 0x00, IMPLD}, {"BR", 0x01, RELTV}, {"BNC", 0x02, RELTV}, {"BC", 0x03, RELTV},
{"BP", 0x04, RELTV}, {"BM", 0x05, RELTV}, {"BZ", 0x06, RELTV}, {"BNZ", 0x07, RELTV},
{"BM1", 0x08, RELTV}, {"BNM1", 0x09, RELTV}, {"BK", 0x0A, IMPLD}, {"RS", 0x0B, IMPLD},
{"BS", 0x0C, RELTV}, {"SET", 0x10, ABSLT}, {"LD", 0x20, RGIND}, {"ST", 0x30, RGIND},
{"LD", 0x40, INDCT}, {"ST", 0x50, INDCT}, {"LDD", 0x60, INDCT}, {"STD", 0x70, INDCT},
{"POP", 0x80, INDCT}, {"STP", 0x90, INDCT}, {"ADD", 0xA0, RGSTR}, {"SUB", 0xB0, RGSTR},
{"POPD", 0xC0, INDCT}, {"CPR", 0xD0, RGSTR}, {"INR", 0xE0, RGSTR}, {"DCR", 0xF0, RGSTR}
};

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,13 @@ passed a high ASCII character (127 - 255).
The following functions are defined:
b = isalph(c); Returns TRUE if c is alphabetic, otherwise FALSE.
An alphabetic character is a letter (A-Z or a-z).
Note: Call internal routine isalp, which in turn
calls internal routines isupr and islwr.
b = isalnm(c); Returns TRUE if c is alphanumeric, otherwise FALSE.
An alphanumeric character is a letter (A-Z or a-z),
@ -28,13 +35,14 @@ The following functions are defined:
Note: Calls internal routine isalu, which in turn
calls internal routines isdgt and isalp.
b = isalph(c); Returns TRUE if c is alphabetic, otherwise FALSE.
b = isalud(c); Returns TRUE if c is an alphanumundOT, otherwise FALSE.
An alphabetic character is a letter (A-Z or a-z).
An alphanumundot character is a letter (A-Z or a-z),
a digit (0-9), an underline (_), or a dot (.).
Note: Call internal routine isalp, which in turn
calls internal routines isupr and islwr.
Note: Calls internal routine isalu, which in turn
calls internal routines isdgt and isalp.
b = isbdgt(c); Returns TRUE if c is a binary digit, otherwise FALSE.
A binary digit is a character in the range 0 through 1.

View File

@ -19,6 +19,7 @@ blkstr block Block String Search block for segment beginning with
blkswp block Block Swap Swap bytes of array with the current segment.
blksrt block Block Sort Sort segments in block by initial string.
button paddle Button Read paddle button controller status.
char stdlib Char from integer Convert Integer to Character
chdir direct Change Directory Change to specified directory
chdrv direct Change Drive Change to specified drive
ctoa stdlib Character to ASCII Convert byte to numeric string.
@ -44,18 +45,30 @@ fsinit fileio File System Init Initialize file system.
fsname fileio File Set Name Set filename for fopen, fsave, or fload.
fwrite fileio File Write Write bytes to file.
getc stdio Get Character Read character from keyboard.
getcpr stdiox Get Char Prompt Display prompt and wait for keypress.
getcwd direct Get CWD Return current working directory
getdrv direct Get Drive Return current drive identifier
getdst stddef Get Destination Get address in Destination Pointer.
getprc stdiox Get Prompt Character Display prompt and wait for key press.
gets stdio Get String Read string from keyboard.
getsrc stddef Get Source Get address in Source Pointer.
iabs intlib Integer Absolute Return absolute value of integer.
iacc intlib Integer Accumulator Set integer accumulator.
iadd intlib Integer Add Add two integer values.
iaddc intlib Integer Add Character Add character and integer value.
icmp intlib Integer Compare Compare two integer values.
idiv intlib Integer Divide Divide integer values by integer value.
imax intlib Integer Maximum Return greater of two integers.
imin intlib Integer Minimum Return lesser of two integers.
imod intlib Integer Modulo Return modulus of two integer values.
imult intlib Integer Multiply Multiply two integer values.
imultc intlib Integer Multiply Char Multiply character and integer value.
ineg intlib Integer Negate Return Negative of integer value.
int stdlib Int from character Convert Character to Integer
intay stdlib Int from A,Y Convert Character Pair to Integer
isalnm ctype Is Alphanumeric Return TRUE if character is A-Z, a-z, or 0-9.
isalnu ctype Is Alphanumunder Return TRUE if character is A-Z, a-z, 0-9, or _.
isalph ctype Is Alphabetic Return TRUE if character is A-Z or a-z.
isalud ctype Is Alphanumundot Return TRUE if character is A-Z, a-z, 0-9, ., or _.
isbdgt ctype Is Binary Digit Return TRUE if character is 0 or 1.
isctrl ctype is Control Return TRUE if ASCII code is 0-31 or 127.
isdigt ctype Is Digit Return TRUE if character is 0-9.
@ -67,6 +80,7 @@ islowr ctype Is Lowercase Return TRUE if character is a-z.
ispnct ctype Is Punctuation Return TRUE if Graphical and not Alphanumeric.
isprnt ctype Is Printable Return TRUE if ASCII code is 32-126.
isspce ctype Is white Space Return TRUE if ASCII code is 9-13 or 32.
isub intlib Integer Subtract Subtract two integer values.
isuppr ctype Is Uppercase Return TRUE if character is A-Z.
itoa intlib Integer to ASCII Convert Integer to String.
joystk joystk Joystick Read Atari style joystick controller status.
@ -77,7 +91,7 @@ mclose memio Memory Close Close memory file.
memdst memory Memory Destination Set destination array for subsequent functions.
memset memory Memory Set File bytes in array with byte.
memchr memory Memory Character Search for byte in array.
memclr memory Memory Cllear File bytes in array with $00.
memclr memory Memory Clear File bytes in array with $00.
memcmp memory Memory Compare Compare bytes in array against destination array.
memcpy memory Memory Copy Copy bytes from array to destination array.
memswp memory Memory Swap Swap bytes in array with destination array.
@ -110,17 +124,27 @@ ptrsav pointer Pointer Save Save pointer into two-byte array.
ptrrst pointer Pointer Restore Restore pointer from two-byte array.
printf stdiox Print Formatted Write formatted byte and/or string/address to screen.
putadr test Put Address Write "address=" and hexadecimal address to screen.
putbin stdiox Put Binary Write byte to screen as binary number.
putc stdio Put Character Write character to screen.
putdec stdiox Put Decimal Write byte to screen as decimal number.
putdeh stdiox Put Decimal Hundred Write byte mod 100, zero-filled to screen.
putdel stdiox Put Decimal Left Write byte to screen as left-justified decimal.
putder stdiox Put Decimal Right Write byte to screen as right-justified decimal.
putdst stdios Put Destination Write destination string to screen.
putdez stdiox Put Decimal Zero``` Write byte zero-filled to screen.
putdst stdiox Put Destination Write destination string to screen.
putexh stdiox Put Extended Hex Write 24 bit number to screen as hexadecimal number.
puthex stdiox Put Hexadecimal Write byte to screen as hexadecimal number.
putinr stdiox Put Integer Right Write integer to screen as right justified decimal number.
putint stdiox Put Integer Write integer to screen as decimal number.
putln stdio Put Line Write string plus newline to screen.
putnyb stdiox Put Nybble Write low nybble to screen as hexadecimal digit.
puts stdio Put String Write string to screen.
putmsk stdiox Put Mask Write bit masked byte to screen as binary number.
putrpc stdiox Put Repeated Char Write character multiple times to screen.
putrps stdiox Put Repeated Spaces Write multiple spaces to screen.
putspc stdiox Put Space Write space character to screen.
putsub stdio Put Substring Write substring to screen.
putwrd stdiox Put Word Write address to screen as hexadecimal number.
putwrd stdiox Put Word Write integer to screen as hexadecimal number.
rand stdlib Random Generate pseudorandom number.
rands stdlib Random Seed Seed random number generator.
rddir dirent Read Directory Read Directory Entry
@ -158,15 +182,23 @@ strapd string String Append Append character to string.
strcat string String Concatenate Concatenate string to destination string.
strchr string String Character Search for character in string.
strcmp string String Compare Compare string contents against destination string.
strcms string String Compare Source Compare source string against destination string.
strcps string String Copy Source Copy source string to destination string.
strcpy string String Copy Copy string contents to destination string.
strcsp stringx String Char Span Return length of span in destination not in string.
strcut string String Cut Copy substring to destination string.
strget stringl String Get Read entry from string list.
strlen string String Length Calculate length of string.
strlln stringl String List Length Calculate number of entries in string list
strlwr stringm String Lower Convert string to lowercase.
strpbk stringx String Pointer Break Find first character in destination found in string.
strpad stringm String Pad Pad or truncate string.
strppd string String Prepend Prepend character to string.
strput stringl String Put Write entry to string list.
strrch string String Reverse Char Search for character from end of string.
strspn stringx String Span Return length of span in destination found in string.
strstr string String String Search for string in destination string.
strupr stringm String Upper Convert string to uppercase.
swap bitlib Swap nybbles Swaps left and right nybbles in byte.
tolowr ctype To Lowercase Convert character to lowercase.
touppr ctype To Uppercase Convert character to uppercase.

View File

@ -6,15 +6,17 @@
; toxxxx set Carry if character is converted, otherwise clear Carry
;Machine Language Subroutines modify Flags but not Accumulator
; Carry will be Set if True and Cleared if False
;Index Registers X an Y are not modified by any routines
;Index Registers X and Y are not modified by any routines
SUBROUTINE CTYPE
;Character Test Functions - Set Accumulator
ISALNU: JSR ISANU ;Is Alphanumunder
ISALUD: JSR ISAUD ;Is Alphanumunder or Dot
BVC .ISBTF
ISALNM: JSR ISALN ;Is Alphanumeric Character
BVC .ISBTF
ISALNU: JSR ISANU ;Is Alphanumunder
BVC .ISBTF
ISALPH: JSR ISALP ;Is Alphabetic Character
BVC .ISBTF
ISBDGT: JSR ISBIN ;Is Binary Digit
@ -57,6 +59,9 @@ TOUPPR: JSR ISLWR ;If Char IS Not Lower Case
RTS ; and Return
;Machine Language Subroutines - Set/Clear Carry, Preserve Accumulator
ISAUD: CMP #$2E ;If Char = '.'
BEQ .ISSEC ; Return Carry Set
;Else
ISANU: CMP #$5F ;If Char = '_'
BEQ .ISSEC ; Return Carry Set
;Else

View File

@ -20,6 +20,12 @@ char isalnu();
* Returns: TRUE or FALSE */
char isalph();
/* Check for Alphanumundot Character *
* (Alpha, Digit, '.', or '_') *
* Args: c - Character to Check *
* Returns: TRUE or FALSE */
char isalud();
/* Checks for Control Character *
* (Less than Space or Delete) *
* Args: c - Character to Check *

View File

@ -1,11 +1,32 @@
; C02 module intlib.h02 assembly language subroutines
; Requires
; external zero page words DSTPTR and SRCPTR
; and external locations TEMP0, TEMP1, TEMP2, and TEMP3
; Requires external zero page words DSTPTR, SRCPTR,
; external bytes TEMP0, TEMP1, TEMP2, and TEMP3, and
; external words INTACC, INTARG, and INTOVR.
SUBROUTINE INTLIB
;iabs(n) - Get Integer ABSolute Value
;iacc(i) - Set Integer Accumulator to i
;Args: Y,X = Argument
;Sets: INTACC = Y,X
IACC: STX INTACC
STY INTACC+1
RTS
;Set Integer Argument
.SETARG STX INTARG
STY INTARG+1
RTS
;Clear Integer Overflow
;Sets: INTOVR = 0
;Returns A = 0
.CLROVR LDA #0
STA INTOVR
STA INTOVR+1
RTS
;iabs(i) - Get Integer ABSolute Value
;Args: Y,X = Integer to get Absolute Value Of
;Sets: TEMP1, TEMP2
;Affects: C, N, Z
@ -23,188 +44,248 @@ IABS: CPY #$80 ;If Negative (High Bit Set)
;imax(i) - Get MAXimum of Two Integers
;Args: Y,X = Second Integer
;Uses: SRCPTR = First Integer
;Uses: INTACC = First Integer
;Affects: N,Z,C
;Returns: Y,X = Larger of the Two Arguments
IMAX: CPY SRCPTR+1 ;If Y < SRCPTR MSB
BCC .GETSRC ; Return SRCPTR
CPX SRCPTR ;IF X >= SRCPTR LSB
BCS .RETURN ; Return Argument
.GETSRC JMP GETSRC ;Return Integer in SRCPTR
IMAX: CPY INTACC+1 ;If Y < INTACC MSB
BCC .GETACC ; Return INTACC
CPX INTACC ;IF X >= INTACC LSB
BCS .IMSET ; Set INTACC to and Return Argument
.GETACC LDX INTACC ;Return Integer Accumulator
LDY INTACC+1
RTS
;imin(i) - Get MINimum of Two Integers
;Args: Y,X = Second Integer
;Uses: SRCPTR = First Integer
;Uses: INTACC = First Integer
;Sets: IINTACC = Result
;Affects: N,Z,C
;Returns: Y,X = Larger of the Two Arguments
IMIN: CPY SRCPTR+1 ;If Y < SRCPTR+1
IMIN: CPY INTACC+1 ;If Y < INTACC+1
BCC .RETURN ; Return Argument
BNE .GETSRC ;If Y > SRCPTR+1 Return SRCPTR
CPX SRCPTR ;If X >= SRCPTR
BCS .GETSRC ; Return SRCPTR
RTS ;Return Argument
BNE .GETACC ;If Y > INTACC+1
CPX INTACC ;or X >= INTACC
BCS .GETACC ; Return INTACC
.IMSET JMP IACC ;Else Set INTACC to and Return Argument
;iaddc(c,i) - Add Byte c to Integer i
IADDC: JSR SETSRC ;Save Integer and Clear Y
;iaddc(c,i) - Integer ADD Char c to int i
IADDC: JSR IACC ;Store Integer in Accumulator
LDY #0 ;Set Argument MSB to 0
TAX ;Copy Byte to LSB and drop into IADD
;iadd(d) - ADD Integer d to from Integer g
;iand(d) - Integer ADD g + d
;Args: Y,X = Addend
;Requires: setsrc(g) - Augend
;Sets: TEMP1,TEMP2 = Addend
;Affects: Z,C
;Returns: A = Carry
;Requires: IACC(g) - Augend
;Sets: INTACC = Result
;Affects: Z
;Returns: Y,X = Sum
;IAND: TXA ;AND Argument LSB
; AND IACC ;with Accumulator LSB
; TAX
; TYA ;AND Argument MSB
; AND IACC+1 ;with Accumulator MSB
; TAY
; JMP IACC ;Set INTACC to And Return Result
;iadd(d) - Integer ADD g + d
;Args: Y,X = Addend
;Requires: IACC(g) - Augend
;Sets: INTACC = Sum
;Affects: Z
;Returns: A,C = Carry
; Y,X = Sum
; N = Sign of Result
IADD: CLC ;Clear Carry for Addition
TXA ;Add Addend LSB
ADC SRCPTR ;to Augend LSB
TAX ;and Copy to X
TYA ;Add Addend MSB
ADC SRCPTR+1 ;to Augebd MSB
TAY ;and Copy to Y
LDA #0 ;Set Overflow to 0
ROL ; Rotate Carry (Same as Adding it)
RTS ; and Return
IADD: CLC ;Clear Carry for Addition
TXA ;Add Addend LSB
ADC INTACC ;to Augend LSB
TAX ;and Copy to X
TYA ;Add Addend MSB
ADC INTACC+1 ;to Augebd MSB
TAY ;and Copy to Y
PHP ;Save Result Flags
LDA #0 ;Clear CHR Result to 0
STA INTOVR+1 ; and Clear Overflow MSB
ROL ;Rotate Carry Flag into CHR Result
STA INTOVR ; and store in INTOVR
PLP ;Restore Result Flags
JMP IACC ;Set INTACC to And Return Result
;isub(s) - SUBtract Integer s from Integer m
;ineg(i) - Integer NEGate int i
;Args: Y,X = Integer to Negate
;Sets: INTACC = Result
; INTARG = Argument
;Returns: Y,X = Negated Integer
; N = Sign of Result
INEG: LDA #0 ;Set Minuend to Zero
STA INTACC
STA INTACC+1
;isub(s) - Integer SUBtract m - s
;Args: Y,X = Subtrahend
;Requires: setsrc(m) - Minuend
;Sets: TEMP1,TEMP2 = Subtrahend
;Affects: Z,C
;Returns: A = Carry
;Requires: IACC(m) - Minuend
;Sets: INTACC = Difference
; INTARG = Subtrahend
;Affects: Z
;Returns: A,C = Carry
; Y,X = Difference
; N = Sign of Result
ISUB: JSR SAVRXY ;Store Subtrahend in TEMP1,TEMP2
SEC ;Set Carry for Subtraction
LDA SRCPTR ;Load Minuend LSB
SBC TEMP1 ;Subtract Subtrahend LSB
TAX ;Copy Difference LSB to X
LDA SRCPTR+1 ;Load Minuend MSB
SBC TEMP2 ;Subtract Subtrahend MSB
TAY ;Copy Difference MSB to Y
LDA #0 ;Set Overflow Byte to 0
SBC #0 ; Subtract Carry
RTS ; and Return
ISUB: JSR .SETARG ;Store Subtrahend in INTARG
SEC ;Set Carry for Subtraction
LDA INTACC ;Load Minuend LSB
SBC INTARG ;Subtract Subtrahend LSB
TAX ;Copy Difference LSB to X
LDA INTACC+1 ;Load Minuend MSB
SBC INTARG+1 ;Subtract Subtrahend MSB
TAY ;Copy Difference MSB to Y
PHP ;Save Result Flags
LDA #0 ;Set Overflow Byte to 0
SBC #0 ;and Subtract Carry
PLP ;Restore Result Flags
JMP IACC ;Set INTACC to And Return Result
;imultc(c,m) - Multiply Int m by Char c
;Args: A - Multiplicand
; Y,X - Multiplier
;Sets: INTACC - Product MSB, LSB
IMULTC: STA INTACC ;Set Integer Accumulator to int(A)
LDA #0
STA INTACC+1 ;and execute IMULT
;imult(m) - MULTiply Two Integers
;Args: Y,X - Multiplier
;Requires: DSTPTR = Multiplicand
;Sets: TEMP0-TEMP3 = 32 Bit Product
;Destroys: SRCPTR
;Affects: A,C,Z,N
;imult(m) = MULTiply Integer n * Integer m
;Args: Y,X = Multiplier
;Uses: INTACC = Multiplicand
;Sets: INTACC = Product MSB, LSB
;Sets: INTOVR = Product MSB, LSB
;Destroys: TEMP0,TEMP1,TEMP2,TEMP3
;Affects: C,Z,N
;Returns: A,Y,X = 24 Bit Product
IMULT: JSR SETSRC ;Save Multiplier
STY TEMP0+2 ;Clear Upper Bits of Product
STY TEMP0+3
IMULT: JSR .SETARG ;Save Multiplier
LDY #0
STY INTOVR ;Clear Upper Bits of Product
STY INTOVR+1
LDX #16 ;Rotate Through 16 Bits
.MSHFTR LSR SRCPTR+1 ;Divide Multiplier by 2
ROR SRCPTR
.MSHFTR LSR INTARG+1 ;Divide Multiplier by 2
ROR INTARG
BCC .MROTR ;If Shifted out Bit is 1
LDA TEMP0+2 ; Add Multiplicand
LDA INTACC ; Add Multiplicand
CLC ; to Upper Half of Product
ADC DSTPTR
STA TEMP0+2
LDA TEMP0+3
ADC DSTPTR+1
STA TEMP0+3
.MROTR ROR TEMP0+3
ROR TEMP0+2
ROR TEMP0+1
ADC INTOVR
STA INTOVR
LDA INTOVR+1
ADC INTACC+1
STA INTOVR+1
.MROTR ROR INTOVR+1
ROR INTOVR
ROR TEMP1
ROR TEMP0
DEX ;Decrement Counter
BNE .MSHFTR ;and Process Next Bit
LDX TEMP0
LDY TEMP1 ;Return Low 24 Bits of
LDA TEMP2 ;Product in A, Y, and X
RTS
LDA INTOVR ;Get Bits 16-24 of Result
LDY TEMP1 ;Get Bits 8-15 of Result
LDX TEMP0 ;Get Bits 0-7 of Result
JMP IACC ;Store Y,X in INTACC and Return in Y,X
;idiv(d) - Integer DIVide
;imod(d) - Integer MODulus d % s
;Args: Y,X - Divisor
;Requires: DSTPTR = Dividend
;Sets: SRCPTR = Divisor
; DSTPTR = Quotient
; TEMP1,TEMP2 = Remainder
;Requires: IACC(d) = Dividend
;Sets: INTARG = Divisor
; INTACC, INTOVR = Modulus
;Affects: A,C,Z,N
;Returns: Y,X = 16 Bit Modulus
IMOD: JSR IDIV ;Do Division
LDX INTOVR ;get Remainder
LDY INTOVR+1 l
JMP IACC ;Store in INTACC and Return in Y,X
;idiv(s) - Integer DIVide d / s
;Args: Y,X - Divisor
;Requires: IACC(d) = Dividend
;Sets: INTARG = Divisor
; INTACC = Quotient
; INTOVR = Remainder
;Affects: A,C,Z,N
;Returns: Y,X = 16 Bit Quotient
IDIV: JSR .IDIV ;Do Division and
JMP GETDST ;Return Quotient
;imod(d) - Integer MODulus
;Args: Y,X - Divisor
;Requires: DSTPTR = Dividend
;Sets: SRCPTR = Divisor
; DSTPTR = Quotient
; TEMP1,TEMP2 = Remainder
;Affects: A,C,Z,N
;Returns: Y,X = 16 Bit Remainder
IMOD: JSR .IDIV ;Do Division and
JMP RESRXY ;Return Remainder
.IDIV JSR SETSRC ;Save Divisor
STY TEMP1
STY TEMP1+1
IDIV: JSR .SETARG ;Save Divisor
LDY #0
STY INTOVR
STY INTOVR+1
LDX #16 ;repeat for each bit: ...
.IDLOOP ASL DSTPTR ;dividend lb & hb*2, msb -> Carry
ROL DSTPTR+1
ROL TEMP1 ;remainder lb & hb * 2 + msb from carry
ROL TEMP1+1
LDA TEMP1
.IDLOOP ASL INTACC ;dividend lb & hb*2, msb -> Carry
ROL INTACC+1
ROL INTOVR ;remainder lb & hb * 2 + msb from carry
ROL INTOVR+1
LDA INTOVR
SEC
SBC SRCPTR ;subtract divisor to see if it fits in
SBC INTARG ;subtract divisor to see if it fits in
TAY ;lb result -> Y, for we may need it later
LDA TEMP1+1
SBC SRCPTR+1
LDA INTOVR+1
SBC INTARG+1
BCC .IDSKIP ;if carry=0 then divisor didn't fit in yet
STA TEMP1+1 ;else save substraction result as new remainder,
STY TEMP1
INC DSTPTR ;and INCrement result cause divisor fit in 1 times
STA INTOVR+1 ;else save substraction result as new remainder,
STY INTOVR
INC INTACC ;and INCrement result cause divisor fit in 1 times
.IDSKIP DEX
BNE .IDLOOP
RTS
JMP .GETACC ;Return Integer Accumulator
;ishftl(n,i) - Shift Integer i to the Left n Bits
;Sets: TEMP1, TEMP2 = LSB, MSB of Result
;Affects: A,Y,N,Z,C
;Returns: A = Bits Shifted out of Integer
;Args: A = Number of Bits to Shift
; Y,X = Integer Value to Shift
;Sets: INTACC = Bits 0 to 15 of Result
; INTOVR = Bits 16 to 31 of Result
;Sets: INTACC = Shifted Intger
;Affects: N,Z,C
;Returns: A = LSB of Underflow
; Y,X = Shifted Integer
ISHFTL: JSR SAVRXY ;Save X,Y in TEMP1,TEMP2
TAY ;Set Counter to Number of Bits
BEQ .RESRXY ;If Zero, Return
LDA #0 ;Clear Overflow
.LSLOOP ASL TEMP1 ;Shift LSB to Left
ROL TEMP2 ;Rotate MSB to Left
ROL ;Rotate Carry into A
DEY ;Decrement Counter
ISHFTL: JSR IACC ;Save Argument in INTACC
LDX #0 ;Clear Overflow
STX INTOVR
STX INTOVR
TAX ;Set Counter to Number of Bits
BEQ .LSDONE ;If Zero, Return 0
.LSLOOP ASL INTACC ;Shift Bits 0-7 to Left
ROL INTACC+1 ;Rotate Bits 8-15 to Left
ROL INTOVR ;Rotate Bits 16-23 to Left
ROL INTOVR+1 ;Rotate Bits 24-31 to Left
DEX ;Decrement Counter
BNE .LSLOOP ; and Loop if Not 0
BEQ .RESRXY ;Return Shifted Integer
LDA INTOVR ;Return Bits 16-23 in A
.LSDONE JMP .GETACC ;and Bits 0-15 in Y,X
;ishftr(n,i) - Shift Integer i to the Right n Bits
;Sets: TEMP1, TEMP2 = LSB, MSB of Result
;Affects: A,Y,N,Z,C
;Returns: A = Bits Shifted out of Integer
; Y,X = Shifted Integer
ISHFTR: JSR SAVRXY ;Save X,Y in TEMP1,TEMP2
TAY ;Set Counter to Number of Bits
BEQ .RESRXY ;If Zero, Return
LDA #0 ;Clear Overflow
.RSLOOP LSR TEMP2 ;Shift MSB to Right
ROR TEMP1 ;Rotate LSB to Right
ROR ;Rotate Carry into A
DEY ;Decrement Counter
;Args: A = Number of Bits to Shift
; Y,X = Integer Value to Shift
;Sets: INTACC = Bits 0 to 15 of Result
; INTOVR = Bits -1 to -16 of Result
;Sets: INTACC = Shifted Intger
;Affects: N,Z,C
;Returns: A = MSB of Underflow
; Y,X = Shifted Result
ISHFTR: JSR IACC ;Save Argument in INTACC
LDX #0 ;Clear Overflow
STX INTOVR
STX INTOVR
TAX ;Set Counter to Number of Bits
BEQ .RSDONE ;If Zero, Return Argument
.RSLOOP LSR INTACC+1 ;Shift MSB to Right
ROR INTACC ;Rotate LSB to Right
ROR INTOVR+1 ;Rotate Underflow MSB
ROR INTOVR ;Rotate Underflow LSB
DEX ;Decrement Counter
BNE .RSLOOP ; and Loop if Not 0
BEQ .RESRXY ;Load Shifted Integer and Return
LDA INTOVR+1 ;Return Underflow MSB in A
.RSDONE JMP .GETACC ;and Result in Y,X
;atoi(&s) - ASCII string TO Integer
;Args: Y,X = Address of String to Convert
;Sets: TEMP1, TEMP2 = Integer Value
;Affects: TEMP0
;Sets: INTACC = Integer Value
;Affects: TEMP0,TEMP1,TEMP2
;Returns: A = Number of Digits
; Y,X = Integer Value
ATOI: JSR SETSRC ;Initialize Source String
STY TEMP1 ;Initialize Result
STY TEMP2
.AILOOP LDA (SRCPTR),Y ;Get Next Character
.AILOOP LDA (SRCPTR),Y ;Get Next Character
CMP #$30 ;If Less Than '0'
BCC .AIDONE ; Exit
CMP #$3A ;If Greater Than '9'
@ -235,14 +316,18 @@ ATOI: JSR SETSRC ;Initialize Source String
INY ;Increment Index
BPL .AILOOP ; and Loop
.AIDONE TYA ;Return Number of Digits
.RESRXY JMP RESRXY ;and Integer Value
.RESRXY JSR RESRXY ;and Integer Value
JMP IACC
;itoa(n) - Integer TO ASCII string
;Args: Y,X = Integer Value to Convert
;itoa(&d) - Integer TO ASCII string
;Args: Y,X = Address of Destination String
;Uses: INTACC = Integer to Convert
;Uses: DSTPTR = Destination String
;Affects: X
;Returns: A,Y = Length of String
ITOA: JSR CVIBCD ;Convert Integer to Packed BCD
ITOA: JSR SETDST ;Store String Pointer Agrumenr
JSR .GETACC ;Load INTACC
JSR CVIBCD ;Convert Integer to Packed BCD
LDY #0 ;Initialize Index into String
STY TEMP3
.ITOAA LDY #4 ;Set Initial Digit Number
@ -250,24 +335,25 @@ ITOA: JSR CVIBCD ;Convert Integer to Packed BCD
BNE .IASKIP ;If Zero
DEY ; Decrement Digit Number
BNE .IAZERO ; If Not Zero Loop
BEQ .IASKIP ; Else .IDSKIP Unpack
BEQ .IASKIP ; Else Branch into .IALOOP
.IALOOP JSR UPBCDI ;Unpack Digit #Y
.IASKIP TAX ;Save Digit in X
TYA ;Push Digit Number into Stack
TYA ;Push Unpack Index into Stack
PHA
TXA ;and Restore Digit
LDY TEMP3 ;Get Index into String
ORA #$30 ;Convert Digit to ASCII
LDY TEMP3 ;Get Index into String
STA (DSTPTR),Y ;and Store in String
INC TEMP3 ;Increment Index into String
PLA ;Pull Digit Number off Stack
TAY
DEY ;Decrement Digit Number
BPL .IALOOP ;Loop if >= Zero
BPL .IALOOP ;Loop if >= Zero
LDA #0 ;Terminate String
STA (DSTPTR),Y
TYA ;Return String Length
RTS
JMP .GETACC ;and INTACC
;upbcdi() - UnPack digits from BCD Integer
; Assumes that TEMP0, TEMP1, and TEMP2
@ -298,21 +384,17 @@ UPBCDI: PHP
; TEMP1 = Thousands and Hundreds Digit
; TEMP2 = Ten-Thousands Digit
;Affects: A
CVIBCD: LDA #0 ;Clear BCD Bytes
CVIBCD: JSR IACC ;Store Argument
LDA #0 ;Clear BCD Bytes
STA TEMP0
STA TEMP1
STA TEMP2
PHP ;Save Status Register
SEI ;Disable Interrupts
SED ;Set Decimal Mode
TYA ;Push MSB onto Stack
PHA
TXA ;Push LSB onto Stack
PHA
TSX ;Copy Stack Pointer to X
LDY #16 ;Process 16 bits of Binary
.CVLOOP ASL $101,X ;Shift High Bit Into Carry
ROL $102,X
.CVLOOP ASL INTACC ;Shift High Bit Into Carry
ROL INTACC+1
LDA TEMP0 ;Add 6 Digit BCD Number Itself
ADC TEMP0 ; Effectively Multiplying It by 2
STA TEMP0 ; and Adding in the Shifted Out Bit
@ -324,9 +406,27 @@ CVIBCD: LDA #0 ;Clear BCD Bytes
STA TEMP2
DEY ;Decrement Counter and
BNE .CVLOOP ; Process Next Bit
PLA ;Restore X and Y Registers
PLA
PLP ;Restore Status Register
RTS
;icmp(j) - Compare Int i to Int j
;Requires: IACC(i) - int to compare against
;Args: X,Y = int to compare
; N based on return value of A
;Returns A=$01 and C=1 if INTACC > Arg
; A=$00 and Z=1, C=1 if INTACC = Arg
; A=$FF and C=0 if INTACC < Arg
ICMP: CPY INTACC+1 ;Compare MSBs
BCC .GT ;INTACC < Y,X
BNE .LT ;INTACC > Y,X
CPX INTACC ;Compare LSBs
BCC .GT ;INTACC < Y,X
BNE .LT ;INTACC > Y,X
LDA #0
RTS ;Return INTACC = YX
.LT LDA #$FF
RTS ;Return INTACC < YX
.GT LDA #1
RTS ;Return INTACC > YX
ENDSUBROUTINE

View File

@ -2,77 +2,115 @@
* intlib - Standard Library Routines for Integer Values *
*********************************************************/
/* Integer Absolute Value *
* Args: int w - Integer to test *
* Returns: int v -Absolute value of w */
/* Set Integer Accumlator *
* Args: int w - Integer value *
* Sets: iacc = Argument *
* Returns: int w - Argument */
char iacc();
/* Integer Absolute Value *
* Args: int w - Integer value *
* Sets: iacc = Result *
* Returns: int v - Absolute value of w */
char iabs();
/* Integer Add *
* Setup: setsrc(g) - Augend *
* Args: int d - Addend *
* Returns: char c - Carry *
* int r - Sum */
/* Integer Add: g + d *
* Setup: iset(g) - Augend *
* Args: int d - Addend *
* Sets: iacc, iover = Result *
* Returns: char c - Carry *
* int r - Sum */
char iadd();
/* Integer Add Char: c + d *
* Args: char c - Augend *
* int d - Addend *
* Sets: iacc, iover = result *
* Returns: char c - Carry *
* int r - Sum */
char iaddc();
/* ASCII to Integer *
* Convert ASCII string to Unsigned Integer *
* Args: &s - String to Convert *
* Sets: iacc = Result *
* Returns: char n - Number of digits parsed *
* int v - Numeric value of string */
char atoi();
/* Integer to ASCII *
* Convert Unsigned Integer to String *
* Setup: setdst(s) - Destination String *
* Args: int w - Unsigned Int to Convert *
* Returns: char n - Length of string */
/* Integer to ASCII *
* Convert Unsigned Integer to String *
* Setup: iset(i) - Unsigned Int to Convert *
* Args: &s - Destination String *
* Sets: iacc = Argument *
* Returns: char n - Length of string */
void itoa();
/* Integer Divide *
* Divide Unsigned Integers *
* Aetup: setdst(n) - Numerator *
* Args: int d - Denominator *
* Returns: int q - Quotient */
/* Integer unsigned Divide *
* Aetup: iset (n) - Numerator *
* Args: int d - Denominator *
* Sets: iacc = Quotient *
* Returns: int q - Quotient */
char idiv();
/* Integer Maximum *
/* Integer unsigned Maximum *
* Return Largest of Two Integers *
* Requires: setsrc(i) - First Integer *
* Setup: iset(i) - First Integer *
* Args: int j - Second Integer *
* Sets: iacc = Result *
* Returns: int m - Greater of the Two */
char imax();
/* Integer Minimum *
* Return smallest of Two Integers *
* Requires: setsrc(i) - First Integer *
* Args: int j - Second Integer *
* Returns: int m - Lesser of the Two */
/* Integer unsigned Minimum *
* Return smallest of Two Integers *
* Setup: setsrc(i) - First Integer *
* Args: int j - Second Integer *
* Sets: iacc = Result *
* Returns: int m - Lesser of the Two */
char imin();
/* Integer Multiply *
* Multiply Unsigned Integers *
* Requires: setdst(m) - Muliplicand *
* Args: int r - Multiplier *
* Returns: long p - Product */
/* Integer unsigned Modulo *
* Aetup: iset(n) - Numerator *
* Args: int d - Denominator *
* Sets: iacc = Result *
* Returns: int q - Modulus */
char idiv();
/* Integer unsigned Multiply: m * r *
* Setup: iset(m) - Muliplicand *
* Args: int r - Multiplier *
* Sets: iacc, iover = 32 bit Product *
* Returns: long p - 24 bit Product */
char imult();
/* Integer Left Shift *
* Args: char n - Number of Bits *
* int w - Value to Shift *
* Returns: char v - Overflow Bits *
int r - Shifted Integer */
/* Integer Multiply Char: c * r *
* Args: int c - Multplicand
* int r - Multiplier *
* Sets: iacc, iover = 32 bit Product *
* Returns: long p - 24 bit Product */
char imult();
/* Integer Shift Left *
* Args: char n - Number of Bits *
* int w - Value to Shift *
* Sets: iacc = Integer result *
* iover = Integer Overflow *
* Returns: long p - 24 bit Result */
char ishftl();
/* Integer Shift Right *
/* Integer Shift Right *
* Args: char n - Number of Bits *
* int w - Value to Shift *
* Returns: char v - Overflow Bits *
* Sets: iacc = Integer result *
* iover = Integer Underflow *
* Returns: char u - Underflow Bits *
int r - Shifted Integer */
char ishftr();
/* Integer Subtract *
* Requires: setsrc(m) - Minuend *
* Args: int s - Subtrahend *
* Returns: char c - Carry *
* int d - Difference */
/* Integer Subtract: m - s *
* Setup: iaet(m) - Minuend *
* Args: int s - Subtrahend *
* Sets: iacc, iover = result *
* Returns: char c - Carry *
* int d - Difference */
char isub();

View File

@ -5,48 +5,70 @@ DELKEY EQU $08 ;Delete/Backspace Key (Backspace)
ESCKEY EQU $1B ;Escape/Stop Key (Escape)
RTNKEY EQU $0D ;Return/Enter Key (Carriage Return)
;Zero Page Locations
SRCPTR EQU $30 ;Source String Pointer
DSTPTR EQU $32 ;Destination String Pointer
BLKPTR EQU $34 ;Block Segment Pointer
STKPTR EQU $36 ;Stack Pointer
USRPTR EQU $38 ;User Pointer
;Zero Page Variables
; $00-$06 ;Reserved
XMADDR EQU $3A ;Extended Memory Address
XMBANK EQU $3C ;Extended Memory Bank
; $3D ;Unused
XMBANK EQU $07 ;Extended Memory Bank
XMADDR EQU $08 ;Extended Memory Address
RDSEED EQU $3E ;Pseudo-RANDOM Seed
RANDOM EQU $3F ;Pseudo-RANDOM Number Storage
SRCPTR EQU $10 ;Source Pointer
DSTPTR EQU $12 ;Destination Pointer
TEMP0 EQU $40 ;Temporary Storage
TEMP1 EQU $41
TEMP2 EQU $42
TEMP3 EQU $43
TMPPTR EQU $44 ;Temporary Pointer
TEMP0 EQU $14 ;Temporary Storage
TEMP1 EQU $15
TEMP2 EQU $16
TEMP3 EQU $17
TMPPTR EQU $18 ;Temporary Pointer
BLKBGN EQU $46
BLKEND EQU $48
BLKLEN EQU $4A ;Block Segment Length
SYSBFP EQU $4B ;Position in System Buffer
STKBGN EQU $4C ;Stack Start Address
STKEND EQU $4E ;Stack End Address
; $50-$FF ;Free Zero Page for Applications
LSTPTR EQU $1A ;List Pointer
USRPTR EQU $1C ;User Pointer
; $1E ;Reserved
BLKLEN EQU $1F ;Block Segment Length
BLKPTR EQU $20 ;Block Segment Pointer
BLKBGN EQU $22 ;Block Start Address
BLKEND EQU $24 ;Block End Address
STKPTR EQU $26 ;Stack Pointer
STKBGN EQU $28 ;Stack Start Addres
STKEND EQU $2A ;Stack End Address
RDSEED EQU $2C ;Pseudo-RANDOM Seed
RANDOM EQU $2D ;Pseudo-RANDOM Number Storage
SYSBFP EQU $2E ;Position in System Buffer
.STKSAV EQU $2F ;Stack Pointer Storage
INTACC EQU $30 ;Integer Accumulator
INTOVR EQU $32 ;Integer Overflow
INTARG EQU $34 ;Integer Argument
; $34-$3F ;Reserved
; $40-$FF ;Free Zero Page for Applications
SYSBFL EQU 128 ;System Buffer Size (Max String Size)
SYSBFR EQU $0200 ;System Buffer
; $0281-$03FF ;Unused
;Memory Mapped I/O
_KBHIT EQU $FFF0 ;Is a Key Pressed
_GETCH EQU $FFF1 ;Read Keyboard (Blocking)
;Emulated BIOS System Calls
.GETCH EQU $FFE0 ;-K Read Keyboard
.PUTCH EQU $FFE3 ;-C Write to Screen
FSCMD EQU $FFE6 ;-F filecmd() - File I/O Command Processor
SYSCMD EQU $FFE9 ;-S syscmd() - System Command Processor
XMCMD EQU $FFEC ;-E Extended Memory
.STDIO EQU $FFEF ;-M Memory Mapped stdio
EXIT EQU $FFF0 ;-X Exit Emulator
; $0000 ;-N NMI Vector
ARGV EQU $0300 ;Command Line Arguments Bu
ORG $0400 ;START at RAM midpoint
START: JMP MAIN ;Execute Program
;Read Character from Console
GETKEY EQU $FFE0 ;Emulator _GETCH Routine
GETKEY EQU .GETCH ;Emulator _GETCH Routine
;Poll Character from Keyboard
POLKEY: BRK ;Exit Emulator
@ -58,7 +80,7 @@ GETCHR: JSR GETKEY ;Get Key from Console
RTS
;Read Character from stdin
RDCHAR: LDA $FFEA ;Read Character from STDIN
RDCHAR: LDA .STDIO ;Read Character from STDIN
CMP #$FF ;If EOF
BNE RDCHAX
LDA #0 ; Set to ASCII NUL
@ -80,16 +102,12 @@ NEWLIN: LDA #$0D ;Load Carriage Return into Accumulator
JMP PUTCHR ; and Print it
;Print Character to Console
PUTCHR EQU $FFE3 ;Emulator CHROUT Routine
PUTCHR EQU .PUTCH ;Emulator CHROUT Routine
;Write Character to stdout
PRCHAR: STA $FFEA ;Read Character from STDIN
PRCHAR: STA .STDIO ;Read Character from STDIN
RTS
EXIT EQU $FFEC ;Emulator SHUTDN Routine
FSCMD EQU $FFE6 ;run6502 File System Command Routine
INCLUDE "prbyte.a02" ;PRBYTE and PRHEX routines
INCLUDE "putstr.a02" ;PUTSTR routine

View File

@ -1,25 +1,26 @@
/* run6502 Header File */
/* Platform Specific Settings */
#pragma zeropage $50 $FF //Zero Page Free Space
#pragma zeropage $40 $FF //Zero Page Free Space
/* Platform Specific Constants */
#define DELKEY $08 //Delete/Backspace Key
#define DELKEY $7F //Delete/Backspace Key
#define ESCKEY $1B //Escape/Stop Key
#define RTNKEY $0D //Return/Enter Key
#define SYSBFL 128 //System Buffer Length
/* Standard Library Variables */
zeropage int srcptr, dstptr; //Source and Destination Pointer
zeropage int blkptr, stkptr; //Block and Stack Pointers
zeropage int tmpptr, usrptr; //Temporary and User Pointer
int stkbgn, stkend; //Stack Begin and End Address
int blkbgn, blkend; //Block Begin and End Address
char blklen, xmbank; //Block Segment Length, Ext Memory Bank
int xmaddr; //Extended Memory Address
char random, rdseed; //Pseudo-Random Number and Seed
char temp0, temp1, temp2, temp3; //Temporary Storage
char sysbfr[], sysbfp; //System String Buffer and Position
zeropage int srcptr, dstptr; //Source and Destination Pointer
zeropage int blkptr, stkptr; //Block and Stack Pointers
zeropage int tmpptr, lstptr, usrptr; //Temporary and User Pointer
int stkbgn, stkend; //Stack Begin and End Address
int blkbgn, blkend; //Block Begin and End Address
char blklen, xmbank; //Block Segment Length, Ext Memory Bank
int xmaddr; //Extended Memory Address
int intacc, intarg, intovr; //Integer Accumulator, Argument, Overflow
char random, rdseed; //Pseudo-Random Number and Seed
char temp0, temp1, temp2, temp3; //Temporary Storage
char sysbfr[], sysbfp; //System String Buffer and Position
/* System Subroutines */
void delchr(); //Delete previous character
@ -29,6 +30,7 @@ void newlin(); //Advance cursor to beginning of next line
char polkey(); //Poll Console for character
void prbyte(); //Print Accumulator as Hexadecimal number
void prhex(); //Print Low Nybble of Accumulator as Hex Digit
void prword(); //Print Low Nybble of Accumulator as Hex Digit
char putchr(); //Print ASCII character to Console
char putstr(); //Print ASCII string to Console

View File

@ -22,6 +22,7 @@ head:
putchr('A'); //Alphabetic
putchr('N'); //Alphanumeric
putchr('M'); //Alphanumunder
putchr('T'); //Alphanumundots
putchr('G'); //Graphic
putchr('R'); //Printable
putchr('B'); //Binary
@ -45,6 +46,7 @@ loop:
c = isalph(i) & $0A | $20; putchr(c);
c = isalnm(i) & $0A | $20; putchr(c);
c = isalnu(i) & $0A | $20; putchr(c);
c = isalud(i) & $0A | $20; putchr(c);
c = isgrph(i) & $0A | $20; putchr(c);
c = isprnt(i) & $0A | $20; putchr(c);
c = isbdgt(i) & $0A | $20; putchr(c);

View File

@ -16,44 +16,70 @@ char s[128]; //Test String
char cval,cnum,ctot; //Character Function Variables
int ivar,ival; //Integer Variables
int icmp,itot,ires; //Function Variables
int ichk,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);
void cpcval(cnum) {
if (cval <> cnum) {
puthex(cval); puts("<>"); puthex(cnum);
failln();
goto exit;
}
}
/* Test imin() and imax() */
void minmax() {
void cpival(ichk) {
if (>ival <> >ichk or <ival <> <ichk) {
prword(ival); puts("<>"); prword(ichk);
failln();
goto exit;
}
}
/* Test imin() and imax() and icmp() */
void minmax(ctot) {
newlin();
puts("LESS=$"); putwrd(less); puts(",MORE=$"); putwrd(more); newlin();
puts(" IMIN()=$"); setsrc(less);
ival = imin(more); putwrd(ival); newlin();
puts("IMIN(IACC($"); prword(less); puts("),$"); prword(more); puts(")=$");
ival = imin(iacc(less),more); prword(ival); newlin();
cpival(less);
puts(" IMAX()=$"); setsrc(less);
ival = imax(more); putwrd(ival); newlin();
puts("IMIN(IACC($"); prword(more); puts("),$"); prword(less); puts(")=$");
ival = imin(iacc(more),less); prword(ival); newlin();
cpival(less);
puts("IMAX(IACC($"); prword(less); puts("),$"); prword(more); puts(")=$");
iacc(less); ival = imax(more); prword(ival); newlin();
cpival(more);
puts("IMIN(IACC($"); prword(more); puts("),$"); prword(less); puts(")=$");
iacc(more); ival = imax(less); prword(ival); newlin();
cpival(more);
puts("ICMP(IACC($"); prword(less); puts("),$"); prword(more); puts(")=$");
cval = icmp(iacc(less),more); puthex(cval); newlin();
cpcval(-ctot);
puts("ICMP(IACC($"); prword(more); puts("),$"); prword(less); puts(")=$");
cval = icmp(iacc(more),less); puthex(cval); newlin();
cpcval(ctot);
}
/* Test cvibcd() and upbcdi() */
void intbcd(ival) {
newlin(); puts("CVIBCD($"); putwrd(ival); puts(")=$");
newlin(); puts("CVIBCD($"); prword(ival); puts(")=$");
cvibcd(ival); puthex(temp2); puthex(temp1); puthex(temp0);
newlin(); puts("UPBCDI()=");
for (cnum=4; cnum:+; cnum--) {if(cnum<4) {putc(',');} putnyb(upbcdi(0,cnum));}
}
/* Test itoa() and atoi() */
void itaati(ivar) {
newlin();
puts("ITOA($"); putwrd(ivar); puts(")=\"");
setdst(s); size = itoa(ivar); puts(s); putln("\"");
//intbcd(ivar); newlin();
puts("ITOA(IACC($"); prword(ivar); puts(",S); ");
iacc(ivar); size = itoa(s); puts(" S=\""); puts(s); putln("\"");
puts("ATOI(\""); puts(s); puts("\")=$");
ival = atoi(s); putwrd(ival); newlin();
ival = atoi(s); prword(ival); newlin();
cpival(ivar);
}
@ -62,11 +88,11 @@ void itaati(ivar) {
void addsub(ivar) {
newlin();
putint(ival); putc('+'); putint(ivar); putc('=');
setsrc(ival); ctot, itot = iadd(ivar);
putint(itot); puts(" carry=$"); puthex(ctot); newlin();
iacc(ival); ctot, itot = iadd(ivar);
putint(itot); puts(", carry="); prhex(ctot); newlin();
putint(itot); putc('-'); putint(ivar); putc('=');
setsrc(itot); ires = isub(ivar);
putint(itot); puts(" carry=$"); puthex(ctot); newlin();
iacc(itot); ires = isub(ivar);
putint(itot); puts(", carry="); prhex(ctot); newlin();
cpival(ires);
}
@ -74,15 +100,15 @@ void addsub(ivar) {
void mltdiv(ivar) {
newlin();
putint(ival); putc('*'); putint(ivar); putc('=');
setdst(ival); cval,itot = imult(ivar); putint(itot);
iacc(ival); cval,itot = imult(ivar); putint(itot);
if (cval) puts(" OVERFLOW!"); newlin();
putint(itot); putc('/'); putint(ivar); putc('=');
setdst(itot); ires = idiv(ivar); putint(ires); newlin();
iacc(itot); ires = idiv(ivar); putint(ires); newlin();
cpival(ires);
ival>>; setsrc(ival); cval,itot = iadd(itot);
ival>>; iacc(ival); cval,itot = iadd(itot);
if (cval) return; //Number to Large to Modulo
putint(itot); putc('%'); putint(ivar); putc('=');
setdst(itot); ires = imod(ivar); putint(ires); newlin();
iacc(itot); ires = imod(ivar); putint(ires); newlin();
cpival(ires);
}
@ -110,50 +136,55 @@ void shftlr(cval, ivar) {
cpival(itot);
}
main:
less = $009A; more = $00DE; minmax();
less = $789A; more = $78DE; minmax();
less = $7800; more = $BC00; minmax();
less = $789A; more = $BCDE; minmax();
less = $F18F; more = $F18F; minmax();
less = $009A; more = $00DE; minmax(1);
less = $789A; more = $78DE; minmax(1);
anykey();
less = $7800; more = $BC00; minmax(1);
less = $789A; more = $BCDE; minmax(1);
less = $F18F; more = $F18F; minmax(0);
anykey();
itaati(&0);
itaati(&234);
itaati(&256);
itaati(&456);
itaati(&23456);
itaati(&$FFFF);
anykey();
doasc:
//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);
ival = &$FDEC; addsub(&$CDEF);
anykey();
doadd:
ival = &23; addsub(&34);
ival = &1234; addsub(&5678);
ival = &23456; addsub(&34567);
ival = &$7700; addsub(&$6600);
ival = &$7FFF; addsub(&$8000);
ival = &$FDEC; addsub(&$CDEF);
anykey();
domlt:
ival = &23; mltdiv(&34);
ival = &123; mltdiv(&234);
ival = &255; mltdiv(&257);
anykey();
ival = &23; mltdiv(&34);
ival = &123; mltdiv(&234);
ival = &255; mltdiv(&257);
anykey();
shftlr(0,&$AA55);
shftlr(1,&$A55A);
shftlr(2,&$F00F);
shftlr(3,&$0FF0);
shftlr(4,&$AA55);
shftlr(7,&$A55A);
anykey();
shftlr(8,&$AA55);
shftlr(9,&$A55A);
shftlr(11,&$0FF0);
shftlr(12,&$AA55);
shftlr(15,&$A55A);
shftlr(16,&$F00F);
doshft:
shftlr(0,&$AA55);
shftlr(1,&$A55A);
shftlr(2,&$F00F);
shftlr(3,&$0FF0);
shftlr(4,&$AA55);
shftlr(7,&$A55A);
anykey();
shftlr(8,&$AA55);
shftlr(9,&$A55A);
shftlr(11,&$0FF0);
shftlr(12,&$AA55);
shftlr(15,&$A55A);
shftlr(16,&$F00F);
anykey();
goto exit;