diff --git a/Makefile.apple1basic b/Makefile.apple1basic new file mode 100644 index 0000000..c9a99e3 --- /dev/null +++ b/Makefile.apple1basic @@ -0,0 +1,12 @@ +OBJS=perfect6502.o apple1basic.o +CFLAGS=-Werror -Wall -O3 +CC=clang + +all: apple1basic + +apple1basic: $(OBJS) + $(CC) -o apple1basic $(OBJS) + +clean: + rm -f $(OBJS) apple1basic + diff --git a/apple1basic.bin b/apple1basic.bin new file mode 100644 index 0000000..9681b0e Binary files /dev/null and b/apple1basic.bin differ diff --git a/apple1basic.c b/apple1basic.c new file mode 100644 index 0000000..0ca22db --- /dev/null +++ b/apple1basic.c @@ -0,0 +1,131 @@ +#include +#ifndef _WIN32 +#include + +#include "perfect6502.h" + +/************************************************************ + * + * Interface to OS Library Code / Monitor + * + ************************************************************/ + +/* imported by runtime.c */ +unsigned char A, X, Y, S, P; +unsigned short PC; +int N, Z, C; + +void +init_monitor() +{ + FILE *f; + f = fopen("apple1basic.bin", "r"); + fread(memory + 0xE000, 1, 4096, f); + fclose(f); + + memory[0xfffc] = 0x00; + memory[0xfffd] = 0xE0; + +} + + +void +charout(char ch) { + unsigned short S = readSP(); + unsigned char a = 1 + memory[0x0100+S+1] | memory[0x0100+((S+2) & 0xFF)] << 8; + + /* + * Apple I BASIC prints every character received + * from the terminal. UNIX terminals do this + * anyway, so we have to avoid printing every + * line again + */ + if (a==0xe2a6) /* character echo */ + return; + if (a==0xe2b6) /* CR echo */ + return; + + /* + * Apple I BASIC prints a line break and 6 spaces + * after every 37 characters. UNIX terminals do + * line breaks themselves, so ignore these + * characters + */ + if (a==0xe025 && (ch==10 || ch==' ')) + return; + + /* INPUT */ + if (a==0xe182) { +#if _WIN32 + if (!isatty(0)) + return; +#else + struct stat st; + fstat(0, &st); + if (S_ISFIFO (st.st_mode)) + return; +#endif + } +#endif + + putc(ch, stdout); + fflush(stdout); +} + +void +handle_monitor() +{ + if (readRW()) { + unsigned short a = readAddressBus(); + if ((a & 0xFF1F) == 0xD010) { + unsigned char c = getchar(); + if (c == 10) + c = 13; + c |= 0x80; + writeDataBus(c); + } + if ((a & 0xFF1F) == 0xD011) { + if (readPC() == 0xE006) + /* if the code is reading a character, we have one ready */ + writeDataBus(0x80); + else + /* if the code checks for a STOP condition, nothing is pressed */ + writeDataBus(0); + } + if ((a & 0xFF1F) == 0xD012) { + /* 0x80 would mean we're not yet ready to receive a character */ + writeDataBus(0); + } + } else { + unsigned short a = readAddressBus(); + unsigned char d = readDataBus(); + if ((a & 0xFF1F) == 0xD012) { + unsigned char temp8 = d & 0x7F; + if (temp8 == 13) + temp8 = 10; + charout(temp8); + } + } +} + +int +main() +{ + int clk = 0; + + initAndResetChip(); + + /* set up memory for user program */ + init_monitor(); + + /* emulate the 6502! */ + for (;;) { + step(); + clk = !clk; + if (!clk) + handle_monitor(); + +// chipStatus(); + //if (!(cycle % 1000)) printf("%d\n", cycle); + }; +} diff --git a/perfect6502.h b/perfect6502.h index 070acf0..7f3aa60 100644 --- a/perfect6502.h +++ b/perfect6502.h @@ -10,6 +10,7 @@ extern unsigned char readSP(); extern unsigned char readP(); extern unsigned int readRW(); extern unsigned short readAddressBus(); +extern void writeDataBus(unsigned char); extern unsigned char readDataBus(); extern unsigned char readIR();