This commit is contained in:
Christopher A. Mosher 2022-11-03 18:26:07 -04:00
parent 617bad3e51
commit 348f85e391
14 changed files with 131 additions and 51 deletions

View File

@ -11,6 +11,8 @@
cpu epple2
# standard 48K RAM with mixed chip brands
motherboard ram E MM5290 MM5290 MM5290 MK4116 MM5290 MM5290 MM5290 MK4116
motherboard strap E 16K 8000

View File

@ -0,0 +1,16 @@
# Use the Visual 6502 emulation algorithm (from http://www.visual6502.org/).
# WARNING: this is EXTREMELY SLOW
cpu visual6502
motherboard ram E MM5290 MM5290 MM5290 MK4116 MM5290 MM5290 MM5290 MK4116
motherboard strap E 16K 8000
motherboard ram D MM5290 MM5290 MK4116 MK4116 MM5290 MK4116 MM5290 MCM4116
motherboard strap D 16K 4000
motherboard ram C MK4116 MK4116 MM5290 MM5290 MM5290 MM5290 MM5290 MM5290
motherboard strap C 16K 0000
import motherboard rom 2C00 ${LIBDIR}/epple2/system/epple2sys.a65

View File

@ -121,6 +121,26 @@ strap c 4K 0000
#### cpu
The `cpu` command chooses which CPU emulator to run with.
``` conf
cpu epple2
```
Valid values are:
`epple2` The standard, faster, albeit less accurate, high-level emulator. Works for 99.99% of known cases.
This is the default value, used when the `cpu` command is not present.
`visual6502` The emulator based on the algorithm and transistor circuitry from http://www.visual6502.org/.
WARNING: this emulator is *extremely slow*, but absolutely 100% accurate to the original MOS6502.
Note: the CPU cannot be changed in the user interface, only in the configuration file.
#### import
The `import` command imports a binary image file into the emulated Apple's ROMs.

View File

@ -72,17 +72,9 @@ add_executable(epple2 ${sources})
find_package(SDL2 CONFIG)
message(STATUS "SDL2_INCLUDE_DIRS: ${SDL2_INCLUDE_DIRS}")
message(STATUS "SDL2_LIBRARIES: ${SDL2_LIBRARIES}")
target_include_directories(epple2 PRIVATE ${SDL2_INCLUDE_DIRS})
message(STATUS "SDL2_LIBRARIES: ${SDL2_LIBRARIES}")
target_link_libraries(epple2 ${SDL2_LIBRARIES})
target_compile_features(epple2 PRIVATE cxx_std_17)
target_compile_definitions(epple2 PRIVATE ETCDIR="${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_SYSCONFDIR}")
option(USE_EMU "Use http://www.visual6502.org/ CPU (will run slowly)")
if (USE_EMU)
message(STATUS "USE_EMU")
target_compile_definitions(epple2 PRIVATE USE_EMU)
# target_compile_definitions(epple2 PRIVATE TRACESEG)
target_compile_definitions(epple2 PRIVATE TRACEREG)
endif()

View File

