mirror of
https://github.com/JorjBauer/aiie.git
synced 2024-12-04 18:52:42 +00:00
initial commit
This commit is contained in:
commit
85a97abe13
16
Makefile
Executable file
16
Makefile
Executable 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
52
README.txt
Normal 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 :)
|
||||
|
73
cpu.h
Normal file
73
cpu.h
Normal 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
17
mmu.h
Normal 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
8202
util/6502_functional_test.h
Normal file
File diff suppressed because it is too large
Load Diff
8206
util/6502_functional_test_2.h
Normal file
8206
util/6502_functional_test_2.h
Normal file
File diff suppressed because it is too large
Load Diff
8202
util/65C02_extended_opcodes_test.h
Normal file
8202
util/65C02_extended_opcodes_test.h
Normal file
File diff suppressed because it is too large
Load Diff
64
util/testharness.cpp
Normal file
64
util/testharness.cpp
Normal 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);
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user