initial commit

This commit is contained in:
Jorj Bauer 2017-02-19 13:46:13 -05:00
commit 85a97abe13
9 changed files with 25884 additions and 0 deletions

16
Makefile Executable file
View File

@ -0,0 +1,16 @@
LDFLAGS=-L/usr/local/lib
CXXFLAGS=-Wall -I .. -I . -O3
TSRC=cpu.cpp util/testharness.cpp
all:
@echo There is no 'all' target. Yet.
clean:
rm -f *.o *~ */*.o */*~ testharness.basic testharness.verbose testharness.extended
test: $(TSRC)
g++ $(CXXFLAGS) -DBASICTEST $(TSRC) -o testharness.basic
g++ $(CXXFLAGS) -DVERBOSETEST $(TSRC) -o testharness.verbose
g++ $(CXXFLAGS) -DEXTENDEDTEST $(TSRC) -o testharness.extended

52
README.txt Normal file
View File

@ -0,0 +1,52 @@
Aiie!
=====
Aiie! is an Apple //e emulator, written ground-up for the Teensy
3.6.
The name comes from a game I used to play on the Apple //e back
around 1986 - Ali Baba and the Forty Thieves, published by Quality
Software in 1981.
http://crpgaddict.blogspot.com/2013/07/game-103-ali-baba-and-forty-thieves-1981.html
When characters in the game did damage to each other, they exclaimed
something like "HAH! JUST A SCRATCH!" or "AAARGH!" or "OH MA, I THINK
ITS MY TIME" [sic]. One of these exclamations was "AIIYEEEEE!!"
Build log:
----------
https://hackaday.io/project/19925-aiie-an-embedded-apple-e-emulator
CPU
===
The CPU is a 65C02, not quite complete; it supports all of the 65C02
documented opcodes but not the undocumented ones here:
http://www.oxyron.de/html/opcodes02.html
The timing of the CPU is also not quite correct. It's close, but
doesn't count cycles due to page boundary crossings during branch
instructions. (See the "cycle count footnotes" in cpu.cpp.)
The CPU passes the 6502 functional test from here:
https://github.com/Klaus2m5/6502_65C02_functional_tests
... which is included in binary form in the test harness (see the .h
files in util/ for notes).
testharness.basic should reach "test number 240", hang for a while,
and then exit.
testharness.verbose should show that it gets through 43 tests, test
240, and then loops repeatedly for a while (exiting at a somewhat
arbitrary point).
testharness.extended currently fails (hanging at 0x733) because I
haven't implemented the undocumented opcodes. It should get to address
0x24a8 and hang. Some day I'll finish implementing all of the
undocumented opcodes :)

1052
cpu.cpp Normal file

File diff suppressed because it is too large Load Diff

73
cpu.h Normal file
View File

@ -0,0 +1,73 @@
#ifndef __CPU_H
#define __CPU_H
#include <stdlib.h>
#include <stdint.h>
class MMU;
// Flags (P) register bit definitions.
// Negative
#define F_N (1<<7)
// Overflow
#define F_V (1<<6)
#define F_UNK (1<<5) // What the heck is this?
// Break
#define F_B (1<<4)
// Decimal
#define F_D (1<<3)
// Interrupt Disable
#define F_I (1<<2)
// Zero
#define F_Z (1<<1)
// Carry
#define F_C (1<<0)
class Cpu {
public:
Cpu();
~Cpu();
void Reset();
void nmi();
void rst();
void brk();
void irq();
uint8_t Run(uint8_t numSteps);
uint8_t step();
uint8_t X();
uint8_t Y();
uint8_t A();
uint16_t PC();
uint8_t SP();
uint8_t P();
protected:
// Stack manipulation
void pushS8(uint8_t b);
void pushS16(uint16_t w);
uint8_t popS8();
uint16_t popS16();
public:
void SetMMU(MMU *mmu) { this->mmu = mmu; }
public:
uint16_t pc;
uint8_t sp;
uint8_t a;
uint8_t x;
uint8_t y;
uint8_t flags;
uint32_t cycles;
MMU *mmu;
};
#endif

17
mmu.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef __MMU_H
#define __MMU_H
#include <stdint.h>
class MMU {
public:
virtual ~MMU() {}
virtual void Reset() = 0;
virtual uint8_t read(uint16_t mem) = 0;
virtual void write(uint16_t mem, uint8_t val) = 0;
virtual uint8_t readDirect(uint16_t address, uint8_t fromPage) = 0;
};
#endif

8202
util/6502_functional_test.h Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

64
util/testharness.cpp Normal file
View File

@ -0,0 +1,64 @@
#include <stdio.h>
#include <time.h>
#include <string.h>
#include "cpu.h"
#include "mmu.h"
#ifdef BASICTEST
#include "6502_functional_test.h"
#elif defined(VERBOSETEST)
#include "6502_functional_test_2.h"
#elif defined(EXTENDEDTEST)
#include "65C02_extended_opcodes_test.h"
#else
#error undefined test - specify one of BASICTEST, VERBOSETEST, or EXTENDEDTEST
#endif
class TestMMU : public MMU {
public:
TestMMU() {}
virtual ~TestMMU() {}
virtual void Reset() {}
virtual uint8_t read(uint16_t mem) { if (mem == 0xBFF0) { return 'R'; } return ram[mem];}
virtual void write(uint16_t mem, uint8_t val) {
if (mem == 0xBFF0) {printf("%c", val); return;}
if (mem == 0x200) {printf("Start test %d\n", val);}
ram[mem] = val;}
virtual uint8_t readDirect(uint16_t address, uint8_t fromPage) { return read(address);}
uint8_t ram[65536];
};
Cpu cpu;
TestMMU mmu;
int main(int argc, char *argv[])
{
cpu.SetMMU(&mmu);
cpu.rst();
// Load the 6502 functional test
memcpy(mmu.ram, functest, 0x10000);
cpu.pc = 0x400;
// cpu.Reset();
time_t startTime = time(NULL);
// call cpu.Run() in the worst possible way (most overhead)
for (uint32_t i=0; i<1000000000; i++) {
cpu.Run(1);
#if 0
if (cpu.pc < 0x477F) {
printf("%llu OP $%.2X #%d 0x%.2X X 0x%.2X Y 0x%.2X A 0x%.2X SP 0x%.2X S 0x%.2X\n", cpu.cycles, mmu.read(cpu.pc), mmu.read(0x200), cpu.pc, cpu.x, cpu.y, cpu.a, cpu.sp, cpu.flags);
}
#endif
}
time_t endTime = time(NULL);
printf("%ld seconds\n", endTime - startTime);
printf("Ending PC: 0x%X\n", cpu.pc);
}