@ -1,4 +1,4 @@
/*
/*
* File: Emu6502.h
* Author: Christopher
*
@ -8,6 +8,7 @@
#ifndef EMU6502_H
#define EMU6502_H
#include "abstractcpu.h"
#include "Cpu6502Helper.h"
#include "Cpu6502.h"
#include "Trace.h"
@ -19,7 +20,7 @@
class AddressBus;
class Emu6502 {
class Emu6502 : public AbstractCpu {
public:
Emu6502(std::istream& transistors, AddressBus& mem) : tn(transistors, segs, transes), c(tn), trace(segs, transes, c), cpu(mem, trace, c), cpuhelper(cpu, c) {

29
src/abstractcpu.h Normal file
View File

@ -0,0 +1,29 @@
/*
epple2
Copyright (C) 2008 by Christopher A. Mosher <cmosher01@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY, without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ABSTRACTCPU_H
#define ABSTRACTCPU_H
class AbstractCpu {
public:
virtual ~AbstractCpu() {};
virtual void powerOn() = 0;
virtual void reset() = 0;
virtual void tick() = 0;
};
#endif

View File

@ -48,12 +48,8 @@ Apple2::Apple2(KeypressQueue& keypresses, PaddleButtonStates& paddleButtonStates
addressBus(gui,revision,ram,rom,kbd,videoMode,paddles,paddleButtonStates,speaker,cassetteIn,cassetteOut,slts),
picgen(tv,videoMode,revision),
video(videoMode,addressBus,picgen,textRows),
#ifdef USE_EMU
transistors("transistors"),
cpu(transistors,addressBus),
#else
cpu(addressBus),
#endif
transistors("transistors"),
cpu(NULL),
powerUpReset(*this),
revision(1)
{
@ -63,9 +59,22 @@ Apple2::~Apple2()
{
}
void Apple2::useEpple2Cpu() {
if (this->cpu == NULL) {
std::cout << "Using fast Epple2 CPU emulator" << std::endl;
this->cpu = new CPU(this->addressBus);
}
}
void Apple2::useVisual6502Cpu() {
if (this->cpu == NULL) {
std::cout << "Using http://www.visual6502.org/ CPU emulation (which will be slow)." << std::endl;
this->cpu = new Emu6502(this->transistors, this->addressBus);
}
}
void Apple2::tick() {
this->cpu.tick();
this->cpu->tick();
this->slts.tick();
this->video.tick();
this->paddles.tick();
@ -81,7 +90,7 @@ void Apple2::tick() {
void Apple2::powerOn()
{
this->ram.powerOn();
this->cpu.powerOn();
this->cpu->powerOn();
this->videoMode.powerOn();
this->video.powerOn();
this->picgen.powerOn();
@ -95,6 +104,6 @@ void Apple2::powerOff()
void Apple2::reset()
{
this->cpu.reset();
this->cpu->reset();
this->slts.reset();
}

View File

@ -28,6 +28,7 @@
#include "picturegenerator.h"
#include "textcharacters.h"
#include "video.h"
#include "abstractcpu.h"
#include "cpu.h"
#include "paddles.h"
#include "paddlebuttonstates.h"
@ -56,12 +57,8 @@ class Apple2 : public Timable
PictureGenerator picgen;
TextCharacters textRows;
Video video;
#ifdef USE_EMU
std::ifstream transistors;
Emu6502 cpu;
#else
CPU cpu;
#endif
std::ifstream transistors;
AbstractCpu* cpu;
PowerUpReset powerUpReset;
int revision;
@ -69,6 +66,9 @@ public:
Apple2(KeypressQueue& keypresses, PaddleButtonStates& paddleButtonStates, AnalogTV& tv, HyperMode& fhyper, KeyboardBufferMode& buffered, ScreenImage& gui);
~Apple2();
void useEpple2Cpu();
void useVisual6502Cpu();
void powerOn();
void powerOff();
void reset();

View File

@ -17,6 +17,7 @@
*/
#include "configep2.h"
#include "apple2.h"
#include "memory.h"
#include "memoryrandomaccess.h"
#include "slots.h"
@ -93,14 +94,8 @@ static void trim(std::string& str)
}
}
void Config::parse(MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut)
void Config::parse(MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut, Apple2* apple2)
{
#ifdef USE_EMU
std::cout << "Running with http://www.visual6502.org/ CPU emulation (which will be slow)." << std::endl;
#endif
std::ifstream* pConfig;
std::string path(this->file_path);
@ -192,7 +187,7 @@ void Config::parse(MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revis
trim(line);
if (!line.empty())
{
parseLine(line,ram,rom,slts,revision,gui,cassetteIn,cassetteOut);
parseLine(line,ram,rom,slts,revision,gui,cassetteIn,cassetteOut,apple2);
}
std::getline(*pConfig,line);
}
@ -201,11 +196,11 @@ void Config::parse(MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revis
// TODO: make sure there is no more than ONE stdin and/or ONE stdout card
}
void Config::parseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut)
void Config::parseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut, Apple2* apple2)
{
try
{
tryParseLine(line,ram,rom,slts,revision,gui,cassetteIn,cassetteOut);
tryParseLine(line,ram,rom,slts,revision,gui,cassetteIn,cassetteOut,apple2);
}
catch (const ConfigException& err)
{
@ -220,7 +215,7 @@ static std::string filter_row(const std::string &row) {
return std::string(1, static_cast<char>(std::toupper(row[0])));
}
void Config::tryParseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut)
void Config::tryParseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut, Apple2* apple2)
{
std::istringstream tok(line);
@ -456,10 +451,28 @@ void Config::tryParseLine(const std::string& line, MemoryRandomAccess& ram, Memo
throw ConfigException("error: unknown cassette command: "+cas);
}
}
else if (cmd == "cpu")
{
std::string cpu;
tok >> cpu;
if (apple2 != NULL) {
if (cpu == "epple2") {
apple2->useEpple2Cpu();
} else if (cpu == "visual6502") {
apple2->useVisual6502Cpu();
} else {
throw ConfigException("invalid value for cpu command: "+cpu);
}
}
}
else
{
throw ConfigException("Invalid command: "+cmd);
}
if (apple2 != NULL) {
apple2->useEpple2Cpu(); // set default CPU
}
}
void Config::loadDisk(Slots& slts, int slot, int drive, const std::string& fnib)

View File

@ -25,6 +25,7 @@ class Slots;
class ScreenImage;
class CassetteIn;
class CassetteOut;
class Apple2;
class ConfigException {
public:
@ -41,14 +42,14 @@ private:
static void unloadDisk(Slots& slts, int slot, int drive);
static void saveDisk(Slots& slts, int slot, int drive);
static void insertCard(const std::string& cardType, int slot, Slots& slts, ScreenImage& gui, std::istringstream& tok);
static void tryParseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut);
static void tryParseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut, Apple2* apple2);
public:
Config(const std::string& file_path);
~Config();
void parse(MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut);
static void parseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut);
void parse(MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut, Apple2* apple2);
static void parseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut, Apple2* apple2);
};
#endif

View File

@ -18,10 +18,11 @@
#ifndef CPU_H
#define CPU_H
#include "abstractcpu.h"
class AddressBus;
#include <istream>
class CPU
{
class CPU : public AbstractCpu {
private:
enum { MEMORY_LIM = 1 << 0x10 };
enum { IRQ_VECTOR = MEMORY_LIM-2 }; // or BRK
@ -43,7 +44,7 @@ private:
bool pendingIRQ;
bool pendingNMI;
bool pendingReset;
bool started;
unsigned char a;
@ -205,7 +206,7 @@ private:
public:
CPU(AddressBus& addressBus);
~CPU();
virtual ~CPU();
void powerOn();
void reset();

View File

@ -72,7 +72,7 @@ void Emulator::powerOffComputer() {
}
void Emulator::config(Config& cfg) {
cfg.parse(this->apple2.ram, this->apple2.rom, this->apple2.slts, this->apple2.revision, this->screenImage, this->apple2.cassetteIn, this->apple2.cassetteOut);
cfg.parse(this->apple2.ram, this->apple2.rom, this->apple2.slts, this->apple2.revision, this->screenImage, this->apple2.cassetteIn, this->apple2.cassetteOut, &this->apple2);
this->apple2.ram.dump_config();
}
@ -444,7 +444,7 @@ void Emulator::processCommand() {
return;
}
Config::parseLine(cmdline, this->apple2.ram, this->apple2.rom, this->apple2.slts, this->apple2.revision, this->screenImage, this->apple2.cassetteIn, this->apple2.cassetteOut);
Config::parseLine(cmdline, this->apple2.ram, this->apple2.rom, this->apple2.slts, this->apple2.revision, this->screenImage, this->apple2.cassetteIn, this->apple2.cassetteOut, NULL);
cmdline.erase(cmdline.begin(), cmdline.end());
}

View File

@ -60,7 +60,7 @@ class Emulator
void dispatchKeyUp(const SDL_KeyboardEvent& keyEvent);
void cmdKey(const SDL_KeyboardEvent& keyEvent);
void processCommand();
bool isSafeToQuit();
bool isSafeToQuit();
public:
Emulator();

View File

@ -44,9 +44,5 @@ void PowerUpReset::tick()
void PowerUpReset::powerOn()
{
#ifdef USE_EMU
this->pendingTicks = 99; // TODO REMOVE THIS
#else
this->pendingTicks = (int)(E2Const::AVG_CPU_HZ*.3); // U.A.II, p. 7-15
#endif
}