Updated to v067r21 release.

byuu says:

This moves toward a profile-selection mode. Right now, it is incomplete.
There are three binaries, one for each profile. The GUI selection
doesn't actually do anything yet. There will be a launcher in a future
release that loads each profile's respective binary.

I reverted away from blargg's SMP library for the time being, in favor
of my own. This will fix most of the csnes/bsnes-performance bugs. This
causes a 10% speed hit on 64-bit platforms, and a 15% speed hit on
32-bit platforms. I hope to be able to regain that speed in the future,
I may also experiment with creating my own fast-SMP core which drops bus
hold delays and TEST register support (never used by anything, ever.)

Save states now work in all three cores, but they are not
cross-compatible. The profile name is stored in the description field of
the save states, and it won't load a state if the profile name doesn't
match.

The debugger only works on the research target for now. Give it time and
it will return for the other targets.

Other than that, let's please resume testing on all three once again.
See how far we get this time :)
I can confirm the following games have issues on the performance
profile:
- Armored Police Metal Jacket (minor logo flickering, not a big deal)
- Chou Aniki (won't start, so obviously unplayable)
- Robocop vs The Terminator (major in-game flickering, unplayable)

Anyone still have that gigantic bsnes thread archive from the ZSNES
forum? Maybe I posted about how to fix those two broken games in there,
heh.

I really want to release this as v1.0, but my better judgment says we
need to give it another week. Damn.
This commit is contained in:
Tim Allen 2010-10-20 22:22:44 +11:00
parent 1a32ed7cfa
commit 3c3956744f
69 changed files with 421 additions and 4573 deletions

View File

@ -1,6 +1,6 @@
include nall/Makefile
snes := snes
profile := asnes
profile := research
ui := qt
# compiler
@ -56,19 +56,19 @@ ifeq ($(platform),osx)
test -d ../bsnes.app || mkdir -p ../bsnes.app/Contents/MacOS
$(strip $(cpp) -o ../bsnes.app/Contents/MacOS/bsnes $(objects) $(link))
else
$(strip $(cpp) -o out/$(profile) $(objects) $(link))
$(strip $(cpp) -o out/bsnes-$(profile) $(objects) $(link))
endif
install:
ifeq ($(platform),x)
install -D -m 755 out/$(profile) $(DESTDIR)$(prefix)/bin/$(profile)
install -D -m 755 out/bsnes $(DESTDIR)$(prefix)/bin/bsnes
install -D -m 644 qt/data/bsnes.png $(DESTDIR)$(prefix)/share/pixmaps/bsnes.png
install -D -m 644 qt/data/bsnes.desktop $(DESTDIR)$(prefix)/share/applications/bsnes.desktop
endif
uninstall:
ifeq ($(platform),x)
rm $(DESTDIR)$(prefix)/bin/$(profile)
rm $(DESTDIR)$(prefix)/bin/bsnes
rm $(DESTDIR)$(prefix)/share/pixmaps/bsnes.png
rm $(DESTDIR)$(prefix)/share/applications/bsnes.desktop
endif

View File

@ -37,6 +37,7 @@ Configuration::Configuration() {
//internal
//========
attach(system.profile = "", "system.profile");
attach(system.video = "", "system.video");
attach(system.audio = "", "system.audio");
attach(system.input = "", "system.input");

View File

@ -1,6 +1,7 @@
class Configuration : public configuration {
public:
struct System {
string profile;
string video, audio, input;
bool crashedOnLastRun;
unsigned speed;

Binary file not shown.

After

Width:  |  Height:  |  Size: 629 B

View File

@ -17,6 +17,7 @@
<file alias="16x16/appointment-new.png">../data/icons-16x16/appointment-new.png</file>
<file alias="16x16/audio-volume-high.png">../data/icons-16x16/audio-volume-high.png</file>
<file alias="16x16/document-open.png">../data/icons-16x16/document-open.png</file>
<file alias="16x16/emblem-system.png">../data/icons-16x16/emblem-system.png</file>
<file alias="16x16/folder.png">../data/icons-16x16/folder.png</file>
<file alias="16x16/folder-new.png">../data/icons-16x16/folder-new.png</file>
<file alias="16x16/go-up.png">../data/icons-16x16/go-up.png</file>

92
qt/settings/profile.cpp Executable file
View File

@ -0,0 +1,92 @@
#include "profile.moc"
ProfileSettingsWindow *profileSettingsWindow;
ProfileSettingsWindow::ProfileSettingsWindow() {
layout = new QVBoxLayout;
layout->setMargin(Style::WindowMargin);
layout->setSpacing(0);
layout->setAlignment(Qt::AlignTop);
setLayout(layout);
profileInfo = new QLabel(
"Profiles allow you to balance emulation accuracy against system performance.<br>"
"Note that you must restart bsnes for profile changes to take effect!<br>"
"Also, while save RAM is compatible between profiles, save states are not cross-compatible."
);
layout->addWidget(profileInfo);
layout->addSpacing(Style::WidgetSpacing);
profileResearch = new QRadioButton("Research");
profileResearch->setStyleSheet("font-weight: bold; font-size: 12pt;");
layout->addWidget(profileResearch);
profileResearchInfo = new QLabel(
"<b>System Requirements:</b> A super-computer cooled by LN<sub>2</sub>.<br>"
"Maximum accuracy, no matter the cost.<br>"
"Use this mode for development purposes only."
);
profileResearchInfo->setStyleSheet("margin-left: 22px;");
layout->addWidget(profileResearchInfo);
layout->addSpacing(Style::WidgetSpacing);
profileBaseline = new QRadioButton("Baseline (recommended)");
profileBaseline->setStyleSheet("font-weight: bold; font-size: 12pt;");
layout->addWidget(profileBaseline);
profileBaselineInfo = new QLabel(
"<b>System Requirements:</b> Intel Core Solo or AMD Athlon 64 processor.<br>"
"Extreme accuracy with reasonable hardware requirements in mind.<br>"
"Very rarely, slight graphical glitches may appear."
);
profileBaselineInfo->setStyleSheet("margin-left: 22px;");
layout->addWidget(profileBaselineInfo);
layout->addSpacing(Style::WidgetSpacing);
profilePerformance = new QRadioButton("Performance");
profilePerformance->setStyleSheet("font-weight: bold; font-size: 12pt;");
layout->addWidget(profilePerformance);
profilePerformanceInfo = new QLabel(
"<b>System Requirements:</b> Intel Atom, Intel Pentium IV or AMD Athlon processor.<br>"
"High accuracy with reasonable sacrifices for performance.<br>"
"Sacrifices a small degree of compatibility to run full-speed on older hardware.<br>"
"Use this mode only if baseline is too slow, or if you are running on battery power."
);
profilePerformanceInfo->setStyleSheet("margin-left: 22px;");
layout->addWidget(profilePerformanceInfo);
if(config().system.profile == "research") {
profileResearch->setChecked(true);
} else if(config().system.profile == "baseline") {
profileBaseline->setChecked(true);
} else if(config().system.profile == "performance") {
profilePerformance->setChecked(true);
} else {
config().system.profile = "baseline";
profileBaseline->setChecked(true);
QMessageBox::information(0, "First-Run Notice",
"<b>Note:</b> bsnes contains multiple emulation profiles.<br><br>"
"If bsnes runs too slowly, you can double the speed by using the "
"'Performance' profile; or if you want even more accuracy, you can use the "
"'Research' profile.<br><br>"
"Feel free to experiment. You can select different profiles via:<br>"
"Settings -> Configuration -> Profile"
);
}
connect(profileResearch, SIGNAL(pressed()), this, SLOT(setResearchProfile()));
connect(profileBaseline, SIGNAL(pressed()), this, SLOT(setBaselineProfile()));
connect(profilePerformance, SIGNAL(pressed()), this, SLOT(setPerformanceProfile()));
}
void ProfileSettingsWindow::setResearchProfile() {
config().system.profile = "research";
}
void ProfileSettingsWindow::setBaselineProfile() {
config().system.profile = "baseline";
}
void ProfileSettingsWindow::setPerformanceProfile() {
config().system.profile = "performance";
}

22
qt/settings/profile.moc.hpp Executable file
View File

@ -0,0 +1,22 @@
class ProfileSettingsWindow : public QWidget {
Q_OBJECT
public:
QVBoxLayout *layout;
QLabel *profileInfo;
QRadioButton *profileResearch;
QLabel *profileResearchInfo;
QRadioButton *profileBaseline;
QLabel *profileBaselineInfo;
QRadioButton *profilePerformance;
QLabel *profilePerformanceInfo;
ProfileSettingsWindow();
private slots:
void setResearchProfile();
void setBaselineProfile();
void setPerformanceProfile();
};
extern ProfileSettingsWindow *profileSettingsWindow;

View File

@ -1,5 +1,6 @@
#include "../ui-base.hpp"
#include "profile.cpp"
#include "video.cpp"
#include "audio.cpp"
#include "input.cpp"
@ -21,12 +22,18 @@ SettingsWindow::SettingsWindow() {
layout->setSpacing(Style::WidgetSpacing);
setLayout(layout);
profileSettingsWindow = new ProfileSettingsWindow;
videoSettingsWindow = new VideoSettingsWindow;
audioSettingsWindow = new AudioSettingsWindow;
inputSettingsWindow = new InputSettingsWindow;
pathSettingsWindow = new PathSettingsWindow;
advancedSettingsWindow = new AdvancedSettingsWindow;
profileArea = new QScrollArea;
profileArea->setWidget(profileSettingsWindow);
profileArea->setFrameStyle(0);
profileArea->setWidgetResizable(true);
videoArea = new QScrollArea;
videoArea->setWidget(videoSettingsWindow);
videoArea->setFrameStyle(0);
@ -53,6 +60,7 @@ SettingsWindow::SettingsWindow() {
advancedArea->setWidgetResizable(true);
tab = new QTabWidget;
tab->addTab(profileArea, QIcon(":/16x16/emblem-system.png"), "Profile");
tab->addTab(videoArea, QIcon(":/16x16/video-display.png"), "Video");
tab->addTab(audioArea, QIcon(":/16x16/audio-volume-high.png"), "Audio");
tab->addTab(inputArea, QIcon(":/16x16/input-gaming.png"), "Input");

View File

@ -4,6 +4,7 @@ class SettingsWindow : public Window {
public:
QVBoxLayout *layout;
QTabWidget *tab;
QScrollArea *profileArea;
QScrollArea *videoArea;
QScrollArea *audioArea;
QScrollArea *inputArea;

View File

@ -63,6 +63,7 @@ using namespace ruby;
#include "movie/movie.hpp"
#include "settings/settings.moc.hpp"
#include "settings/profile.moc.hpp"
#include "settings/video.moc.hpp"
#include "settings/audio.moc.hpp"
#include "settings/input.moc.hpp"

View File

@ -10,22 +10,22 @@ snes_objects += snes-obc1 snes-st0010 snes-st0011 snes-st0018
snes_objects += snes-msu1 snes-serial
objects += $(snes_objects)
ifeq ($(profile),asnes)
flags += -DPROFILE_ASNES
ifeq ($(profile),research)
flags += -DPROFILE_RESEARCH
snescpu := $(snes)/cpu
snessmp := $(snes)/smp
snesdsp := $(snes)/dsp
snesppu := $(snes)/ppu
else ifeq ($(profile),bsnes)
flags += -DPROFILE_BSNES
else ifeq ($(profile),baseline)
flags += -DPROFILE_BASELINE
snescpu := $(snes)/cpu
snessmp := $(snes)/smp
snesdsp := $(snes)/fast/dsp
snesppu := $(snes)/fast/ppu
else ifeq ($(profile),csnes)
flags += -DPROFILE_CSNES
else ifeq ($(profile),performance)
flags += -DPROFILE_PERFORMANCE
snescpu := $(snes)/fast/cpu
snessmp := $(snes)/fast/smp
snessmp := $(snes)/smp
snesdsp := $(snes)/fast/dsp
snesppu := $(snes)/fast/ppu
endif
@ -37,10 +37,10 @@ obj/snes-system.o : $(snes)/system/system.cpp $(call rwildcard,$(snes)/system/
obj/snes-memory.o : $(snes)/memory/memory.cpp $(call rwildcard,$(snes)/memory/)
obj/snes-cpucore.o : $(snes)/cpu/core/core.cpp $(call rwildcard,$(snes)/cpu/core/)
obj/snes-smpcore.o : $(snes)/smp/core/core.cpp $(call rwildcard,$(snes)/smp/core/)
obj/snes-cpu.o : $(snescpu)/cpu.cpp $(call rwildcard,$(snescpu)/cpu/)
obj/snes-smp.o : $(snessmp)/smp.cpp $(call rwildcard,$(snessmp)/smp/)
obj/snes-dsp.o : $(snesdsp)/dsp.cpp $(call rwildcard,$(snesdsp)/dsp/)
obj/snes-ppu.o : $(snesppu)/ppu.cpp $(call rwildcard,$(snesppu)/ppu/)
obj/snes-cpu.o : $(snescpu)/cpu.cpp $(call rwildcard,$(snescpu)/)
obj/snes-smp.o : $(snessmp)/smp.cpp $(call rwildcard,$(snessmp)/)
obj/snes-dsp.o : $(snesdsp)/dsp.cpp $(call rwildcard,$(snesdsp)/)
obj/snes-ppu.o : $(snesppu)/ppu.cpp $(call rwildcard,$(snesppu)/)
obj/snes-cartridge.o: $(snes)/cartridge/cartridge.cpp $(call rwilddcard,$(snes)/cartridge/)
obj/snes-cheat.o : $(snes)/cheat/cheat.cpp $(call rwildcard,$(snes)/cheat/)

View File

@ -48,6 +48,7 @@ void Cx4::op10() {
r4 = r0 & 0x1ff;
if(r1 & 0x8000)r1 |= ~0x7fff;
else r1 &= 0x7fff;
mul(cos(r4), r1, r5, r2);
r5 = (r5 >> 16) & 0xff;

View File

@ -26,11 +26,19 @@ void CPU::step(unsigned clocks) {
}
void CPU::synchronize_smp() {
if(smp.clock < 0) co_switch(smp.thread);
if(SMP::Threaded == true) {
if(smp.clock < 0) co_switch(smp.thread);
} else {
while(smp.clock < 0) smp.enter();
}
}
void CPU::synchronize_ppu() {
if(ppu.clock < 0) co_switch(ppu.thread);
if(PPU::Threaded == true) {
if(ppu.clock < 0) co_switch(ppu.thread);
} else {
while(ppu.clock < 0) ppu.enter();
}
}
void CPU::synchronize_coprocessor() {

View File

@ -1,5 +1,6 @@
class CPU : public Processor, public CPUcore, public PPUcounter, public MMIO {
public:
enum : bool { Threaded = true };
array<Processor*> coprocessors;
alwaysinline void step(unsigned clocks);
alwaysinline void synchronize_smp();
@ -12,6 +13,7 @@ public:
alwaysinline uint8 port_read(uint8 port) { return apu_port[port & 3]; }
alwaysinline void port_write(uint8 port, uint8 data) { apu_port[port & 3] = data; }
void enter();
void power();
void reset();
@ -117,7 +119,6 @@ private:
} alu;
static void Enter();
void enter();
void op_irq();
debugvirtual void op_step();

View File

@ -30,7 +30,11 @@ void DSP::step(unsigned clocks) {
}
void DSP::synchronize_smp() {
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(smp.thread);
if(SMP::Threaded == true) {
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(smp.thread);
} else {
while(clock >= 0) smp.enter();
}
}
void DSP::Enter() { dsp.enter(); }

View File

@ -1,11 +1,13 @@
class DSP : public Processor {
public:
enum : bool { Threaded = true };
alwaysinline void step(unsigned clocks);
alwaysinline void synchronize_smp();
uint8 read(uint8 addr);
void write(uint8 addr, uint8 data);
void enter();
void power();
void reset();
@ -165,7 +167,6 @@ private:
//dsp
static void Enter();
void enter();
void tick();
friend class DSPDebugger;

View File

@ -1,331 +0,0 @@
#ifdef CPUCORE_CPP
inline void CPUcore::op_adc_b() {
int result;
if(!regs.p.d) {
result = regs.a.l + rd.l + regs.p.c;
} else {
result = (regs.a.l & 0x0f) + (rd.l & 0x0f) + (regs.p.c << 0);
if(result > 0x09) result += 0x06;
regs.p.c = result > 0x0f;
result = (regs.a.l & 0xf0) + (rd.l & 0xf0) + (regs.p.c << 4) + (result & 0x0f);
}
regs.p.v = ~(regs.a.l ^ rd.l) & (regs.a.l ^ result) & 0x80;
if(regs.p.d && result > 0x9f) result += 0x60;
regs.p.c = result > 0xff;
regs.p.n = result & 0x80;
regs.p.z = (uint8_t)result == 0;
regs.a.l = result;
}
inline void CPUcore::op_adc_w() {
int result;
if(!regs.p.d) {
result = regs.a.w + rd.w + regs.p.c;
} else {
result = (regs.a.w & 0x000f) + (rd.w & 0x000f) + (regs.p.c << 0);
if(result > 0x0009) result += 0x0006;
regs.p.c = result > 0x000f;
result = (regs.a.w & 0x00f0) + (rd.w & 0x00f0) + (regs.p.c << 4) + (result & 0x000f);
if(result > 0x009f) result += 0x0060;
regs.p.c = result > 0x00ff;
result = (regs.a.w & 0x0f00) + (rd.w & 0x0f00) + (regs.p.c << 8) + (result & 0x00ff);
if(result > 0x09ff) result += 0x0600;
regs.p.c = result > 0x0fff;
result = (regs.a.w & 0xf000) + (rd.w & 0xf000) + (regs.p.c << 12) + (result & 0x0fff);
}
regs.p.v = ~(regs.a.w ^ rd.w) & (regs.a.w ^ result) & 0x8000;
if(regs.p.d && result > 0x9fff) result += 0x6000;
regs.p.c = result > 0xffff;
regs.p.n = result & 0x8000;
regs.p.z = (uint16_t)result == 0;
regs.a.w = result;
}
inline void CPUcore::op_and_b() {
regs.a.l &= rd.l;
regs.p.n = regs.a.l & 0x80;
regs.p.z = regs.a.l == 0;
}
inline void CPUcore::op_and_w() {
regs.a.w &= rd.w;
regs.p.n = regs.a.w & 0x8000;
regs.p.z = regs.a.w == 0;
}
inline void CPUcore::op_bit_b() {
regs.p.n = rd.l & 0x80;
regs.p.v = rd.l & 0x40;
regs.p.z = (rd.l & regs.a.l) == 0;
}
inline void CPUcore::op_bit_w() {
regs.p.n = rd.w & 0x8000;
regs.p.v = rd.w & 0x4000;
regs.p.z = (rd.w & regs.a.w) == 0;
}
inline void CPUcore::op_cmp_b() {
int r = regs.a.l - rd.l;
regs.p.n = r & 0x80;
regs.p.z = (uint8)r == 0;
regs.p.c = r >= 0;
}
inline void CPUcore::op_cmp_w() {
int r = regs.a.w - rd.w;
regs.p.n = r & 0x8000;
regs.p.z = (uint16)r == 0;
regs.p.c = r >= 0;
}
inline void CPUcore::op_cpx_b() {
int r = regs.x.l - rd.l;
regs.p.n = r & 0x80;
regs.p.z = (uint8)r == 0;
regs.p.c = r >= 0;
}
inline void CPUcore::op_cpx_w() {
int r = regs.x.w - rd.w;
regs.p.n = r & 0x8000;
regs.p.z = (uint16)r == 0;
regs.p.c = r >= 0;
}
inline void CPUcore::op_cpy_b() {
int r = regs.y.l - rd.l;
regs.p.n = r & 0x80;
regs.p.z = (uint8)r == 0;
regs.p.c = r >= 0;
}
inline void CPUcore::op_cpy_w() {
int r = regs.y.w - rd.w;
regs.p.n = r & 0x8000;
regs.p.z = (uint16)r == 0;
regs.p.c = r >= 0;
}
inline void CPUcore::op_eor_b() {
regs.a.l ^= rd.l;
regs.p.n = regs.a.l & 0x80;
regs.p.z = regs.a.l == 0;
}
inline void CPUcore::op_eor_w() {
regs.a.w ^= rd.w;
regs.p.n = regs.a.w & 0x8000;
regs.p.z = regs.a.w == 0;
}
inline void CPUcore::op_lda_b() {
regs.a.l = rd.l;
regs.p.n = regs.a.l & 0x80;
regs.p.z = regs.a.l == 0;
}
inline void CPUcore::op_lda_w() {
regs.a.w = rd.w;
regs.p.n = regs.a.w & 0x8000;
regs.p.z = regs.a.w == 0;
}
inline void CPUcore::op_ldx_b() {
regs.x.l = rd.l;
regs.p.n = regs.x.l & 0x80;
regs.p.z = regs.x.l == 0;
}
inline void CPUcore::op_ldx_w() {
regs.x.w = rd.w;
regs.p.n = regs.x.w & 0x8000;
regs.p.z = regs.x.w == 0;
}
inline void CPUcore::op_ldy_b() {
regs.y.l = rd.l;
regs.p.n = regs.y.l & 0x80;
regs.p.z = regs.y.l == 0;
}
inline void CPUcore::op_ldy_w() {
regs.y.w = rd.w;
regs.p.n = regs.y.w & 0x8000;
regs.p.z = regs.y.w == 0;
}
inline void CPUcore::op_ora_b() {
regs.a.l |= rd.l;
regs.p.n = regs.a.l & 0x80;
regs.p.z = regs.a.l == 0;
}
inline void CPUcore::op_ora_w() {
regs.a.w |= rd.w;
regs.p.n = regs.a.w & 0x8000;
regs.p.z = regs.a.w == 0;
}
inline void CPUcore::op_sbc_b() {
int result;
rd.l ^= 0xff;
if(!regs.p.d) {
result = regs.a.l + rd.l + regs.p.c;
} else {
result = (regs.a.l & 0x0f) + (rd.l & 0x0f) + (regs.p.c << 0);
if(result <= 0x0f) result -= 0x06;
regs.p.c = result > 0x0f;
result = (regs.a.l & 0xf0) + (rd.l & 0xf0) + (regs.p.c << 4) + (result & 0x0f);
}
regs.p.v = ~(regs.a.l ^ rd.l) & (regs.a.l ^ result) & 0x80;
if(regs.p.d && result <= 0xff) result -= 0x60;
regs.p.c = result > 0xff;
regs.p.n = result & 0x80;
regs.p.z = (uint8_t)result == 0;
regs.a.l = result;
}
inline void CPUcore::op_sbc_w() {
int result;
rd.w ^= 0xffff;
if(!regs.p.d) {
result = regs.a.w + rd.w + regs.p.c;
} else {
result = (regs.a.w & 0x000f) + (rd.w & 0x000f) + (regs.p.c << 0);
if(result <= 0x000f) result -= 0x0006;
regs.p.c = result > 0x000f;
result = (regs.a.w & 0x00f0) + (rd.w & 0x00f0) + (regs.p.c << 4) + (result & 0x000f);
if(result <= 0x00ff) result -= 0x0060;
regs.p.c = result > 0x00ff;
result = (regs.a.w & 0x0f00) + (rd.w & 0x0f00) + (regs.p.c << 8) + (result & 0x00ff);
if(result <= 0x0fff) result -= 0x0600;
regs.p.c = result > 0x0fff;
result = (regs.a.w & 0xf000) + (rd.w & 0xf000) + (regs.p.c << 12) + (result & 0x0fff);
}
regs.p.v = ~(regs.a.w ^ rd.w) & (regs.a.w ^ result) & 0x8000;
if(regs.p.d && result <= 0xffff) result -= 0x6000;
regs.p.c = result > 0xffff;
regs.p.n = result & 0x8000;
regs.p.z = (uint16_t)result == 0;
regs.a.w = result;
}
inline void CPUcore::op_inc_b() {
rd.l++;
regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0;
}
inline void CPUcore::op_inc_w() {
rd.w++;
regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0;
}
inline void CPUcore::op_dec_b() {
rd.l--;
regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0;
}
inline void CPUcore::op_dec_w() {
rd.w--;
regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0;
}
inline void CPUcore::op_asl_b() {
regs.p.c = rd.l & 0x80;
rd.l <<= 1;
regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0;
}
inline void CPUcore::op_asl_w() {
regs.p.c = rd.w & 0x8000;
rd.w <<= 1;
regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0;
}
inline void CPUcore::op_lsr_b() {
regs.p.c = rd.l & 1;
rd.l >>= 1;
regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0;
}
inline void CPUcore::op_lsr_w() {
regs.p.c = rd.w & 1;
rd.w >>= 1;
regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0;
}
inline void CPUcore::op_rol_b() {
unsigned carry = (unsigned)regs.p.c;
regs.p.c = rd.l & 0x80;
rd.l = (rd.l << 1) | carry;
regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0;
}
inline void CPUcore::op_rol_w() {
unsigned carry = (unsigned)regs.p.c;
regs.p.c = rd.w & 0x8000;
rd.w = (rd.w << 1) | carry;
regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0;
}
inline void CPUcore::op_ror_b() {
unsigned carry = (unsigned)regs.p.c << 7;
regs.p.c = rd.l & 1;
rd.l = carry | (rd.l >> 1);
regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0;
}
inline void CPUcore::op_ror_w() {
unsigned carry = (unsigned)regs.p.c << 15;
regs.p.c = rd.w & 1;
rd.w = carry | (rd.w >> 1);
regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0;
}
inline void CPUcore::op_trb_b() {
regs.p.z = (rd.l & regs.a.l) == 0;
rd.l &= ~regs.a.l;
}
inline void CPUcore::op_trb_w() {
regs.p.z = (rd.w & regs.a.w) == 0;
rd.w &= ~regs.a.w;
}
inline void CPUcore::op_tsb_b() {
regs.p.z = (rd.l & regs.a.l) == 0;
rd.l |= regs.a.l;
}
inline void CPUcore::op_tsb_w() {
regs.p.z = (rd.w & regs.a.w) == 0;
rd.w |= regs.a.w;
}
#endif

View File

@ -1,74 +0,0 @@
#include <snes.hpp>
#define CPUCORE_CPP
namespace SNES {
#include "serialization.cpp"
#include "algorithms.cpp"
#include "disassembler/disassembler.cpp"
#define L last_cycle();
#define A 0
#define X 1
#define Y 2
#define Z 3
#define S 4
#define D 5
#define call(op) (this->*op)()
#include "opcode_read.cpp"
#include "opcode_write.cpp"
#include "opcode_rmw.cpp"
#include "opcode_pc.cpp"
#include "opcode_misc.cpp"
#include "table.cpp"
#undef L
#undef A
#undef X
#undef Y
#undef Z
#undef S
#undef D
#undef call
//immediate, 2-cycle opcodes with I/O cycle will become bus read
//when an IRQ is to be triggered immediately after opcode completion.
//this affects the following opcodes:
// clc, cld, cli, clv, sec, sed, sei,
// tax, tay, txa, txy, tya, tyx,
// tcd, tcs, tdc, tsc, tsx, txs,
// inc, inx, iny, dec, dex, dey,
// asl, lsr, rol, ror, nop, xce.
alwaysinline void CPUcore::op_io_irq() {
if(interrupt_pending()) {
//modify I/O cycle to bus read cycle, do not increment PC
op_read(regs.pc.d);
} else {
op_io();
}
}
alwaysinline void CPUcore::op_io_cond2() {
if(regs.d.l != 0x00) {
op_io();
}
}
alwaysinline void CPUcore::op_io_cond4(uint16 x, uint16 y) {
if(!regs.p.x || (x & 0xff00) != (y & 0xff00)) {
op_io();
}
}
alwaysinline void CPUcore::op_io_cond6(uint16 addr) {
if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) {
op_io();
}
}
CPUcore::CPUcore() {
initialize_opcode_table();
}
}

View File

@ -1,217 +0,0 @@
class CPUcore {
public:
#include "registers.hpp"
#include "memory.hpp"
#include "disassembler/disassembler.hpp"
regs_t regs;
reg24_t aa, rd;
uint8_t sp, dp;
virtual void op_io() = 0;
virtual uint8_t op_read(uint32_t addr) = 0;
virtual void op_write(uint32_t addr, uint8_t data) = 0;
virtual void last_cycle() = 0;
virtual bool interrupt_pending() = 0;
void op_io_irq();
void op_io_cond2();
void op_io_cond4(uint16 x, uint16 y);
void op_io_cond6(uint16 addr);
void op_adc_b();
void op_adc_w();
void op_and_b();
void op_and_w();
void op_bit_b();
void op_bit_w();
void op_cmp_b();
void op_cmp_w();
void op_cpx_b();
void op_cpx_w();
void op_cpy_b();
void op_cpy_w();
void op_eor_b();
void op_eor_w();
void op_lda_b();
void op_lda_w();
void op_ldx_b();
void op_ldx_w();
void op_ldy_b();
void op_ldy_w();
void op_ora_b();
void op_ora_w();
void op_sbc_b();
void op_sbc_w();
void op_inc_b();
void op_inc_w();
void op_dec_b();
void op_dec_w();
void op_asl_b();
void op_asl_w();
void op_lsr_b();
void op_lsr_w();
void op_rol_b();
void op_rol_w();
void op_ror_b();
void op_ror_w();
void op_trb_b();
void op_trb_w();
void op_tsb_b();
void op_tsb_w();
template<void (CPUcore::*)()> void op_read_const_b();
template<void (CPUcore::*)()> void op_read_const_w();
void op_read_bit_const_b();
void op_read_bit_const_w();
template<void (CPUcore::*)()> void op_read_addr_b();
template<void (CPUcore::*)()> void op_read_addr_w();
template<void (CPUcore::*)()> void op_read_addrx_b();
template<void (CPUcore::*)()> void op_read_addrx_w();
template<void (CPUcore::*)()> void op_read_addry_b();
template<void (CPUcore::*)()> void op_read_addry_w();
template<void (CPUcore::*)()> void op_read_long_b();
template<void (CPUcore::*)()> void op_read_long_w();
template<void (CPUcore::*)()> void op_read_longx_b();
template<void (CPUcore::*)()> void op_read_longx_w();
template<void (CPUcore::*)()> void op_read_dp_b();
template<void (CPUcore::*)()> void op_read_dp_w();
template<void (CPUcore::*)(), int> void op_read_dpr_b();
template<void (CPUcore::*)(), int> void op_read_dpr_w();
template<void (CPUcore::*)()> void op_read_idp_b();
template<void (CPUcore::*)()> void op_read_idp_w();
template<void (CPUcore::*)()> void op_read_idpx_b();
template<void (CPUcore::*)()> void op_read_idpx_w();
template<void (CPUcore::*)()> void op_read_idpy_b();
template<void (CPUcore::*)()> void op_read_idpy_w();
template<void (CPUcore::*)()> void op_read_ildp_b();
template<void (CPUcore::*)()> void op_read_ildp_w();
template<void (CPUcore::*)()> void op_read_ildpy_b();
template<void (CPUcore::*)()> void op_read_ildpy_w();
template<void (CPUcore::*)()> void op_read_sr_b();
template<void (CPUcore::*)()> void op_read_sr_w();
template<void (CPUcore::*)()> void op_read_isry_b();
template<void (CPUcore::*)()> void op_read_isry_w();
template<int> void op_write_addr_b();
template<int> void op_write_addr_w();
template<int, int> void op_write_addrr_b();
template<int, int> void op_write_addrr_w();
template<int> void op_write_longr_b();
template<int> void op_write_longr_w();
template<int> void op_write_dp_b();
template<int> void op_write_dp_w();
template<int, int> void op_write_dpr_b();
template<int, int> void op_write_dpr_w();
void op_sta_idp_b();
void op_sta_idp_w();
void op_sta_ildp_b();
void op_sta_ildp_w();
void op_sta_idpx_b();
void op_sta_idpx_w();
void op_sta_idpy_b();
void op_sta_idpy_w();
void op_sta_ildpy_b();
void op_sta_ildpy_w();
void op_sta_sr_b();
void op_sta_sr_w();
void op_sta_isry_b();
void op_sta_isry_w();
template<int, int> void op_adjust_imm_b();
template<int, int> void op_adjust_imm_w();
void op_asl_imm_b();
void op_asl_imm_w();
void op_lsr_imm_b();
void op_lsr_imm_w();
void op_rol_imm_b();
void op_rol_imm_w();
void op_ror_imm_b();
void op_ror_imm_w();
template<void (CPUcore::*)()> void op_adjust_addr_b();
template<void (CPUcore::*)()> void op_adjust_addr_w();
template<void (CPUcore::*)()> void op_adjust_addrx_b();
template<void (CPUcore::*)()> void op_adjust_addrx_w();
template<void (CPUcore::*)()> void op_adjust_dp_b();
template<void (CPUcore::*)()> void op_adjust_dp_w();
template<void (CPUcore::*)()> void op_adjust_dpx_b();
template<void (CPUcore::*)()> void op_adjust_dpx_w();
template<int, int> void op_branch();
void op_bra();
void op_brl();
void op_jmp_addr();
void op_jmp_long();
void op_jmp_iaddr();
void op_jmp_iaddrx();
void op_jmp_iladdr();
void op_jsr_addr();
void op_jsr_long_e();
void op_jsr_long_n();
void op_jsr_iaddrx_e();
void op_jsr_iaddrx_n();
void op_rti_e();
void op_rti_n();
void op_rts();
void op_rtl_e();
void op_rtl_n();
void op_nop();
void op_wdm();
void op_xba();
template<int> void op_move_b();
template<int> void op_move_w();
template<int, int> void op_interrupt_e();
template<int, int> void op_interrupt_n();
void op_stp();
void op_wai();
void op_xce();
template<int, int> void op_flag();
template<int> void op_pflag_e();
template<int> void op_pflag_n();
template<int, int> void op_transfer_b();
template<int, int> void op_transfer_w();
void op_tcs_e();
void op_tcs_n();
void op_tsx_b();
void op_tsx_w();
void op_txs_e();
void op_txs_n();
template<int> void op_push_b();
template<int> void op_push_w();
void op_phd_e();
void op_phd_n();
void op_phb();
void op_phk();
void op_php();
template<int> void op_pull_b();
template<int> void op_pull_w();
void op_pld_e();
void op_pld_n();
void op_plb();
void op_plp_e();
void op_plp_n();
void op_pea_e();
void op_pea_n();
void op_pei_e();
void op_pei_n();
void op_per_e();
void op_per_n();
void (CPUcore::**opcode_table)();
void (CPUcore::*op_table[256 * 5])();
void initialize_opcode_table();
void update_table();
enum {
table_EM = 0, // 8-bit accumulator, 8-bit index (emulation mode)
table_MX = 256, // 8-bit accumulator, 8-bit index
table_Mx = 512, // 8-bit accumulator, 16-bit index
table_mX = 768, //16-bit accumulator, 8-bit index
table_mx = 1024, //16-bit accumulator, 16-bit index
};
void core_serialize(serializer&);
CPUcore();
};

View File

@ -1,483 +0,0 @@
#ifdef CPUCORE_CPP
uint8 CPUcore::dreadb(uint32 addr) {
if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) {
//$[00-3f|80-bf]:[2000-5fff]
//do not read MMIO registers within debugger
return 0x00;
}
return bus.read(addr);
}
uint16 CPUcore::dreadw(uint32 addr) {
uint16 r;
r = dreadb((addr + 0) & 0xffffff) << 0;
r |= dreadb((addr + 1) & 0xffffff) << 8;
return r;
}
uint32 CPUcore::dreadl(uint32 addr) {
uint32 r;
r = dreadb((addr + 0) & 0xffffff) << 0;
r |= dreadb((addr + 1) & 0xffffff) << 8;
r |= dreadb((addr + 2) & 0xffffff) << 16;
return r;
}
uint32 CPUcore::decode(uint8 offset_type, uint32 addr) {
uint32 r = 0;
switch(offset_type) {
case OPTYPE_DP:
r = (regs.d + (addr & 0xffff)) & 0xffff;
break;
case OPTYPE_DPX:
r = (regs.d + regs.x + (addr & 0xffff)) & 0xffff;
break;
case OPTYPE_DPY:
r = (regs.d + regs.y + (addr & 0xffff)) & 0xffff;
break;
case OPTYPE_IDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr);
break;
case OPTYPE_IDPX:
addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr);
break;
case OPTYPE_IDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr) + regs.y;
break;
case OPTYPE_ILDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = dreadl(addr);
break;
case OPTYPE_ILDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = dreadl(addr) + regs.y;
break;
case OPTYPE_ADDR:
r = (regs.db << 16) + (addr & 0xffff);
break;
case OPTYPE_ADDR_PC:
r = (regs.pc.b << 16) + (addr & 0xffff);
break;
case OPTYPE_ADDRX:
r = (regs.db << 16) + (addr & 0xffff) + regs.x;
break;
case OPTYPE_ADDRY:
r = (regs.db << 16) + (addr & 0xffff) + regs.y;
break;
case OPTYPE_IADDR_PC:
r = (regs.pc.b << 16) + (addr & 0xffff);
break;
case OPTYPE_IADDRX:
r = (regs.pc.b << 16) + ((addr + regs.x) & 0xffff);
break;
case OPTYPE_ILADDR:
r = addr;
break;
case OPTYPE_LONG:
r = addr;
break;
case OPTYPE_LONGX:
r = (addr + regs.x);
break;
case OPTYPE_SR:
r = (regs.s + (addr & 0xff)) & 0xffff;
break;
case OPTYPE_ISRY:
addr = (regs.s + (addr & 0xff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr) + regs.y;
break;
case OPTYPE_RELB:
r = (regs.pc.b << 16) + ((regs.pc.w + 2) & 0xffff);
r += int8(addr);
break;
case OPTYPE_RELW:
r = (regs.pc.b << 16) + ((regs.pc.w + 3) & 0xffff);
r += int16(addr);
break;
}
return(r & 0xffffff);
}
void CPUcore::disassemble_opcode(char *output, uint32 addr) {
static reg24_t pc;
char t[256];
char *s = output;
if(false /* in_opcode() == true */) {
strcpy(s, "?????? <CPU within opcode>");
return;
}
pc.d = addr;
sprintf(s, "%.6x ", (uint32)pc.d);
uint8 op = dreadb(pc.d); pc.w++;
uint8 op0 = dreadb(pc.d); pc.w++;
uint8 op1 = dreadb(pc.d); pc.w++;
uint8 op2 = dreadb(pc.d);
#define op8 ((op0))
#define op16 ((op0) | (op1 << 8))
#define op24 ((op0) | (op1 << 8) | (op2 << 16))
#define a8 (regs.e || regs.p.m)
#define x8 (regs.e || regs.p.x)
switch(op) {
case 0x00: sprintf(t, "brk #$%.2x ", op8); break;
case 0x01: sprintf(t, "ora ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x02: sprintf(t, "cop #$%.2x ", op8); break;
case 0x03: sprintf(t, "ora $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x04: sprintf(t, "tsb $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x05: sprintf(t, "ora $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x06: sprintf(t, "asl $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x07: sprintf(t, "ora [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x08: sprintf(t, "php "); break;
case 0x09: if(a8)sprintf(t, "ora #$%.2x ", op8);
else sprintf(t, "ora #$%.4x ", op16); break;
case 0x0a: sprintf(t, "asl a "); break;
case 0x0b: sprintf(t, "phd "); break;
case 0x0c: sprintf(t, "tsb $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0d: sprintf(t, "ora $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0e: sprintf(t, "asl $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0f: sprintf(t, "ora $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x10: sprintf(t, "bpl $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x11: sprintf(t, "ora ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x12: sprintf(t, "ora ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x13: sprintf(t, "ora ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x14: sprintf(t, "trb $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x15: sprintf(t, "ora $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x16: sprintf(t, "asl $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x17: sprintf(t, "ora [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x18: sprintf(t, "clc "); break;
case 0x19: sprintf(t, "ora $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x1a: sprintf(t, "inc "); break;
case 0x1b: sprintf(t, "tcs "); break;
case 0x1c: sprintf(t, "trb $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x1d: sprintf(t, "ora $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x1e: sprintf(t, "asl $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x1f: sprintf(t, "ora $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x20: sprintf(t, "jsr $%.4x [%.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break;
case 0x21: sprintf(t, "and ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x22: sprintf(t, "jsl $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x23: sprintf(t, "and $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x24: sprintf(t, "bit $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x25: sprintf(t, "and $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x26: sprintf(t, "rol $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x27: sprintf(t, "and [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x28: sprintf(t, "plp "); break;
case 0x29: if(a8)sprintf(t, "and #$%.2x ", op8);
else sprintf(t, "and #$%.4x ", op16); break;
case 0x2a: sprintf(t, "rol a "); break;
case 0x2b: sprintf(t, "pld "); break;
case 0x2c: sprintf(t, "bit $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2d: sprintf(t, "and $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2e: sprintf(t, "rol $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2f: sprintf(t, "and $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x30: sprintf(t, "bmi $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x31: sprintf(t, "and ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x32: sprintf(t, "and ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x33: sprintf(t, "and ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x34: sprintf(t, "bit $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x35: sprintf(t, "and $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x36: sprintf(t, "rol $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x37: sprintf(t, "and [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x38: sprintf(t, "sec "); break;
case 0x39: sprintf(t, "and $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x3a: sprintf(t, "dec "); break;
case 0x3b: sprintf(t, "tsc "); break;
case 0x3c: sprintf(t, "bit $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3d: sprintf(t, "and $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3e: sprintf(t, "rol $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3f: sprintf(t, "and $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x40: sprintf(t, "rti "); break;
case 0x41: sprintf(t, "eor ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x42: sprintf(t, "wdm "); break;
case 0x43: sprintf(t, "eor $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x44: sprintf(t, "mvp $%.2x,$%.2x ", op1, op8); break;
case 0x45: sprintf(t, "eor $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x46: sprintf(t, "lsr $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x47: sprintf(t, "eor [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x48: sprintf(t, "pha "); break;
case 0x49: if(a8)sprintf(t, "eor #$%.2x ", op8);
else sprintf(t, "eor #$%.4x ", op16); break;
case 0x4a: sprintf(t, "lsr a "); break;
case 0x4b: sprintf(t, "phk "); break;
case 0x4c: sprintf(t, "jmp $%.4x [%.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break;
case 0x4d: sprintf(t, "eor $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x4e: sprintf(t, "lsr $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x4f: sprintf(t, "eor $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x50: sprintf(t, "bvc $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x51: sprintf(t, "eor ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x52: sprintf(t, "eor ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x53: sprintf(t, "eor ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x54: sprintf(t, "mvn $%.2x,$%.2x ", op1, op8); break;
case 0x55: sprintf(t, "eor $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x56: sprintf(t, "lsr $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x57: sprintf(t, "eor [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x58: sprintf(t, "cli "); break;
case 0x59: sprintf(t, "eor $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x5a: sprintf(t, "phy "); break;
case 0x5b: sprintf(t, "tcd "); break;
case 0x5c: sprintf(t, "jml $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x5d: sprintf(t, "eor $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x5e: sprintf(t, "lsr $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x5f: sprintf(t, "eor $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x60: sprintf(t, "rts "); break;
case 0x61: sprintf(t, "adc ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x62: sprintf(t, "per $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x63: sprintf(t, "adc $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x64: sprintf(t, "stz $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x65: sprintf(t, "adc $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x66: sprintf(t, "ror $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x67: sprintf(t, "adc [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x68: sprintf(t, "pla "); break;
case 0x69: if(a8)sprintf(t, "adc #$%.2x ", op8);
else sprintf(t, "adc #$%.4x ", op16); break;
case 0x6a: sprintf(t, "ror a "); break;
case 0x6b: sprintf(t, "rtl "); break;
case 0x6c: sprintf(t, "jmp ($%.4x) [%.6x]", op16, decode(OPTYPE_IADDR_PC, op16)); break;
case 0x6d: sprintf(t, "adc $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x6e: sprintf(t, "ror $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x6f: sprintf(t, "adc $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x70: sprintf(t, "bvs $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x71: sprintf(t, "adc ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x72: sprintf(t, "adc ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x73: sprintf(t, "adc ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x74: sprintf(t, "stz $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x75: sprintf(t, "adc $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x76: sprintf(t, "ror $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x77: sprintf(t, "adc [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x78: sprintf(t, "sei "); break;
case 0x79: sprintf(t, "adc $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x7a: sprintf(t, "ply "); break;
case 0x7b: sprintf(t, "tdc "); break;
case 0x7c: sprintf(t, "jmp ($%.4x,x) [%.6x]", op16, decode(OPTYPE_IADDRX, op16)); break;
case 0x7d: sprintf(t, "adc $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x7e: sprintf(t, "ror $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x7f: sprintf(t, "adc $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x80: sprintf(t, "bra $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x81: sprintf(t, "sta ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x82: sprintf(t, "brl $%.4x [%.6x]", uint16(decode(OPTYPE_RELW, op16)), decode(OPTYPE_RELW, op16)); break;
case 0x83: sprintf(t, "sta $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x84: sprintf(t, "sty $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x85: sprintf(t, "sta $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x86: sprintf(t, "stx $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x87: sprintf(t, "sta [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x88: sprintf(t, "dey "); break;
case 0x89: if(a8)sprintf(t, "bit #$%.2x ", op8);
else sprintf(t, "bit #$%.4x ", op16); break;
case 0x8a: sprintf(t, "txa "); break;
case 0x8b: sprintf(t, "phb "); break;
case 0x8c: sprintf(t, "sty $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8d: sprintf(t, "sta $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8e: sprintf(t, "stx $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8f: sprintf(t, "sta $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x90: sprintf(t, "bcc $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x91: sprintf(t, "sta ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x92: sprintf(t, "sta ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x93: sprintf(t, "sta ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x94: sprintf(t, "sty $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x95: sprintf(t, "sta $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x96: sprintf(t, "stx $%.2x,y [%.6x]", op8, decode(OPTYPE_DPY, op8)); break;
case 0x97: sprintf(t, "sta [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x98: sprintf(t, "tya "); break;
case 0x99: sprintf(t, "sta $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x9a: sprintf(t, "txs "); break;
case 0x9b: sprintf(t, "txy "); break;
case 0x9c: sprintf(t, "stz $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x9d: sprintf(t, "sta $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x9e: sprintf(t, "stz $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x9f: sprintf(t, "sta $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xa0: if(x8)sprintf(t, "ldy #$%.2x ", op8);
else sprintf(t, "ldy #$%.4x ", op16); break;
case 0xa1: sprintf(t, "lda ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xa2: if(x8)sprintf(t, "ldx #$%.2x ", op8);
else sprintf(t, "ldx #$%.4x ", op16); break;
case 0xa3: sprintf(t, "lda $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xa4: sprintf(t, "ldy $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa5: sprintf(t, "lda $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa6: sprintf(t, "ldx $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa7: sprintf(t, "lda [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xa8: sprintf(t, "tay "); break;
case 0xa9: if(a8)sprintf(t, "lda #$%.2x ", op8);
else sprintf(t, "lda #$%.4x ", op16); break;
case 0xaa: sprintf(t, "tax "); break;
case 0xab: sprintf(t, "plb "); break;
case 0xac: sprintf(t, "ldy $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xad: sprintf(t, "lda $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xae: sprintf(t, "ldx $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xaf: sprintf(t, "lda $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xb0: sprintf(t, "bcs $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xb1: sprintf(t, "lda ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xb2: sprintf(t, "lda ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xb3: sprintf(t, "lda ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xb4: sprintf(t, "ldy $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xb5: sprintf(t, "lda $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xb6: sprintf(t, "ldx $%.2x,y [%.6x]", op8, decode(OPTYPE_DPY, op8)); break;
case 0xb7: sprintf(t, "lda [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xb8: sprintf(t, "clv "); break;
case 0xb9: sprintf(t, "lda $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xba: sprintf(t, "tsx "); break;
case 0xbb: sprintf(t, "tyx "); break;
case 0xbc: sprintf(t, "ldy $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xbd: sprintf(t, "lda $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xbe: sprintf(t, "ldx $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xbf: sprintf(t, "lda $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xc0: if(x8)sprintf(t, "cpy #$%.2x ", op8);
else sprintf(t, "cpy #$%.4x ", op16); break;
case 0xc1: sprintf(t, "cmp ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xc2: sprintf(t, "rep #$%.2x ", op8); break;
case 0xc3: sprintf(t, "cmp $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xc4: sprintf(t, "cpy $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc5: sprintf(t, "cmp $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc6: sprintf(t, "dec $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc7: sprintf(t, "cmp [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xc8: sprintf(t, "iny "); break;
case 0xc9: if(a8)sprintf(t, "cmp #$%.2x ", op8);
else sprintf(t, "cmp #$%.4x ", op16); break;
case 0xca: sprintf(t, "dex "); break;
case 0xcb: sprintf(t, "wai "); break;
case 0xcc: sprintf(t, "cpy $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xcd: sprintf(t, "cmp $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xce: sprintf(t, "dec $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xcf: sprintf(t, "cmp $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xd0: sprintf(t, "bne $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xd1: sprintf(t, "cmp ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xd2: sprintf(t, "cmp ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xd3: sprintf(t, "cmp ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xd4: sprintf(t, "pei ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xd5: sprintf(t, "cmp $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xd6: sprintf(t, "dec $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xd7: sprintf(t, "cmp [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xd8: sprintf(t, "cld "); break;
case 0xd9: sprintf(t, "cmp $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xda: sprintf(t, "phx "); break;
case 0xdb: sprintf(t, "stp "); break;
case 0xdc: sprintf(t, "jmp [$%.4x] [%.6x]", op16, decode(OPTYPE_ILADDR, op16)); break;
case 0xdd: sprintf(t, "cmp $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xde: sprintf(t, "dec $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xdf: sprintf(t, "cmp $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xe0: if(x8)sprintf(t, "cpx #$%.2x ", op8);
else sprintf(t, "cpx #$%.4x ", op16); break;
case 0xe1: sprintf(t, "sbc ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xe2: sprintf(t, "sep #$%.2x ", op8); break;
case 0xe3: sprintf(t, "sbc $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xe4: sprintf(t, "cpx $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe5: sprintf(t, "sbc $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe6: sprintf(t, "inc $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe7: sprintf(t, "sbc [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xe8: sprintf(t, "inx "); break;
case 0xe9: if(a8)sprintf(t, "sbc #$%.2x ", op8);
else sprintf(t, "sbc #$%.4x ", op16); break;
case 0xea: sprintf(t, "nop "); break;
case 0xeb: sprintf(t, "xba "); break;
case 0xec: sprintf(t, "cpx $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xed: sprintf(t, "sbc $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xee: sprintf(t, "inc $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xef: sprintf(t, "sbc $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xf0: sprintf(t, "beq $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xf1: sprintf(t, "sbc ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xf2: sprintf(t, "sbc ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xf3: sprintf(t, "sbc ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xf4: sprintf(t, "pea $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xf5: sprintf(t, "sbc $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xf6: sprintf(t, "inc $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xf7: sprintf(t, "sbc [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xf8: sprintf(t, "sed "); break;
case 0xf9: sprintf(t, "sbc $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xfa: sprintf(t, "plx "); break;
case 0xfb: sprintf(t, "xce "); break;
case 0xfc: sprintf(t, "jsr ($%.4x,x) [%.6x]", op16, decode(OPTYPE_IADDRX, op16)); break;
case 0xfd: sprintf(t, "sbc $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xfe: sprintf(t, "inc $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xff: sprintf(t, "sbc $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
}
#undef op8
#undef op16
#undef op24
#undef a8
#undef x8
strcat(s, t);
strcat(s, " ");
sprintf(t, "A:%.4x X:%.4x Y:%.4x S:%.4x D:%.4x DB:%.2x ",
regs.a.w, regs.x.w, regs.y.w, regs.s.w, regs.d.w, regs.db);
strcat(s, t);
if(regs.e) {
sprintf(t, "%c%c%c%c%c%c%c%c",
regs.p.n ? 'N' : 'n', regs.p.v ? 'V' : 'v',
regs.p.m ? '1' : '0', regs.p.x ? 'B' : 'b',
regs.p.d ? 'D' : 'd', regs.p.i ? 'I' : 'i',
regs.p.z ? 'Z' : 'z', regs.p.c ? 'C' : 'c');
} else {
sprintf(t, "%c%c%c%c%c%c%c%c",
regs.p.n ? 'N' : 'n', regs.p.v ? 'V' : 'v',
regs.p.m ? 'M' : 'm', regs.p.x ? 'X' : 'x',
regs.p.d ? 'D' : 'd', regs.p.i ? 'I' : 'i',
regs.p.z ? 'Z' : 'z', regs.p.c ? 'C' : 'c');
}
strcat(s, t);
strcat(s, " ");
sprintf(t, "V:%3d H:%4d", cpu.vcounter(), cpu.hcounter());
strcat(s, t);
}
//opcode_length() retrieves the length of the next opcode
//to be executed. It is used by the debugger to step over,
//disable and proceed cpu opcodes.
//
//5 and 6 are special cases, 5 is used for #consts based on
//the A register size, 6 for the X/Y register size. the
//rest are literal sizes. There's no need to test for
//emulation mode, as regs.p.m/regs.p.x should *always* be
//set in emulation mode.
uint8 CPUcore::opcode_length() {
uint8 op, len;
static uint8 op_len_tbl[256] = {
//0,1,2,3, 4,5,6,7, 8,9,a,b, c,d,e,f
2,2,2,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x0n
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0x1n
3,2,4,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x2n
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0x3n
1,2,2,2, 3,2,2,2, 1,5,1,1, 3,3,3,4, //0x4n
2,2,2,2, 3,2,2,2, 1,3,1,1, 4,3,3,4, //0x5n
1,2,3,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x6n
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0x7n
2,2,3,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x8n
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0x9n
6,2,6,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0xan
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0xbn
6,2,2,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0xcn
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0xdn
6,2,2,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0xen
2,2,2,2, 3,2,2,2, 1,3,1,1, 3,3,3,4 //0xfn
};
if(false /* in_opcode() == true */) {
return 0;
}
op = dreadb(regs.pc.d);
len = op_len_tbl[op];
if(len == 5) return (regs.e || regs.p.m) ? 2 : 3;
if(len == 6) return (regs.e || regs.p.x) ? 2 : 3;
return len;
}
#endif

View File

@ -1,30 +0,0 @@
enum {
OPTYPE_DP = 0, //dp
OPTYPE_DPX, //dp,x
OPTYPE_DPY, //dp,y
OPTYPE_IDP, //(dp)
OPTYPE_IDPX, //(dp,x)
OPTYPE_IDPY, //(dp),y
OPTYPE_ILDP, //[dp]
OPTYPE_ILDPY, //[dp],y
OPTYPE_ADDR, //addr
OPTYPE_ADDRX, //addr,x
OPTYPE_ADDRY, //addr,y
OPTYPE_IADDRX, //(addr,x)
OPTYPE_ILADDR, //[addr]
OPTYPE_LONG, //long
OPTYPE_LONGX, //long, x
OPTYPE_SR, //sr,s
OPTYPE_ISRY, //(sr,s),y
OPTYPE_ADDR_PC, //pbr:addr
OPTYPE_IADDR_PC, //pbr:(addr)
OPTYPE_RELB, //relb
OPTYPE_RELW, //relw
};
void disassemble_opcode(char *output, uint32 addr);
uint8 dreadb(uint32 addr);
uint16 dreadw(uint32 addr);
uint32 dreadl(uint32 addr);
uint32 decode(uint8 offset_type, uint32 addr);
uint8 opcode_length();

View File

@ -1,77 +0,0 @@
alwaysinline uint8_t op_readpc() {
return op_read((regs.pc.b << 16) + regs.pc.w++);
}
alwaysinline uint8_t op_readstack() {
regs.e ? regs.s.l++ : regs.s.w++;
return op_read(regs.s.w);
}
alwaysinline uint8_t op_readstackn() {
return op_read(++regs.s.w);
}
alwaysinline uint8_t op_readaddr(uint32_t addr) {
return op_read(addr & 0xffff);
}
alwaysinline uint8_t op_readlong(uint32_t addr) {
return op_read(addr & 0xffffff);
}
alwaysinline uint8_t op_readdbr(uint32_t addr) {
return op_read(((regs.db << 16) + addr) & 0xffffff);
}
alwaysinline uint8_t op_readpbr(uint32_t addr) {
return op_read((regs.pc.b << 16) + (addr & 0xffff));
}
alwaysinline uint8_t op_readdp(uint32_t addr) {
if(regs.e && regs.d.l == 0x00) {
return op_read((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff));
} else {
return op_read((regs.d + (addr & 0xffff)) & 0xffff);
}
}
alwaysinline uint8_t op_readsp(uint32_t addr) {
return op_read((regs.s + (addr & 0xffff)) & 0xffff);
}
alwaysinline void op_writestack(uint8_t data) {
op_write(regs.s.w, data);
regs.e ? regs.s.l-- : regs.s.w--;
}
alwaysinline void op_writestackn(uint8_t data) {
op_write(regs.s.w--, data);
}
alwaysinline void op_writeaddr(uint32_t addr, uint8_t data) {
op_write(addr & 0xffff, data);
}
alwaysinline void op_writelong(uint32_t addr, uint8_t data) {
op_write(addr & 0xffffff, data);
}
alwaysinline void op_writedbr(uint32_t addr, uint8_t data) {
op_write(((regs.db << 16) + addr) & 0xffffff, data);
}
alwaysinline void op_writepbr(uint32_t addr, uint8_t data) {
op_write((regs.pc.b << 16) + (addr & 0xffff), data);
}
alwaysinline void op_writedp(uint32_t addr, uint8_t data) {
if(regs.e && regs.d.l == 0x00) {
op_write((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff), data);
} else {
op_write((regs.d + (addr & 0xffff)) & 0xffff, data);
}
}
alwaysinline void op_writesp(uint32_t addr, uint8_t data) {
op_write((regs.s + (addr & 0xffff)) & 0xffff, data);
}

View File

@ -1,338 +0,0 @@
#ifdef CPUCORE_CPP
void CPUcore::op_nop() {
L op_io_irq();
}
void CPUcore::op_wdm() {
L op_readpc();
}
void CPUcore::op_xba() {
op_io();
L op_io();
regs.a.l ^= regs.a.h;
regs.a.h ^= regs.a.l;
regs.a.l ^= regs.a.h;
regs.p.n = (regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
template<int adjust> void CPUcore::op_move_b() {
dp = op_readpc();
sp = op_readpc();
regs.db = dp;
rd.l = op_readlong((sp << 16) | regs.x.w);
op_writelong((dp << 16) | regs.y.w, rd.l);
op_io();
regs.x.l += adjust;
regs.y.l += adjust;
L op_io();
if(regs.a.w--) regs.pc.w -= 3;
}
template<int adjust> void CPUcore::op_move_w() {
dp = op_readpc();
sp = op_readpc();
regs.db = dp;
rd.l = op_readlong((sp << 16) | regs.x.w);
op_writelong((dp << 16) | regs.y.w, rd.l);
op_io();
regs.x.w += adjust;
regs.y.w += adjust;
L op_io();
if(regs.a.w--) regs.pc.w -= 3;
}
template<int vectorE, int vectorN> void CPUcore::op_interrupt_e() {
op_readpc();
op_writestack(regs.pc.h);
op_writestack(regs.pc.l);
op_writestack(regs.p);
rd.l = op_readlong(vectorE + 0);
regs.pc.b = 0;
regs.p.i = 1;
regs.p.d = 0;
L rd.h = op_readlong(vectorE + 1);
regs.pc.w = rd.w;
}
template<int vectorE, int vectorN> void CPUcore::op_interrupt_n() {
op_readpc();
op_writestack(regs.pc.b);
op_writestack(regs.pc.h);
op_writestack(regs.pc.l);
op_writestack(regs.p);
rd.l = op_readlong(vectorN + 0);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
L rd.h = op_readlong(vectorN + 1);
regs.pc.w = rd.w;
}
void CPUcore::op_stp() {
while(regs.wai = true) {
L op_io();
}
}
void CPUcore::op_wai() {
regs.wai = true;
while(regs.wai) {
L op_io();
}
op_io();
}
void CPUcore::op_xce() {
L op_io_irq();
bool carry = regs.p.c;
regs.p.c = regs.e;
regs.e = carry;
if(regs.e) {
regs.p |= 0x30;
regs.s.h = 0x01;
}
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
update_table();
}
template<int mask, int value> void CPUcore::op_flag() {
L op_io_irq();
regs.p = (regs.p & ~mask) | value;
}
template<int mode> void CPUcore::op_pflag_e() {
rd.l = op_readpc();
L op_io();
regs.p = (mode ? regs.p | rd.l : regs.p & ~rd.l);
regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
update_table();
}
template<int mode> void CPUcore::op_pflag_n() {
rd.l = op_readpc();
L op_io();
regs.p = (mode ? regs.p | rd.l : regs.p & ~rd.l);
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
update_table();
}
template<int from, int to> void CPUcore::op_transfer_b() {
L op_io_irq();
regs.r[to].l = regs.r[from].l;
regs.p.n = (regs.r[to].l & 0x80);
regs.p.z = (regs.r[to].l == 0);
}
template<int from, int to> void CPUcore::op_transfer_w() {
L op_io_irq();
regs.r[to].w = regs.r[from].w;
regs.p.n = (regs.r[to].w & 0x8000);
regs.p.z = (regs.r[to].w == 0);
}
void CPUcore::op_tcs_e() {
L op_io_irq();
regs.s.l = regs.a.l;
}
void CPUcore::op_tcs_n() {
L op_io_irq();
regs.s.w = regs.a.w;
}
void CPUcore::op_tsx_b() {
L op_io_irq();
regs.x.l = regs.s.l;
regs.p.n = (regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
}
void CPUcore::op_tsx_w() {
L op_io_irq();
regs.x.w = regs.s.w;
regs.p.n = (regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
void CPUcore::op_txs_e() {
L op_io_irq();
regs.s.l = regs.x.l;
}
void CPUcore::op_txs_n() {
L op_io_irq();
regs.s.w = regs.x.w;
}
template<int n> void CPUcore::op_push_b() {
op_io();
L op_writestack(regs.r[n].l);
}
template<int n> void CPUcore::op_push_w() {
op_io();
op_writestack(regs.r[n].h);
L op_writestack(regs.r[n].l);
}
void CPUcore::op_phd_e() {
op_io();
op_writestackn(regs.d.h);
L op_writestackn(regs.d.l);
regs.s.h = 0x01;
}
void CPUcore::op_phd_n() {
op_io();
op_writestackn(regs.d.h);
L op_writestackn(regs.d.l);
}
void CPUcore::op_phb() {
op_io();
L op_writestack(regs.db);
}
void CPUcore::op_phk() {
op_io();
L op_writestack(regs.pc.b);
}
void CPUcore::op_php() {
op_io();
L op_writestack(regs.p);
}
template<int n> void CPUcore::op_pull_b() {
op_io();
op_io();
L regs.r[n].l = op_readstack();
regs.p.n = (regs.r[n].l & 0x80);
regs.p.z = (regs.r[n].l == 0);
}
template<int n> void CPUcore::op_pull_w() {
op_io();
op_io();
regs.r[n].l = op_readstack();
L regs.r[n].h = op_readstack();
regs.p.n = (regs.r[n].w & 0x8000);
regs.p.z = (regs.r[n].w == 0);
}
void CPUcore::op_pld_e() {
op_io();
op_io();
regs.d.l = op_readstackn();
L regs.d.h = op_readstackn();
regs.p.n = (regs.d.w & 0x8000);
regs.p.z = (regs.d.w == 0);
regs.s.h = 0x01;
}
void CPUcore::op_pld_n() {
op_io();
op_io();
regs.d.l = op_readstackn();
L regs.d.h = op_readstackn();
regs.p.n = (regs.d.w & 0x8000);
regs.p.z = (regs.d.w == 0);
}
void CPUcore::op_plb() {
op_io();
op_io();
L regs.db = op_readstack();
regs.p.n = (regs.db & 0x80);
regs.p.z = (regs.db == 0);
}
void CPUcore::op_plp_e() {
op_io();
op_io();
L regs.p = op_readstack() | 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
update_table();
}
void CPUcore::op_plp_n() {
op_io();
op_io();
L regs.p = op_readstack();
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
update_table();
}
void CPUcore::op_pea_e() {
aa.l = op_readpc();
aa.h = op_readpc();
op_writestackn(aa.h);
L op_writestackn(aa.l);
regs.s.h = 0x01;
}
void CPUcore::op_pea_n() {
aa.l = op_readpc();
aa.h = op_readpc();
op_writestackn(aa.h);
L op_writestackn(aa.l);
}
void CPUcore::op_pei_e() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
op_writestackn(aa.h);
L op_writestackn(aa.l);
regs.s.h = 0x01;
}
void CPUcore::op_pei_n() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
op_writestackn(aa.h);
L op_writestackn(aa.l);
}
void CPUcore::op_per_e() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.w = regs.pc.d + (int16)aa.w;
op_writestackn(rd.h);
L op_writestackn(rd.l);
regs.s.h = 0x01;
}
void CPUcore::op_per_n() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.w = regs.pc.d + (int16)aa.w;
op_writestackn(rd.h);
L op_writestackn(rd.l);
}
#endif

View File

@ -1,181 +0,0 @@
#ifdef CPUCORE_CPP
template<int bit, int val> void CPUcore::op_branch() {
if((bool)(regs.p & bit) != val) {
L rd.l = op_readpc();
} else {
rd.l = op_readpc();
aa.w = regs.pc.d + (int8)rd.l;
op_io_cond6(aa.w);
L op_io();
regs.pc.w = aa.w;
}
}
void CPUcore::op_bra() {
rd.l = op_readpc();
aa.w = regs.pc.d + (int8)rd.l;
op_io_cond6(aa.w);
L op_io();
regs.pc.w = aa.w;
}
void CPUcore::op_brl() {
rd.l = op_readpc();
rd.h = op_readpc();
L op_io();
regs.pc.w = regs.pc.d + (int16)rd.w;
}
void CPUcore::op_jmp_addr() {
rd.l = op_readpc();
L rd.h = op_readpc();
regs.pc.w = rd.w;
}
void CPUcore::op_jmp_long() {
rd.l = op_readpc();
rd.h = op_readpc();
L rd.b = op_readpc();
regs.pc.d = rd.d & 0xffffff;
}
void CPUcore::op_jmp_iaddr() {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readaddr(aa.w + 0);
L rd.h = op_readaddr(aa.w + 1);
regs.pc.w = rd.w;
}
void CPUcore::op_jmp_iaddrx() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readpbr(aa.w + regs.x.w + 0);
L rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
}
void CPUcore::op_jmp_iladdr() {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readaddr(aa.w + 0);
rd.h = op_readaddr(aa.w + 1);
L rd.b = op_readaddr(aa.w + 2);
regs.pc.d = rd.d & 0xffffff;
}
void CPUcore::op_jsr_addr() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
regs.pc.w--;
op_writestack(regs.pc.h);
L op_writestack(regs.pc.l);
regs.pc.w = aa.w;
}
void CPUcore::op_jsr_long_e() {
aa.l = op_readpc();
aa.h = op_readpc();
op_writestackn(regs.pc.b);
op_io();
aa.b = op_readpc();
regs.pc.w--;
op_writestackn(regs.pc.h);
L op_writestackn(regs.pc.l);
regs.pc.d = aa.d & 0xffffff;
regs.s.h = 0x01;
}
void CPUcore::op_jsr_long_n() {
aa.l = op_readpc();
aa.h = op_readpc();
op_writestackn(regs.pc.b);
op_io();
aa.b = op_readpc();
regs.pc.w--;
op_writestackn(regs.pc.h);
L op_writestackn(regs.pc.l);
regs.pc.d = aa.d & 0xffffff;
}
void CPUcore::op_jsr_iaddrx_e() {
aa.l = op_readpc();
op_writestackn(regs.pc.h);
op_writestackn(regs.pc.l);
aa.h = op_readpc();
op_io();
rd.l = op_readpbr(aa.w + regs.x.w + 0);
L rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
regs.s.h = 0x01;
}
void CPUcore::op_jsr_iaddrx_n() {
aa.l = op_readpc();
op_writestackn(regs.pc.h);
op_writestackn(regs.pc.l);
aa.h = op_readpc();
op_io();
rd.l = op_readpbr(aa.w + regs.x.w + 0);
L rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
}
void CPUcore::op_rti_e() {
op_io();
op_io();
regs.p = op_readstack() | 0x30;
rd.l = op_readstack();
L rd.h = op_readstack();
regs.pc.w = rd.w;
}
void CPUcore::op_rti_n() {
op_io();
op_io();
regs.p = op_readstack();
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
rd.l = op_readstack();
rd.h = op_readstack();
L rd.b = op_readstack();
regs.pc.d = rd.d & 0xffffff;
update_table();
}
void CPUcore::op_rts() {
op_io();
op_io();
rd.l = op_readstack();
rd.h = op_readstack();
L op_io();
regs.pc.w = ++rd.w;
}
void CPUcore::op_rtl_e() {
op_io();
op_io();
rd.l = op_readstackn();
rd.h = op_readstackn();
L rd.b = op_readstackn();
regs.pc.b = rd.b;
regs.pc.w = ++rd.w;
regs.s.h = 0x01;
}
void CPUcore::op_rtl_n() {
op_io();
op_io();
rd.l = op_readstackn();
rd.h = op_readstackn();
L rd.b = op_readstackn();
regs.pc.b = rd.b;
regs.pc.w = ++rd.w;
}
#endif

View File

@ -1,279 +0,0 @@
#ifdef CPUCORE_CPP
template<void (CPUcore::*op)()> void CPUcore::op_read_const_b() {
L rd.l = op_readpc();
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_const_w() {
rd.l = op_readpc();
L rd.h = op_readpc();
call(op);
}
void CPUcore::op_read_bit_const_b() {
L rd.l = op_readpc();
regs.p.z = ((rd.l & regs.a.l) == 0);
}
void CPUcore::op_read_bit_const_w() {
rd.l = op_readpc();
L rd.h = op_readpc();
regs.p.z = ((rd.w & regs.a.w) == 0);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_addr_b() {
aa.l = op_readpc();
aa.h = op_readpc();
L rd.l = op_readdbr(aa.w);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_addr_w() {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w + 0);
L rd.h = op_readdbr(aa.w + 1);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_addrx_b() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io_cond4(aa.w, aa.w + regs.x.w);
L rd.l = op_readdbr(aa.w + regs.x.w);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_addrx_w() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io_cond4(aa.w, aa.w + regs.x.w);
rd.l = op_readdbr(aa.w + regs.x.w + 0);
L rd.h = op_readdbr(aa.w + regs.x.w + 1);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_addry_b() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io_cond4(aa.w, aa.w + regs.y.w);
L rd.l = op_readdbr(aa.w + regs.y.w);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_addry_w() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io_cond4(aa.w, aa.w + regs.y.w);
rd.l = op_readdbr(aa.w + regs.y.w + 0);
L rd.h = op_readdbr(aa.w + regs.y.w + 1);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_long_b() {
aa.l = op_readpc();
aa.h = op_readpc();
aa.b = op_readpc();
L rd.l = op_readlong(aa.d);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_long_w() {
aa.l = op_readpc();
aa.h = op_readpc();
aa.b = op_readpc();
rd.l = op_readlong(aa.d + 0);
L rd.h = op_readlong(aa.d + 1);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_longx_b() {
aa.l = op_readpc();
aa.h = op_readpc();
aa.b = op_readpc();
L rd.l = op_readlong(aa.d + regs.x.w);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_longx_w() {
aa.l = op_readpc();
aa.h = op_readpc();
aa.b = op_readpc();
rd.l = op_readlong(aa.d + regs.x.w + 0);
L rd.h = op_readlong(aa.d + regs.x.w + 1);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_dp_b() {
dp = op_readpc();
op_io_cond2();
L rd.l = op_readdp(dp);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_dp_w() {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp + 0);
L rd.h = op_readdp(dp + 1);
call(op);
}
template<void (CPUcore::*op)(), int n> void CPUcore::op_read_dpr_b() {
dp = op_readpc();
op_io_cond2();
op_io();
L rd.l = op_readdp(dp + regs.r[n].w);
call(op);
}
template<void (CPUcore::*op)(), int n> void CPUcore::op_read_dpr_w() {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.r[n].w + 0);
L rd.h = op_readdp(dp + regs.r[n].w + 1);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_idp_b() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
L rd.l = op_readdbr(aa.w);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_idp_w() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
rd.l = op_readdbr(aa.w + 0);
L rd.h = op_readdbr(aa.w + 1);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_idpx_b() {
dp = op_readpc();
op_io_cond2();
op_io();
aa.l = op_readdp(dp + regs.x.w + 0);
aa.h = op_readdp(dp + regs.x.w + 1);
L rd.l = op_readdbr(aa.w);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_idpx_w() {
dp = op_readpc();
op_io_cond2();
op_io();
aa.l = op_readdp(dp + regs.x.w + 0);
aa.h = op_readdp(dp + regs.x.w + 1);
rd.l = op_readdbr(aa.w + 0);
L rd.h = op_readdbr(aa.w + 1);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_idpy_b() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
op_io_cond4(aa.w, aa.w + regs.y.w);
L rd.l = op_readdbr(aa.w + regs.y.w);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_idpy_w() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
op_io_cond4(aa.w, aa.w + regs.y.w);
rd.l = op_readdbr(aa.w + regs.y.w + 0);
L rd.h = op_readdbr(aa.w + regs.y.w + 1);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_ildp_b() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
L rd.l = op_readlong(aa.d);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_ildp_w() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
rd.l = op_readlong(aa.d + 0);
L rd.h = op_readlong(aa.d + 1);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_ildpy_b() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
L rd.l = op_readlong(aa.d + regs.y.w);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_ildpy_w() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
rd.l = op_readlong(aa.d + regs.y.w + 0);
L rd.h = op_readlong(aa.d + regs.y.w + 1);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_sr_b() {
sp = op_readpc();
op_io();
L rd.l = op_readsp(sp);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_sr_w() {
sp = op_readpc();
op_io();
rd.l = op_readsp(sp + 0);
L rd.h = op_readsp(sp + 1);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_isry_b() {
sp = op_readpc();
op_io();
aa.l = op_readsp(sp + 0);
aa.h = op_readsp(sp + 1);
op_io();
L rd.l = op_readdbr(aa.w + regs.y.w);
call(op);
}
template<void (CPUcore::*op)()> void CPUcore::op_read_isry_w() {
sp = op_readpc();
op_io();
aa.l = op_readsp(sp + 0);
aa.h = op_readsp(sp + 1);
op_io();
rd.l = op_readdbr(aa.w + regs.y.w + 0);
L rd.h = op_readdbr(aa.w + regs.y.w + 1);
call(op);
}
#endif

View File

@ -1,169 +0,0 @@
#ifdef CPUCORE_CPP
template<int n, int adjust> void CPUcore::op_adjust_imm_b() {
L op_io_irq();
regs.r[n].l += adjust;
regs.p.n = (regs.r[n].l & 0x80);
regs.p.z = (regs.r[n].l == 0);
}
template<int n, int adjust> void CPUcore::op_adjust_imm_w() {
L op_io_irq();
regs.r[n].w += adjust;
regs.p.n = (regs.r[n].w & 0x8000);
regs.p.z = (regs.r[n].w == 0);
}
void CPUcore::op_asl_imm_b() {
L op_io_irq();
regs.p.c = (regs.a.l & 0x80);
regs.a.l <<= 1;
regs.p.n = (regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
void CPUcore::op_asl_imm_w() {
L op_io_irq();
regs.p.c = (regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.p.n = (regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
void CPUcore::op_lsr_imm_b() {
L op_io_irq();
regs.p.c = (regs.a.l & 0x01);
regs.a.l >>= 1;
regs.p.n = (regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
void CPUcore::op_lsr_imm_w() {
L op_io_irq();
regs.p.c = (regs.a.w & 0x0001);
regs.a.w >>= 1;
regs.p.n = (regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
void CPUcore::op_rol_imm_b() {
L op_io_irq();
bool carry = regs.p.c;
regs.p.c = (regs.a.l & 0x80);
regs.a.l = (regs.a.l << 1) | carry;
regs.p.n = (regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
void CPUcore::op_rol_imm_w() {
L op_io_irq();
bool carry = regs.p.c;
regs.p.c = (regs.a.w & 0x8000);
regs.a.w = (regs.a.w << 1) | carry;
regs.p.n = (regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
void CPUcore::op_ror_imm_b() {
L op_io_irq();
bool carry = regs.p.c;
regs.p.c = (regs.a.l & 0x01);
regs.a.l = (carry << 7) | (regs.a.l >> 1);
regs.p.n = (regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
void CPUcore::op_ror_imm_w() {
L op_io_irq();
bool carry = regs.p.c;
regs.p.c = (regs.a.w & 0x0001);
regs.a.w = (carry << 15) | (regs.a.w >> 1);
regs.p.n = (regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
template<void (CPUcore::*op)()> void CPUcore::op_adjust_addr_b() {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
op_io();
call(op);
L op_writedbr(aa.w, rd.l);
}
template<void (CPUcore::*op)()> void CPUcore::op_adjust_addr_w() {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w + 0);
rd.h = op_readdbr(aa.w + 1);
op_io();
call(op);
op_writedbr(aa.w + 1, rd.h);
L op_writedbr(aa.w + 0, rd.l);
}
template<void (CPUcore::*op)()> void CPUcore::op_adjust_addrx_b() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
op_io();
call(op);
L op_writedbr(aa.w + regs.x.w, rd.l);
}
template<void (CPUcore::*op)()> void CPUcore::op_adjust_addrx_w() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w + 0);
rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
call(op);
op_writedbr(aa.w + regs.x.w + 1, rd.h);
L op_writedbr(aa.w + regs.x.w + 0, rd.l);
}
template<void (CPUcore::*op)()> void CPUcore::op_adjust_dp_b() {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
op_io();
call(op);
L op_writedp(dp, rd.l);
}
template<void (CPUcore::*op)()> void CPUcore::op_adjust_dp_w() {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp + 0);
rd.h = op_readdp(dp + 1);
op_io();
call(op);
op_writedp(dp + 1, rd.h);
L op_writedp(dp + 0, rd.l);
}
template<void (CPUcore::*op)()> void CPUcore::op_adjust_dpx_b() {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
op_io();
call(op);
L op_writedp(dp + regs.x.w, rd.l);
}
template<void (CPUcore::*op)()> void CPUcore::op_adjust_dpx_w() {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w + 0);
rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
call(op);
op_writedp(dp + regs.x.w + 1, rd.h);
L op_writedp(dp + regs.x.w + 0, rd.l);
}
#endif

View File

@ -1,199 +0,0 @@
#ifdef CPUCORE_CPP
template<int n> void CPUcore::op_write_addr_b() {
aa.l = op_readpc();
aa.h = op_readpc();
L op_writedbr(aa.w, regs.r[n]);
}
template<int n> void CPUcore::op_write_addr_w() {
aa.l = op_readpc();
aa.h = op_readpc();
op_writedbr(aa.w + 0, regs.r[n] >> 0);
L op_writedbr(aa.w + 1, regs.r[n] >> 8);
}
template<int n, int i> void CPUcore::op_write_addrr_b() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
L op_writedbr(aa.w + regs.r[i], regs.r[n]);
}
template<int n, int i> void CPUcore::op_write_addrr_w() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
op_writedbr(aa.w + regs.r[i] + 0, regs.r[n] >> 0);
L op_writedbr(aa.w + regs.r[i] + 1, regs.r[n] >> 8);
}
template<int i> void CPUcore::op_write_longr_b() {
aa.l = op_readpc();
aa.h = op_readpc();
aa.b = op_readpc();
L op_writelong(aa.d + regs.r[i], regs.a.l);
}
template<int i> void CPUcore::op_write_longr_w() {
aa.l = op_readpc();
aa.h = op_readpc();
aa.b = op_readpc();
op_writelong(aa.d + regs.r[i] + 0, regs.a.l);
L op_writelong(aa.d + regs.r[i] + 1, regs.a.h);
}
template<int n> void CPUcore::op_write_dp_b() {
dp = op_readpc();
op_io_cond2();
L op_writedp(dp, regs.r[n]);
}
template<int n> void CPUcore::op_write_dp_w() {
dp = op_readpc();
op_io_cond2();
op_writedp(dp + 0, regs.r[n] >> 0);
L op_writedp(dp + 1, regs.r[n] >> 8);
}
template<int n, int i> void CPUcore::op_write_dpr_b() {
dp = op_readpc();
op_io_cond2();
op_io();
L op_writedp(dp + regs.r[i], regs.r[n]);
}
template<int n, int i> void CPUcore::op_write_dpr_w() {
dp = op_readpc();
op_io_cond2();
op_io();
op_writedp(dp + regs.r[i] + 0, regs.r[n] >> 0);
L op_writedp(dp + regs.r[i] + 1, regs.r[n] >> 8);
}
void CPUcore::op_sta_idp_b() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
L op_writedbr(aa.w, regs.a.l);
}
void CPUcore::op_sta_idp_w() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
op_writedbr(aa.w + 0, regs.a.l);
L op_writedbr(aa.w + 1, regs.a.h);
}
void CPUcore::op_sta_ildp_b() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
L op_writelong(aa.d, regs.a.l);
}
void CPUcore::op_sta_ildp_w() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
op_writelong(aa.d + 0, regs.a.l);
L op_writelong(aa.d + 1, regs.a.h);
}
void CPUcore::op_sta_idpx_b() {
dp = op_readpc();
op_io_cond2();
op_io();
aa.l = op_readdp(dp + regs.x.w + 0);
aa.h = op_readdp(dp + regs.x.w + 1);
L op_writedbr(aa.w, regs.a.l);
}
void CPUcore::op_sta_idpx_w() {
dp = op_readpc();
op_io_cond2();
op_io();
aa.l = op_readdp(dp + regs.x.w + 0);
aa.h = op_readdp(dp + regs.x.w + 1);
op_writedbr(aa.w + 0, regs.a.l);
L op_writedbr(aa.w + 1, regs.a.h);
}
void CPUcore::op_sta_idpy_b() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
op_io();
L op_writedbr(aa.w + regs.y.w, regs.a.l);
}
void CPUcore::op_sta_idpy_w() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
op_io();
op_writedbr(aa.w + regs.y.w + 0, regs.a.l);
L op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}
void CPUcore::op_sta_ildpy_b() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
L op_writelong(aa.d + regs.y.w, regs.a.l);
}
void CPUcore::op_sta_ildpy_w() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
op_writelong(aa.d + regs.y.w + 0, regs.a.l);
L op_writelong(aa.d + regs.y.w + 1, regs.a.h);
}
void CPUcore::op_sta_sr_b() {
sp = op_readpc();
op_io();
L op_writesp(sp, regs.a.l);
}
void CPUcore::op_sta_sr_w() {
sp = op_readpc();
op_io();
op_writesp(sp + 0, regs.a.l);
L op_writesp(sp + 1, regs.a.h);
}
void CPUcore::op_sta_isry_b() {
sp = op_readpc();
op_io();
aa.l = op_readsp(sp + 0);
aa.h = op_readsp(sp + 1);
op_io();
L op_writedbr(aa.w + regs.y.w, regs.a.l);
}
void CPUcore::op_sta_isry_w() {
sp = op_readpc();
op_io();
aa.l = op_readsp(sp + 0);
aa.h = op_readsp(sp + 1);
op_io();
op_writedbr(aa.w + regs.y.w + 0, regs.a.l);
L op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}
#endif

View File

@ -1,81 +0,0 @@
struct flag_t {
bool n, v, m, x, d, i, z, c;
inline operator unsigned() const {
return (n << 7) + (v << 6) + (m << 5) + (x << 4)
+ (d << 3) + (i << 2) + (z << 1) + (c << 0);
}
inline unsigned operator=(uint8 data) {
n = data & 0x80; v = data & 0x40; m = data & 0x20; x = data & 0x10;
d = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01;
return data;
}
inline unsigned operator|=(unsigned data) { return operator=(operator unsigned() | data); }
inline unsigned operator^=(unsigned data) { return operator=(operator unsigned() ^ data); }
inline unsigned operator&=(unsigned data) { return operator=(operator unsigned() & data); }
flag_t() : n(0), v(0), m(0), x(0), d(0), i(0), z(0), c(0) {}
};
struct reg16_t {
union {
uint16 w;
struct { uint8 order_lsb2(l, h); };
};
inline operator unsigned() const { return w; }
inline unsigned operator = (unsigned i) { return w = i; }
inline unsigned operator |= (unsigned i) { return w |= i; }
inline unsigned operator ^= (unsigned i) { return w ^= i; }
inline unsigned operator &= (unsigned i) { return w &= i; }
inline unsigned operator <<= (unsigned i) { return w <<= i; }
inline unsigned operator >>= (unsigned i) { return w >>= i; }
inline unsigned operator += (unsigned i) { return w += i; }
inline unsigned operator -= (unsigned i) { return w -= i; }
inline unsigned operator *= (unsigned i) { return w *= i; }
inline unsigned operator /= (unsigned i) { return w /= i; }
inline unsigned operator %= (unsigned i) { return w %= i; }
reg16_t() : w(0) {}
};
struct reg24_t {
union {
uint32 d;
struct { uint16 order_lsb2(w, wh); };
struct { uint8 order_lsb4(l, h, b, bh); };
};
inline operator unsigned() const { return d; }
inline unsigned operator = (unsigned i) { return d = uclip<24>(i); }
inline unsigned operator |= (unsigned i) { return d = uclip<24>(d | i); }
inline unsigned operator ^= (unsigned i) { return d = uclip<24>(d ^ i); }
inline unsigned operator &= (unsigned i) { return d = uclip<24>(d & i); }
inline unsigned operator <<= (unsigned i) { return d = uclip<24>(d << i); }
inline unsigned operator >>= (unsigned i) { return d = uclip<24>(d >> i); }
inline unsigned operator += (unsigned i) { return d = uclip<24>(d + i); }
inline unsigned operator -= (unsigned i) { return d = uclip<24>(d - i); }
inline unsigned operator *= (unsigned i) { return d = uclip<24>(d * i); }
inline unsigned operator /= (unsigned i) { return d = uclip<24>(d / i); }
inline unsigned operator %= (unsigned i) { return d = uclip<24>(d % i); }
reg24_t() : d(0) {}
};
struct regs_t {
reg24_t pc;
reg16_t r[6], &a, &x, &y, &z, &s, &d;
flag_t p;
uint8 db;
bool e;
bool irq; //IRQ pin (0 = low, 1 = trigger)
bool wai; //raised during wai, cleared after interrupt triggered
uint8 mdr; //memory data register
regs_t() : a(r[0]), x(r[1]), y(r[2]), z(r[3]), s(r[4]), d(r[5]), db(0), e(false), irq(false), wai(false), mdr(0) {
z = 0;
}
};

View File

@ -1,36 +0,0 @@
#ifdef CPUCORE_CPP
void CPUcore::core_serialize(serializer &s) {
s.integer(regs.pc.d);
s.integer(regs.a.w);
s.integer(regs.x.w);
s.integer(regs.y.w);
s.integer(regs.z.w);
s.integer(regs.s.w);
s.integer(regs.d.w);
s.integer(regs.p.n);
s.integer(regs.p.v);
s.integer(regs.p.m);
s.integer(regs.p.x);
s.integer(regs.p.d);
s.integer(regs.p.i);
s.integer(regs.p.z);
s.integer(regs.p.c);
s.integer(regs.db);
s.integer(regs.e);
s.integer(regs.irq);
s.integer(regs.wai);
s.integer(regs.mdr);
s.integer(aa.d);
s.integer(rd.d);
s.integer(sp);
s.integer(dp);
update_table();
}
#endif

View File

@ -1,312 +0,0 @@
#ifdef CPUCORE_CPP
void CPUcore::initialize_opcode_table() {
#define opA( id, name ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name;
#define opAII(id, name, x, y ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name<x, y>;
#define opE( id, name ) op_table[table_EM + id] = &CPUcore::op_##name##_e; op_table[table_MX + id] = op_table[table_Mx + id] = op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_n;
#define opEI( id, name, x ) op_table[table_EM + id] = &CPUcore::op_##name##_e<x>; op_table[table_MX + id] = op_table[table_Mx + id] = op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_n<x>;
#define opEII(id, name, x, y ) op_table[table_EM + id] = &CPUcore::op_##name##_e<x, y>; op_table[table_MX + id] = op_table[table_Mx + id] = op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_n<x, y>;
#define opM( id, name ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = &CPUcore::op_##name##_b; op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w;
#define opMI( id, name, x ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = &CPUcore::op_##name##_b<x>; op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<x>;
#define opMII(id, name, x, y ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = &CPUcore::op_##name##_b<x, y>; op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<x, y>;
#define opMF( id, name, fn ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = &CPUcore::op_##name##_b<&CPUcore::op_##fn##_b>; op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<&CPUcore::op_##fn##_w>;
#define opMFI(id, name, fn, x) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = &CPUcore::op_##name##_b<&CPUcore::op_##fn##_b, x>; op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<&CPUcore::op_##fn##_w, x>;
#define opX( id, name ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_mX + id] = &CPUcore::op_##name##_b; op_table[table_Mx + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w;
#define opXI( id, name, x ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_mX + id] = &CPUcore::op_##name##_b<x>; op_table[table_Mx + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<x>;
#define opXII(id, name, x, y ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_mX + id] = &CPUcore::op_##name##_b<x, y>; op_table[table_Mx + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<x, y>;
#define opXF( id, name, fn ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_mX + id] = &CPUcore::op_##name##_b<&CPUcore::op_##fn##_b>; op_table[table_Mx + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<&CPUcore::op_##fn##_w>;
#define opXFI(id, name, fn, x) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_mX + id] = &CPUcore::op_##name##_b<&CPUcore::op_##fn##_b, x>; op_table[table_Mx + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<&CPUcore::op_##fn##_w, x>;
opEII(0x00, interrupt, 0xfffe, 0xffe6)
opMF (0x01, read_idpx, ora)
opEII(0x02, interrupt, 0xfff4, 0xffe4)
opMF (0x03, read_sr, ora)
opMF (0x04, adjust_dp, tsb)
opMF (0x05, read_dp, ora)
opMF (0x06, adjust_dp, asl)
opMF (0x07, read_ildp, ora)
opA (0x08, php)
opMF (0x09, read_const, ora)
opM (0x0a, asl_imm)
opE (0x0b, phd)
opMF (0x0c, adjust_addr, tsb)
opMF (0x0d, read_addr, ora)
opMF (0x0e, adjust_addr, asl)
opMF (0x0f, read_long, ora)
opAII(0x10, branch, 0x80, false)
opMF (0x11, read_idpy, ora)
opMF (0x12, read_idp, ora)
opMF (0x13, read_isry, ora)
opMF (0x14, adjust_dp, trb)
opMFI(0x15, read_dpr, ora, X)
opMF (0x16, adjust_dpx, asl)
opMF (0x17, read_ildpy, ora)
opAII(0x18, flag, 0x01, 0x00)
opMF (0x19, read_addry, ora)
opMII(0x1a, adjust_imm, A, +1)
opE (0x1b, tcs)
opMF (0x1c, adjust_addr, trb)
opMF (0x1d, read_addrx, ora)
opMF (0x1e, adjust_addrx, asl)
opMF (0x1f, read_longx, ora)
opA (0x20, jsr_addr)
opMF (0x21, read_idpx, and)
opE (0x22, jsr_long)
opMF (0x23, read_sr, and)
opMF (0x24, read_dp, bit)
opMF (0x25, read_dp, and)
opMF (0x26, adjust_dp, rol)
opMF (0x27, read_ildp, and)
opE (0x28, plp)
opMF (0x29, read_const, and)
opM (0x2a, rol_imm)
opE (0x2b, pld)
opMF (0x2c, read_addr, bit)
opMF (0x2d, read_addr, and)
opMF (0x2e, adjust_addr, rol)
opMF (0x2f, read_long, and)
opAII(0x30, branch, 0x80, true)
opMF (0x31, read_idpy, and)
opMF (0x32, read_idp, and)
opMF (0x33, read_isry, and)
opMFI(0x34, read_dpr, bit, X)
opMFI(0x35, read_dpr, and, X)
opMF (0x36, adjust_dpx, rol)
opMF (0x37, read_ildpy, and)
opAII(0x38, flag, 0x01, 0x01)
opMF (0x39, read_addry, and)
opMII(0x3a, adjust_imm, A, -1)
opAII(0x3b, transfer_w, S, A)
opMF (0x3c, read_addrx, bit)
opMF (0x3d, read_addrx, and)
opMF (0x3e, adjust_addrx, rol)
opMF (0x3f, read_longx, and)
opE (0x40, rti)
opMF (0x41, read_idpx, eor)
opA (0x42, wdm)
opMF (0x43, read_sr, eor)
opXI (0x44, move, -1)
opMF (0x45, read_dp, eor)
opMF (0x46, adjust_dp, lsr)
opMF (0x47, read_ildp, eor)
opMI (0x48, push, A)
opMF (0x49, read_const, eor)
opM (0x4a, lsr_imm)
opA (0x4b, phk)
opA (0x4c, jmp_addr)
opMF (0x4d, read_addr, eor)
opMF (0x4e, adjust_addr, lsr)
opMF (0x4f, read_long, eor)
opAII(0x50, branch, 0x40, false)
opMF (0x51, read_idpy, eor)
opMF (0x52, read_idp, eor)
opMF (0x53, read_isry, eor)
opXI (0x54, move, +1)
opMFI(0x55, read_dpr, eor, X)
opMF (0x56, adjust_dpx, lsr)
opMF (0x57, read_ildpy, eor)
opAII(0x58, flag, 0x04, 0x00)
opMF (0x59, read_addry, eor)
opXI (0x5a, push, Y)
opAII(0x5b, transfer_w, A, D)
opA (0x5c, jmp_long)
opMF (0x5d, read_addrx, eor)
opMF (0x5e, adjust_addrx, lsr)
opMF (0x5f, read_longx, eor)
opA (0x60, rts)
opMF (0x61, read_idpx, adc)
opE (0x62, per)
opMF (0x63, read_sr, adc)
opMI (0x64, write_dp, Z)
opMF (0x65, read_dp, adc)
opMF (0x66, adjust_dp, ror)
opMF (0x67, read_ildp, adc)
opMI (0x68, pull, A)
opMF (0x69, read_const, adc)
opM (0x6a, ror_imm)
opE (0x6b, rtl)
opA (0x6c, jmp_iaddr)
opMF (0x6d, read_addr, adc)
opMF (0x6e, adjust_addr, ror)
opMF (0x6f, read_long, adc)
opAII(0x70, branch, 0x40, true)
opMF (0x71, read_idpy, adc)
opMF (0x72, read_idp, adc)
opMF (0x73, read_isry, adc)
opMII(0x74, write_dpr, Z, X)
opMFI(0x75, read_dpr, adc, X)
opMF (0x76, adjust_dpx, ror)
opMF (0x77, read_ildpy, adc)
opAII(0x78, flag, 0x04, 0x04)
opMF (0x79, read_addry, adc)
opXI (0x7a, pull, Y)
opAII(0x7b, transfer_w, D, A)
opA (0x7c, jmp_iaddrx)
opMF (0x7d, read_addrx, adc)
opMF (0x7e, adjust_addrx, ror)
opMF (0x7f, read_longx, adc)
opA (0x80, bra)
opM (0x81, sta_idpx)
opA (0x82, brl)
opM (0x83, sta_sr)
opXI (0x84, write_dp, Y)
opMI (0x85, write_dp, A)
opXI (0x86, write_dp, X)
opM (0x87, sta_ildp)
opXII(0x88, adjust_imm, Y, -1)
opM (0x89, read_bit_const)
opMII(0x8a, transfer, X, A)
opA (0x8b, phb)
opXI (0x8c, write_addr, Y)
opMI (0x8d, write_addr, A)
opXI (0x8e, write_addr, X)
opMI (0x8f, write_longr, Z)
opAII(0x90, branch, 0x01, false)
opM (0x91, sta_idpy)
opM (0x92, sta_idp)
opM (0x93, sta_isry)
opXII(0x94, write_dpr, Y, X)
opMII(0x95, write_dpr, A, X)
opXII(0x96, write_dpr, X, Y)
opM (0x97, sta_ildpy)
opMII(0x98, transfer, Y, A)
opMII(0x99, write_addrr, A, Y)
opE (0x9a, txs)
opXII(0x9b, transfer, X, Y)
opMI (0x9c, write_addr, Z)
opMII(0x9d, write_addrr, A, X)
opMII(0x9e, write_addrr, Z, X)
opMI (0x9f, write_longr, X)
opXF (0xa0, read_const, ldy)
opMF (0xa1, read_idpx, lda)
opXF (0xa2, read_const, ldx)
opMF (0xa3, read_sr, lda)
opXF (0xa4, read_dp, ldy)
opMF (0xa5, read_dp, lda)
opXF (0xa6, read_dp, ldx)
opMF (0xa7, read_ildp, lda)
opXII(0xa8, transfer, A, Y)
opMF (0xa9, read_const, lda)
opXII(0xaa, transfer, A, X)
opA (0xab, plb)
opXF (0xac, read_addr, ldy)
opMF (0xad, read_addr, lda)
opXF (0xae, read_addr, ldx)
opMF (0xaf, read_long, lda)
opAII(0xb0, branch, 0x01, true)
opMF (0xb1, read_idpy, lda)
opMF (0xb2, read_idp, lda)
opMF (0xb3, read_isry, lda)
opXFI(0xb4, read_dpr, ldy, X)
opMFI(0xb5, read_dpr, lda, X)
opXFI(0xb6, read_dpr, ldx, Y)
opMF (0xb7, read_ildpy, lda)
opAII(0xb8, flag, 0x40, 0x00)
opMF (0xb9, read_addry, lda)
opX (0xba, tsx)
opXII(0xbb, transfer, Y, X)
opXF (0xbc, read_addrx, ldy)
opMF (0xbd, read_addrx, lda)
opXF (0xbe, read_addry, ldx)
opMF (0xbf, read_longx, lda)
opXF (0xc0, read_const, cpy)
opMF (0xc1, read_idpx, cmp)
opEI (0xc2, pflag, 0)
opMF (0xc3, read_sr, cmp)
opXF (0xc4, read_dp, cpy)
opMF (0xc5, read_dp, cmp)
opMF (0xc6, adjust_dp, dec)
opMF (0xc7, read_ildp, cmp)
opXII(0xc8, adjust_imm, Y, +1)
opMF (0xc9, read_const, cmp)
opXII(0xca, adjust_imm, X, -1)
opA (0xcb, wai)
opXF (0xcc, read_addr, cpy)
opMF (0xcd, read_addr, cmp)
opMF (0xce, adjust_addr, dec)
opMF (0xcf, read_long, cmp)
opAII(0xd0, branch, 0x02, false)
opMF (0xd1, read_idpy, cmp)
opMF (0xd2, read_idp, cmp)
opMF (0xd3, read_isry, cmp)
opE (0xd4, pei)
opMFI(0xd5, read_dpr, cmp, X)
opMF (0xd6, adjust_dpx, dec)
opMF (0xd7, read_ildpy, cmp)
opAII(0xd8, flag, 0x08, 0x00)
opMF (0xd9, read_addry, cmp)
opXI (0xda, push, X)
opA (0xdb, stp)
opA (0xdc, jmp_iladdr)
opMF (0xdd, read_addrx, cmp)
opMF (0xde, adjust_addrx, dec)
opMF (0xdf, read_longx, cmp)
opXF (0xe0, read_const, cpx)
opMF (0xe1, read_idpx, sbc)
opEI (0xe2, pflag, 1)
opMF (0xe3, read_sr, sbc)
opXF (0xe4, read_dp, cpx)
opMF (0xe5, read_dp, sbc)
opMF (0xe6, adjust_dp, inc)
opMF (0xe7, read_ildp, sbc)
opXII(0xe8, adjust_imm, X, +1)
opMF (0xe9, read_const, sbc)
opA (0xea, nop)
opA (0xeb, xba)
opXF (0xec, read_addr, cpx)
opMF (0xed, read_addr, sbc)
opMF (0xee, adjust_addr, inc)
opMF (0xef, read_long, sbc)
opAII(0xf0, branch, 0x02, true)
opMF (0xf1, read_idpy, sbc)
opMF (0xf2, read_idp, sbc)
opMF (0xf3, read_isry, sbc)
opE (0xf4, pea)
opMFI(0xf5, read_dpr, sbc, X)
opMF (0xf6, adjust_dpx, inc)
opMF (0xf7, read_ildpy, sbc)
opAII(0xf8, flag, 0x08, 0x08)
opMF (0xf9, read_addry, sbc)
opXI (0xfa, pull, X)
opA (0xfb, xce)
opE (0xfc, jsr_iaddrx)
opMF (0xfd, read_addrx, sbc)
opMF (0xfe, adjust_addrx, inc)
opMF (0xff, read_longx, sbc)
#undef opA
#undef opAII
#undef opE
#undef opEI
#undef opEII
#undef opM
#undef opMI
#undef opMII
#undef opMF
#undef opMFI
#undef opX
#undef opXI
#undef opXII
#undef opXF
#undef opXFI
}
void CPUcore::update_table() {
if(regs.e) {
opcode_table = &op_table[table_EM];
} else if(regs.p.m) {
if(regs.p.x) {
opcode_table = &op_table[table_MX];
} else {
opcode_table = &op_table[table_Mx];
}
} else {
if(regs.p.x) {
opcode_table = &op_table[table_mX];
} else {
opcode_table = &op_table[table_mx];
}
}
}
#endif

View File

@ -5,6 +5,7 @@ namespace SNES {
CPU cpu;
#include "serialization.cpp"
#include "dma.cpp"
#include "memory.cpp"
#include "mmio.cpp"
@ -20,11 +21,19 @@ void CPU::step(unsigned clocks) {
}
void CPU::synchronize_smp() {
while(smp.clock < 0) smp.run();
if(SMP::Threaded == true) {
if(smp.clock < 0) co_switch(smp.thread);
} else {
while(smp.clock < 0) smp.enter();
}
}
void CPU::synchronize_ppu() {
if(ppu.clock < 0) co_switch(ppu.thread);
if(PPU::Threaded == true) {
if(ppu.clock < 0) co_switch(ppu.thread);
} else {
while(ppu.clock < 0) ppu.enter();
}
}
void CPU::synchronize_coprocessor() {
@ -139,9 +148,6 @@ void CPU::reset() {
dma_reset();
}
void CPU::serialize(serializer &s) {
}
CPU::CPU() : queue(512, { &CPU::queue_event, this }) {
PPUcounter::scanline = { &CPU::scanline, this };
}

View File

@ -1,7 +1,6 @@
#include <nall/priorityqueue.hpp>
class CPU : public Processor, public CPUcore, public PPUcounter, public MMIO {
public:
enum : bool { Threaded = true };
array<Processor*> coprocessors;
alwaysinline void step(unsigned clocks);
alwaysinline void synchronize_smp();
@ -20,6 +19,7 @@ public:
uint8 op_read(unsigned addr);
void op_write(unsigned addr, uint8 data);
void enter();
void power();
void reset();
@ -30,7 +30,6 @@ public:
private:
//cpu
static void Enter();
void enter();
void op_irq(uint16 vector);
//timing

View File

@ -102,7 +102,7 @@ void CPU::mmio_write(unsigned addr, uint8 data) {
if((addr & 0xffc0) == 0x2140) {
synchronize_smp();
smp.port_write(addr & 3, data);
port_write(addr & 3, data);
return;
}

84
snes/fast/cpu/serialization.cpp Executable file
View File

@ -0,0 +1,84 @@
#ifdef CPU_CPP
void CPU::serialize(serializer &s) {
Processor::serialize(s);
CPUcore::core_serialize(s);
PPUcounter::serialize(s);
queue.serialize(s);
s.array(port_data);
for(unsigned i = 0; i < 8; i++) {
s.integer(channel[i].dma_enabled);
s.integer(channel[i].hdma_enabled);
s.integer(channel[i].direction);
s.integer(channel[i].indirect);
s.integer(channel[i].unused);
s.integer(channel[i].reverse_transfer);
s.integer(channel[i].fixed_transfer);
s.integer(channel[i].transfer_mode);
s.integer(channel[i].dest_addr);
s.integer(channel[i].source_addr);
s.integer(channel[i].source_bank);
s.integer(channel[i].transfer_size);
s.integer(channel[i].indirect_bank);
s.integer(channel[i].hdma_addr);
s.integer(channel[i].line_counter);
s.integer(channel[i].unknown);
s.integer(channel[i].hdma_completed);
s.integer(channel[i].hdma_do_transfer);
}
s.integer(status.nmi_valid);
s.integer(status.nmi_line);
s.integer(status.nmi_transition);
s.integer(status.nmi_pending);
s.integer(status.irq_valid);
s.integer(status.irq_line);
s.integer(status.irq_transition);
s.integer(status.irq_pending);
s.integer(status.irq_lock);
s.integer(status.hdma_pending);
s.integer(status.wram_addr);
s.integer(status.joypad_strobe_latch);
s.integer(status.nmi_enabled);
s.integer(status.virq_enabled);
s.integer(status.hirq_enabled);
s.integer(status.auto_joypad_poll_enabled);
s.integer(status.pio);
s.integer(status.wrmpya);
s.integer(status.wrmpyb);
s.integer(status.wrdiva);
s.integer(status.wrdivb);
s.integer(status.htime);
s.integer(status.vtime);
s.integer(status.rom_speed);
s.integer(status.rddiv);
s.integer(status.rdmpy);
s.integer(status.joy1l);
s.integer(status.joy1h);
s.integer(status.joy2l);
s.integer(status.joy2h);
s.integer(status.joy3l);
s.integer(status.joy3h);
s.integer(status.joy4l);
s.integer(status.joy4h);
}
#endif

View File

@ -5,9 +5,7 @@ namespace SNES {
DSP dsp;
#if !defined(PROFILE_CSNES)
#include "../snes_spc/SPC_DSP.cpp"
#endif
#include "../snes_spc/SPC_DSP.cpp"
#include "serialization.cpp"
@ -16,9 +14,14 @@ void DSP::step(unsigned clocks) {
}
void DSP::synchronize_smp() {
if(SMP::Threaded == true) {
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(smp.thread);
} else {
while(clock >= 0) smp.enter();
}
}
void DSP::run() {
void DSP::enter() {
spc_dsp.run(1);
step(24);

View File

@ -1,16 +1,15 @@
#if !defined(PROFILE_CSNES)
#include "../snes_spc/SPC_DSP.h"
#endif
#include "../snes_spc/SPC_DSP.h"
class DSP : public Processor {
public:
enum : bool { Threaded = false };
alwaysinline void step(unsigned clocks);
alwaysinline void synchronize_smp();
void run();
uint8 read(uint8 addr);
void write(uint8 addr, uint8 data);
void enter();
void power();
void reset();

View File

@ -1,8 +1,31 @@
#ifdef DSP_CPP
static void dsp_state_save(unsigned char **out, void *in, size_t size) {
memcpy(*out, in, size);
*out += size;
}
static void dsp_state_load(unsigned char **in, void *out, size_t size) {
memcpy(out, *in, size);
*in += size;
}
void DSP::serialize(serializer &s) {
Processor::serialize(s);
s.array(samplebuffer);
unsigned char state[SPC_DSP::state_size];
unsigned char *p = state;
memset(&state, 0, SPC_DSP::state_size);
if(s.mode() == serializer::Save) {
spc_dsp.copy_state(&p, dsp_state_save);
s.array(state);
} else if(s.mode() == serializer::Load) {
s.array(state);
spc_dsp.copy_state(&p, dsp_state_load);
} else {
s.array(state);
}
}
#endif

View File

@ -20,7 +20,11 @@ void PPU::step(unsigned clocks) {
}
void PPU::synchronize_cpu() {
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread);
if(CPU::Threaded == true) {
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread);
} else {
while(clock >= 0) cpu.enter();
}
}
void PPU::Enter() { ppu.enter(); }

View File

@ -1,5 +1,9 @@
class PPU : public Processor, public PPUcounter, public MMIO {
public:
enum : bool { Threaded = true };
alwaysinline void step(unsigned clocks);
alwaysinline void synchronize_cpu();
#include "memory/memory.hpp"
#include "mmio/mmio.hpp"
#include "render/render.hpp"
@ -10,12 +14,7 @@ public:
uint8 ppu1_version;
uint8 ppu2_version;
//synchronization
alwaysinline void step(unsigned clocks);
alwaysinline void synchronize_cpu();
static void Enter();
void enter();
void add_clocks(unsigned clocks);
uint8 region;
@ -56,6 +55,7 @@ public:
void scanline();
void render_scanline();
void frame();
void enter();
void power();
void reset();

View File

@ -1,126 +0,0 @@
#ifdef SMPCORE_CPP
uint8 SMPcore::op_adc(uint8 x, uint8 y) {
int r = x + y + regs.p.c;
regs.p.n = r & 0x80;
regs.p.v = ~(x ^ y) & (x ^ r) & 0x80;
regs.p.h = (x ^ y ^ r) & 0x10;
regs.p.z = (uint8)r == 0;
regs.p.c = r > 0xff;
return r;
}
uint16 SMPcore::op_addw(uint16 x, uint16 y) {
uint16 r;
regs.p.c = 0;
r = op_adc(x, y);
r |= op_adc(x >> 8, y >> 8) << 8;
regs.p.z = r == 0;
return r;
}
uint8 SMPcore::op_and(uint8 x, uint8 y) {
x &= y;
regs.p.n = x & 0x80;
regs.p.z = x == 0;
return x;
}
uint8 SMPcore::op_cmp(uint8 x, uint8 y) {
int r = x - y;
regs.p.n = r & 0x80;
regs.p.z = (uint8)r == 0;
regs.p.c = r >= 0;
return x;
}
uint16 SMPcore::op_cmpw(uint16 x, uint16 y) {
int r = x - y;
regs.p.n = r & 0x8000;
regs.p.z = (uint16)r == 0;
regs.p.c = r >= 0;
return x;
}
uint8 SMPcore::op_eor(uint8 x, uint8 y) {
x ^= y;
regs.p.n = x & 0x80;
regs.p.z = x == 0;
return x;
}
uint8 SMPcore::op_or(uint8 x, uint8 y) {
x |= y;
regs.p.n = x & 0x80;
regs.p.z = x == 0;
return x;
}
uint8 SMPcore::op_sbc(uint8 x, uint8 y) {
int r = x - y - !regs.p.c;
regs.p.n = r & 0x80;
regs.p.v = (x ^ y) & (x ^ r) & 0x80;
regs.p.h = !((x ^ y ^ r) & 0x10);
regs.p.z = (uint8)r == 0;
regs.p.c = r >= 0;
return r;
}
uint16 SMPcore::op_subw(uint16 x, uint16 y) {
uint16 r;
regs.p.c = 1;
r = op_sbc(x, y);
r |= op_sbc(x >> 8, y >> 8) << 8;
regs.p.z = r == 0;
return r;
}
uint8 SMPcore::op_inc(uint8 x) {
x++;
regs.p.n = x & 0x80;
regs.p.z = x == 0;
return x;
}
uint8 SMPcore::op_dec(uint8 x) {
x--;
regs.p.n = x & 0x80;
regs.p.z = x == 0;
return x;
}
uint8 SMPcore::op_asl(uint8 x) {
regs.p.c = x & 0x80;
x <<= 1;
regs.p.n = x & 0x80;
regs.p.z = x == 0;
return x;
}
uint8 SMPcore::op_lsr(uint8 x) {
regs.p.c = x & 0x01;
x >>= 1;
regs.p.n = x & 0x80;
regs.p.z = x == 0;
return x;
}
uint8 SMPcore::op_rol(uint8 x) {
unsigned carry = (unsigned)regs.p.c;
regs.p.c = x & 0x80;
x = (x << 1) | carry;
regs.p.n = x & 0x80;
regs.p.z = x == 0;
return x;
}
uint8 SMPcore::op_ror(uint8 x) {
unsigned carry = (unsigned)regs.p.c << 7;
regs.p.c = x & 0x01;
x = carry | (x >> 1);
regs.p.n = x & 0x80;
regs.p.z = x == 0;
return x;
}
#endif

View File

@ -1,31 +0,0 @@
#include <snes.hpp>
#define SMPCORE_CPP
namespace SNES {
#include "serialization.cpp"
#include "algorithms.cpp"
#include "disassembler/disassembler.cpp"
#define A 0
#define X 1
#define Y 2
#define SP 3
#include "opcode_mov.cpp"
#include "opcode_pc.cpp"
#include "opcode_read.cpp"
#include "opcode_rmw.cpp"
#include "opcode_misc.cpp"
#include "table.cpp"
#undef A
#undef X
#undef Y
#undef SP
SMPcore::SMPcore() {
initialize_opcode_table();
}
}

View File

@ -1,118 +0,0 @@
class SMPcore {
public:
#include "registers.hpp"
#include "memory.hpp"
#include "disassembler/disassembler.hpp"
regs_t regs;
uint16 dp, sp, rd, wr, bit, ya;
virtual void op_io() = 0;
virtual uint8 op_read(uint16 addr) = 0;
virtual void op_write(uint16 addr, uint8 data) = 0;
uint8 op_adc (uint8 x, uint8 y);
uint16 op_addw(uint16 x, uint16 y);
uint8 op_and (uint8 x, uint8 y);
uint8 op_cmp (uint8 x, uint8 y);
uint16 op_cmpw(uint16 x, uint16 y);
uint8 op_eor (uint8 x, uint8 y);
uint8 op_inc (uint8 x);
uint8 op_dec (uint8 x);
uint8 op_or (uint8 x, uint8 y);
uint8 op_sbc (uint8 x, uint8 y);
uint16 op_subw(uint16 x, uint16 y);
uint8 op_asl (uint8 x);
uint8 op_lsr (uint8 x);
uint8 op_rol (uint8 x);
uint8 op_ror (uint8 x);
template<int, int> void op_mov_reg_reg();
void op_mov_sp_x();
template<int> void op_mov_reg_const();
void op_mov_a_ix();
void op_mov_a_ixinc();
template<int> void op_mov_reg_dp();
template<int, int> void op_mov_reg_dpr();
template<int> void op_mov_reg_addr();
template<int> void op_mov_a_addrr();
void op_mov_a_idpx();
void op_mov_a_idpy();
void op_mov_dp_dp();
void op_mov_dp_const();
void op_mov_ix_a();
void op_mov_ixinc_a();
template<int> void op_mov_dp_reg();
template<int, int> void op_mov_dpr_reg();
template<int> void op_mov_addr_reg();
template<int> void op_mov_addrr_a();
void op_mov_idpx_a();
void op_mov_idpy_a();
void op_movw_ya_dp();
void op_movw_dp_ya();
void op_mov1_c_bit();
void op_mov1_bit_c();
void op_bra();
template<int, int> void op_branch();
template<int, int> void op_bitbranch();
void op_cbne_dp();
void op_cbne_dpx();
void op_dbnz_dp();
void op_dbnz_y();
void op_jmp_addr();
void op_jmp_iaddrx();
void op_call();
void op_pcall();
template<int> void op_tcall();
void op_brk();
void op_ret();
void op_reti();
template<uint8 (SMPcore::*)(uint8, uint8), int> void op_read_reg_const();
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_a_ix();
template<uint8 (SMPcore::*)(uint8, uint8), int> void op_read_reg_dp();
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_a_dpx();
template<uint8 (SMPcore::*)(uint8, uint8), int> void op_read_reg_addr();
template<uint8 (SMPcore::*)(uint8, uint8), int> void op_read_a_addrr();
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_a_idpx();
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_a_idpy();
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_ix_iy();
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_dp_dp();
template<uint8 (SMPcore::*)(uint8, uint8)> void op_read_dp_const();
template<uint16 (SMPcore::*)(uint16, uint16)> void op_read_ya_dp();
void op_cmpw_ya_dp();
template<int> void op_and1_bit();
void op_eor1_bit();
void op_not1_bit();
template<int> void op_or1_bit();
template<uint8 (SMPcore::*)(uint8), int> void op_adjust_reg();
template<uint8 (SMPcore::*)(uint8)> void op_adjust_dp();
template<uint8 (SMPcore::*)(uint8)> void op_adjust_dpx();
template<uint8 (SMPcore::*)(uint8)> void op_adjust_addr();
template<int> void op_adjust_addr_a();
template<int> void op_adjustw_dp();
void op_nop();
void op_wait();
void op_xcn();
void op_daa();
void op_das();
template<int, int> void op_setbit();
void op_notc();
template<int> void op_seti();
template<int, int> void op_setbit_dp();
template<int> void op_push_reg();
void op_push_p();
template<int> void op_pop_reg();
void op_pop_p();
void op_mul_ya();
void op_div_ya_x();
void (SMPcore::*opcode_table[256])();
void initialize_opcode_table();
void core_serialize(serializer&);
SMPcore();
};

View File

@ -1,315 +0,0 @@
#ifdef SMPCORE_CPP
uint8 SMPcore::disassemble_read(uint16 addr) {
if(addr >= 0xffc0) {
#if defined(DEBUGGER)
if(smp.iplrom_enable()) return smp.iplrom[addr & 0x3f];
#else
//unable to determine if IPLROM is enabled, assume that it is
return smp.iplrom[addr & 0x3f];
#endif
}
return memory::apuram[addr];
}
uint16 SMPcore::relb(int8 offset, int op_len) {
uint16 pc = regs.pc + op_len;
return pc + offset;
}
void SMPcore::disassemble_opcode(char *output, uint16 addr) {
char *s, t[512];
uint8 op, op0, op1;
uint16 opw, opdp0, opdp1;
s = output;
sprintf(s, "..%.4x ", addr);
op = disassemble_read(addr + 0);
op0 = disassemble_read(addr + 1);
op1 = disassemble_read(addr + 2);
opw = (op0) | (op1 << 8);
opdp0 = ((unsigned)regs.p.p << 8) + op0;
opdp1 = ((unsigned)regs.p.p << 8) + op1;
strcpy(t, " ");
switch(op) {
case 0x00: sprintf(t, "nop"); break;
case 0x01: sprintf(t, "tcall 0"); break;
case 0x02: sprintf(t, "set0 $%.3x", opdp0); break;
case 0x03: sprintf(t, "bbs0 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
case 0x04: sprintf(t, "or a,$%.3x", opdp0); break;
case 0x05: sprintf(t, "or a,$%.4x", opw); break;
case 0x06: sprintf(t, "or a,(x)"); break;
case 0x07: sprintf(t, "or a,($%.3x+x)", opdp0); break;
case 0x08: sprintf(t, "or a,#$%.2x", op0); break;
case 0x09: sprintf(t, "or $%.3x,$%.3x", opdp1, opdp0); break;
case 0x0a: sprintf(t, "or1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x0b: sprintf(t, "asl $%.3x", opdp0); break;
case 0x0c: sprintf(t, "asl $%.4x", opw); break;
case 0x0d: sprintf(t, "push p"); break;
case 0x0e: sprintf(t, "tset $%.4x,a", opw); break;
case 0x0f: sprintf(t, "brk"); break;
case 0x10: sprintf(t, "bpl $%.4x", relb(op0, 2)); break;
case 0x11: sprintf(t, "tcall 1"); break;
case 0x12: sprintf(t, "clr0 $%.3x", opdp0); break;
case 0x13: sprintf(t, "bbc0 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
case 0x14: sprintf(t, "or a,$%.3x+x", opdp0); break;
case 0x15: sprintf(t, "or a,$%.4x+x", opw); break;
case 0x16: sprintf(t, "or a,$%.4x+y", opw); break;
case 0x17: sprintf(t, "or a,($%.3x)+y", opdp0); break;
case 0x18: sprintf(t, "or $%.3x,#$%.2x", opdp1, op0); break;
case 0x19: sprintf(t, "or (x),(y)"); break;
case 0x1a: sprintf(t, "decw $%.3x", opdp0); break;
case 0x1b: sprintf(t, "asl $%.3x+x", opdp0); break;
case 0x1c: sprintf(t, "asl a"); break;
case 0x1d: sprintf(t, "dec x"); break;
case 0x1e: sprintf(t, "cmp x,$%.4x", opw); break;
case 0x1f: sprintf(t, "jmp ($%.4x+x)", opw); break;
case 0x20: sprintf(t, "clrp"); break;
case 0x21: sprintf(t, "tcall 2"); break;
case 0x22: sprintf(t, "set1 $%.3x", opdp0); break;
case 0x23: sprintf(t, "bbs1 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
case 0x24: sprintf(t, "and a,$%.3x", opdp0); break;
case 0x25: sprintf(t, "and a,$%.4x", opw); break;
case 0x26: sprintf(t, "and a,(x)"); break;
case 0x27: sprintf(t, "and a,($%.3x+x)", opdp0); break;
case 0x28: sprintf(t, "and a,#$%.2x", op0); break;
case 0x29: sprintf(t, "and $%.3x,$%.3x", opdp1, opdp0); break;
case 0x2a: sprintf(t, "or1 c,!$%.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x2b: sprintf(t, "rol $%.3x", opdp0); break;
case 0x2c: sprintf(t, "rol $%.4x", opw); break;
case 0x2d: sprintf(t, "push a"); break;
case 0x2e: sprintf(t, "cbne $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
case 0x2f: sprintf(t, "bra $%.4x", relb(op0, 2)); break;
case 0x30: sprintf(t, "bmi $%.4x", relb(op0, 2)); break;
case 0x31: sprintf(t, "tcall 3"); break;
case 0x32: sprintf(t, "clr1 $%.3x", opdp0); break;
case 0x33: sprintf(t, "bbc1 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
case 0x34: sprintf(t, "and a,$%.3x+x", opdp0); break;
case 0x35: sprintf(t, "and a,$%.4x+x", opw); break;
case 0x36: sprintf(t, "and a,$%.4x+y", opw); break;
case 0x37: sprintf(t, "and a,($%.3x)+y", opdp0); break;
case 0x38: sprintf(t, "and $%.3x,#$%.2x", opdp1, op0); break;
case 0x39: sprintf(t, "and (x),(y)"); break;
case 0x3a: sprintf(t, "incw $%.3x", opdp0); break;
case 0x3b: sprintf(t, "rol $%.3x+x", opdp0); break;
case 0x3c: sprintf(t, "rol a"); break;
case 0x3d: sprintf(t, "inc x"); break;
case 0x3e: sprintf(t, "cmp x,$%.3x", opdp0); break;
case 0x3f: sprintf(t, "call $%.4x", opw); break;
case 0x40: sprintf(t, "setp"); break;
case 0x41: sprintf(t, "tcall 4"); break;
case 0x42: sprintf(t, "set2 $%.3x", opdp0); break;
case 0x43: sprintf(t, "bbs2 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
case 0x44: sprintf(t, "eor a,$%.3x", opdp0); break;
case 0x45: sprintf(t, "eor a,$%.4x", opw); break;
case 0x46: sprintf(t, "eor a,(x)"); break;
case 0x47: sprintf(t, "eor a,($%.3x+x)", opdp0); break;
case 0x48: sprintf(t, "eor a,#$%.2x", op0); break;
case 0x49: sprintf(t, "eor $%.3x,$%.3x", opdp1, opdp0); break;
case 0x4a: sprintf(t, "and1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x4b: sprintf(t, "lsr $%.3x", opdp0); break;
case 0x4c: sprintf(t, "lsr $%.4x", opw); break;
case 0x4d: sprintf(t, "push x"); break;
case 0x4e: sprintf(t, "tclr $%.4x,a", opw); break;
case 0x4f: sprintf(t, "pcall $ff%.2x", op0); break;
case 0x50: sprintf(t, "bvc $%.4x", relb(op0, 2)); break;
case 0x51: sprintf(t, "tcall 5"); break;
case 0x52: sprintf(t, "clr2 $%.3x", opdp0); break;
case 0x53: sprintf(t, "bbc2 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
case 0x54: sprintf(t, "eor a,$%.3x+x", opdp0); break;
case 0x55: sprintf(t, "eor a,$%.4x+x", opw); break;
case 0x56: sprintf(t, "eor a,$%.4x+y", opw); break;
case 0x57: sprintf(t, "eor a,($%.3x)+y", opdp0); break;
case 0x58: sprintf(t, "eor $%.3x,#$%.2x", opdp1, op0); break;
case 0x59: sprintf(t, "eor (x),(y)"); break;
case 0x5a: sprintf(t, "cmpw ya,$%.3x", opdp0); break;
case 0x5b: sprintf(t, "lsr $%.3x+x", opdp0); break;
case 0x5c: sprintf(t, "lsr a"); break;
case 0x5d: sprintf(t, "mov x,a"); break;
case 0x5e: sprintf(t, "cmp y,$%.4x", opw); break;
case 0x5f: sprintf(t, "jmp $%.4x", opw); break;
case 0x60: sprintf(t, "clrc"); break;
case 0x61: sprintf(t, "tcall 6"); break;
case 0x62: sprintf(t, "set3 $%.3x", opdp0); break;
case 0x63: sprintf(t, "bbs3 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
case 0x64: sprintf(t, "cmp a,$%.3x", opdp0); break;
case 0x65: sprintf(t, "cmp a,$%.4x", opw); break;
case 0x66: sprintf(t, "cmp a,(x)"); break;
case 0x67: sprintf(t, "cmp a,($%.3x+x)", opdp0); break;
case 0x68: sprintf(t, "cmp a,#$%.2x", op0); break;
case 0x69: sprintf(t, "cmp $%.3x,$%.3x", opdp1, opdp0); break;
case 0x6a: sprintf(t, "and1 c,!$%.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x6b: sprintf(t, "ror $%.3x", opdp0); break;
case 0x6c: sprintf(t, "ror $%.4x", opw); break;
case 0x6d: sprintf(t, "push y"); break;
case 0x6e: sprintf(t, "dbnz $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
case 0x6f: sprintf(t, "ret"); break;
case 0x70: sprintf(t, "bvs $%.4x", relb(op0, 2)); break;
case 0x71: sprintf(t, "tcall 7"); break;
case 0x72: sprintf(t, "clr3 $%.3x", opdp0); break;
case 0x73: sprintf(t, "bbc3 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
case 0x74: sprintf(t, "cmp a,$%.3x+x", opdp0); break;
case 0x75: sprintf(t, "cmp a,$%.4x+x", opw); break;
case 0x76: sprintf(t, "cmp a,$%.4x+y", opw); break;
case 0x77: sprintf(t, "cmp a,($%.3x)+y", opdp0); break;
case 0x78: sprintf(t, "cmp $%.3x,#$%.2x", opdp1, op0); break;
case 0x79: sprintf(t, "cmp (x),(y)"); break;
case 0x7a: sprintf(t, "addw ya,$%.3x", opdp0); break;
case 0x7b: sprintf(t, "ror $%.3x+x", opdp0); break;
case 0x7c: sprintf(t, "ror a"); break;
case 0x7d: sprintf(t, "mov a,x"); break;
case 0x7e: sprintf(t, "cmp y,$%.3x", opdp0); break;
case 0x7f: sprintf(t, "reti"); break;
case 0x80: sprintf(t, "setc"); break;
case 0x81: sprintf(t, "tcall 8"); break;
case 0x82: sprintf(t, "set4 $%.3x", opdp0); break;
case 0x83: sprintf(t, "bbs4 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
case 0x84: sprintf(t, "adc a,$%.3x", opdp0); break;
case 0x85: sprintf(t, "adc a,$%.4x", opw); break;
case 0x86: sprintf(t, "adc a,(x)"); break;
case 0x87: sprintf(t, "adc a,($%.3x+x)", opdp0); break;
case 0x88: sprintf(t, "adc a,#$%.2x", op0); break;
case 0x89: sprintf(t, "adc $%.3x,$%.3x", opdp1, opdp0); break;
case 0x8a: sprintf(t, "eor1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x8b: sprintf(t, "dec $%.3x", opdp0); break;
case 0x8c: sprintf(t, "dec $%.4x", opw); break;
case 0x8d: sprintf(t, "mov y,#$%.2x", op0); break;
case 0x8e: sprintf(t, "pop p"); break;
case 0x8f: sprintf(t, "mov $%.3x,#$%.2x", opdp1, op0); break;
case 0x90: sprintf(t, "bcc $%.4x", relb(op0, 2)); break;
case 0x91: sprintf(t, "tcall 9"); break;
case 0x92: sprintf(t, "clr4 $%.3x", opdp0); break;
case 0x93: sprintf(t, "bbc4 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
case 0x94: sprintf(t, "adc a,$%.3x+x", opdp0); break;
case 0x95: sprintf(t, "adc a,$%.4x+x", opw); break;
case 0x96: sprintf(t, "adc a,$%.4x+y", opw); break;
case 0x97: sprintf(t, "adc a,($%.3x)+y", opdp0); break;
case 0x98: sprintf(t, "adc $%.3x,#$%.2x", opdp1, op0); break;
case 0x99: sprintf(t, "adc (x),(y)"); break;
case 0x9a: sprintf(t, "subw ya,$%.3x", opdp0); break;
case 0x9b: sprintf(t, "dec $%.3x+x", opdp0); break;
case 0x9c: sprintf(t, "dec a"); break;
case 0x9d: sprintf(t, "mov x,sp"); break;
case 0x9e: sprintf(t, "div ya,x"); break;
case 0x9f: sprintf(t, "xcn a"); break;
case 0xa0: sprintf(t, "ei"); break;
case 0xa1: sprintf(t, "tcall 10"); break;
case 0xa2: sprintf(t, "set5 $%.3x", opdp0); break;
case 0xa3: sprintf(t, "bbs5 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
case 0xa4: sprintf(t, "sbc a,$%.3x", opdp0); break;
case 0xa5: sprintf(t, "sbc a,$%.4x", opw); break;
case 0xa6: sprintf(t, "sbc a,(x)"); break;
case 0xa7: sprintf(t, "sbc a,($%.3x+x)", opdp0); break;
case 0xa8: sprintf(t, "sbc a,#$%.2x", op0); break;
case 0xa9: sprintf(t, "sbc $%.3x,$%.3x", opdp1, opdp0); break;
case 0xaa: sprintf(t, "mov1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0xab: sprintf(t, "inc $%.3x", opdp0); break;
case 0xac: sprintf(t, "inc $%.4x", opw); break;
case 0xad: sprintf(t, "cmp y,#$%.2x", op0); break;
case 0xae: sprintf(t, "pop a"); break;
case 0xaf: sprintf(t, "mov (x)+,a"); break;
case 0xb0: sprintf(t, "bcs $%.4x", relb(op0, 2)); break;
case 0xb1: sprintf(t, "tcall 11"); break;
case 0xb2: sprintf(t, "clr5 $%.3x", opdp0); break;
case 0xb3: sprintf(t, "bbc5 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
case 0xb4: sprintf(t, "sbc a,$%.3x+x", opdp0); break;
case 0xb5: sprintf(t, "sbc a,$%.4x+x", opw); break;
case 0xb6: sprintf(t, "sbc a,$%.4x+y", opw); break;
case 0xb7: sprintf(t, "sbc a,($%.3x)+y", opdp0); break;
case 0xb8: sprintf(t, "sbc $%.3x,#$%.2x", opdp1, op0); break;
case 0xb9: sprintf(t, "sbc (x),(y)"); break;
case 0xba: sprintf(t, "movw ya,$%.3x", opdp0); break;
case 0xbb: sprintf(t, "inc $%.3x+x", opdp0); break;
case 0xbc: sprintf(t, "inc a"); break;
case 0xbd: sprintf(t, "mov sp,x"); break;
case 0xbe: sprintf(t, "das a"); break;
case 0xbf: sprintf(t, "mov a,(x)+"); break;
case 0xc0: sprintf(t, "di"); break;
case 0xc1: sprintf(t, "tcall 12"); break;
case 0xc2: sprintf(t, "set6 $%.3x", opdp0); break;
case 0xc3: sprintf(t, "bbs6 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
case 0xc4: sprintf(t, "mov $%.3x,a", opdp0); break;
case 0xc5: sprintf(t, "mov $%.4x,a", opw); break;
case 0xc6: sprintf(t, "mov (x),a"); break;
case 0xc7: sprintf(t, "mov ($%.3x+x),a", opdp0); break;
case 0xc8: sprintf(t, "cmp x,#$%.2x", op0); break;
case 0xc9: sprintf(t, "mov $%.4x,x", opw); break;
case 0xca: sprintf(t, "mov1 $%.4x:%d,c", opw & 0x1fff, opw >> 13); break;
case 0xcb: sprintf(t, "mov $%.3x,y", opdp0); break;
case 0xcc: sprintf(t, "mov $%.4x,y", opw); break;
case 0xcd: sprintf(t, "mov x,#$%.2x", op0); break;
case 0xce: sprintf(t, "pop x"); break;
case 0xcf: sprintf(t, "mul ya"); break;
case 0xd0: sprintf(t, "bne $%.4x", relb(op0, 2)); break;
case 0xd1: sprintf(t, "tcall 13"); break;
case 0xd2: sprintf(t, "clr6 $%.3x", opdp0); break;
case 0xd3: sprintf(t, "bbc6 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
case 0xd4: sprintf(t, "mov $%.3x+x,a", opdp0); break;
case 0xd5: sprintf(t, "mov $%.4x+x,a", opw); break;
case 0xd6: sprintf(t, "mov $%.4x+y,a", opw); break;
case 0xd7: sprintf(t, "mov ($%.3x)+y,a", opdp0); break;
case 0xd8: sprintf(t, "mov $%.3x,x", opdp0); break;
case 0xd9: sprintf(t, "mov $%.3x+y,x", opdp0); break;
case 0xda: sprintf(t, "movw $%.3x,ya", opdp0); break;
case 0xdb: sprintf(t, "mov $%.3x+x,y", opdp0); break;
case 0xdc: sprintf(t, "dec y"); break;
case 0xdd: sprintf(t, "mov a,y"); break;
case 0xde: sprintf(t, "cbne $%.3x+x,$%.4x", opdp0, relb(op1, 3)); break;
case 0xdf: sprintf(t, "daa a"); break;
case 0xe0: sprintf(t, "clrv"); break;
case 0xe1: sprintf(t, "tcall 14"); break;
case 0xe2: sprintf(t, "set7 $%.3x", opdp0); break;
case 0xe3: sprintf(t, "bbs7 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
case 0xe4: sprintf(t, "mov a,$%.3x", opdp0); break;
case 0xe5: sprintf(t, "mov a,$%.4x", opw); break;
case 0xe6: sprintf(t, "mov a,(x)"); break;
case 0xe7: sprintf(t, "mov a,($%.3x+x)", opdp0); break;
case 0xe8: sprintf(t, "mov a,#$%.2x", op0); break;
case 0xe9: sprintf(t, "mov x,$%.4x", opw); break;
case 0xea: sprintf(t, "not1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0xeb: sprintf(t, "mov y,$%.3x", opdp0); break;
case 0xec: sprintf(t, "mov y,$%.4x", opw); break;
case 0xed: sprintf(t, "notc"); break;
case 0xee: sprintf(t, "pop y"); break;
case 0xef: sprintf(t, "sleep"); break;
case 0xf0: sprintf(t, "beq $%.4x", relb(op0, 2)); break;
case 0xf1: sprintf(t, "tcall 15"); break;
case 0xf2: sprintf(t, "clr7 $%.3x", opdp0); break;
case 0xf3: sprintf(t, "bbc7 $%.3x,$%.4x", opdp0, relb(op1, 3)); break;
case 0xf4: sprintf(t, "mov a,$%.3x+x", opdp0); break;
case 0xf5: sprintf(t, "mov a,$%.4x+x", opw); break;
case 0xf6: sprintf(t, "mov a,$%.4x+y", opw); break;
case 0xf7: sprintf(t, "mov a,($%.3x)+y", opdp0); break;
case 0xf8: sprintf(t, "mov x,$%.3x", opdp0); break;
case 0xf9: sprintf(t, "mov x,$%.3x+y", opdp0); break;
case 0xfa: sprintf(t, "mov $%.3x,$%.3x", opdp1, opdp0); break;
case 0xfb: sprintf(t, "mov y,$%.3x+x", opdp0); break;
case 0xfc: sprintf(t, "inc y"); break;
case 0xfd: sprintf(t, "mov y,a"); break;
case 0xfe: sprintf(t, "dbnz y,$%.4x", relb(op0, 2)); break;
case 0xff: sprintf(t, "stop"); break;
}
t[strlen(t)] = ' ';
strcat(s, t);
sprintf(t, "A:%.2x X:%.2x Y:%.2x SP:01%.2x YA:%.4x ",
regs.a, regs.x, regs.y, regs.sp, (uint16)regs.ya);
strcat(s, t);
sprintf(t, "%c%c%c%c%c%c%c%c",
regs.p.n ? 'N' : 'n',
regs.p.v ? 'V' : 'v',
regs.p.p ? 'P' : 'p',
regs.p.b ? 'B' : 'b',
regs.p.h ? 'H' : 'h',
regs.p.i ? 'I' : 'i',
regs.p.z ? 'Z' : 'z',
regs.p.c ? 'C' : 'c');
strcat(s, t);
}
#endif

View File

@ -1,3 +0,0 @@
void disassemble_opcode(char *output, uint16 addr);
inline uint8 disassemble_read(uint16 addr);
inline uint16 relb(int8 offset, int op_len);

View File

@ -1,27 +0,0 @@
alwaysinline uint8_t op_readpc() {
return op_read(regs.pc++);
}
alwaysinline uint8_t op_readstack() {
return op_read(0x0100 | ++regs.sp);
}
alwaysinline void op_writestack(uint8_t data) {
op_write(0x0100 | regs.sp--, data);
}
alwaysinline uint8_t op_readaddr(uint16_t addr) {
return op_read(addr);
}
alwaysinline void op_writeaddr(uint16_t addr, uint8_t data) {
op_write(addr, data);
}
alwaysinline uint8_t op_readdp(uint8_t addr) {
return op_read(((unsigned)regs.p.p << 8) + addr);
}
alwaysinline void op_writedp(uint8_t addr, uint8_t data) {
op_write(((unsigned)regs.p.p << 8) + addr, data);
}

View File

@ -1,148 +0,0 @@
#ifdef SMPCORE_CPP
void SMPcore::op_nop() {
op_io();
}
void SMPcore::op_wait() {
while(true) {
op_io();
op_io();
}
}
void SMPcore::op_xcn() {
op_io();
op_io();
op_io();
op_io();
regs.a = (regs.a >> 4) | (regs.a << 4);
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
void SMPcore::op_daa() {
op_io();
op_io();
if(regs.p.c || (regs.a) > 0x99) {
regs.a += 0x60;
regs.p.c = 1;
}
if(regs.p.h || (regs.a & 15) > 0x09) {
regs.a += 0x06;
}
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
void SMPcore::op_das() {
op_io();
op_io();
if(!regs.p.c || (regs.a) > 0x99) {
regs.a -= 0x60;
regs.p.c = 0;
}
if(!regs.p.h || (regs.a & 15) > 0x09) {
regs.a -= 0x06;
}
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
template<int mask, int value> void SMPcore::op_setbit() {
op_io();
regs.p = (regs.p & ~mask) | value;
}
void SMPcore::op_notc() {
op_io();
op_io();
regs.p.c = !regs.p.c;
}
template<int value> void SMPcore::op_seti() {
op_io();
op_io();
regs.p.i = value;
}
template<int op, int value> void SMPcore::op_setbit_dp() {
dp = op_readpc();
rd = op_readdp(dp);
rd = (op ? rd | value : rd & ~value);
op_writedp(dp, rd);
}
template<int n> void SMPcore::op_push_reg() {
op_io();
op_io();
op_writestack(regs.r[n]);
}
void SMPcore::op_push_p() {
op_io();
op_io();
op_writestack(regs.p);
}
template<int n> void SMPcore::op_pop_reg() {
op_io();
op_io();
regs.r[n] = op_readstack();
}
void SMPcore::op_pop_p() {
op_io();
op_io();
regs.p = op_readstack();
}
void SMPcore::op_mul_ya() {
op_io();
op_io();
op_io();
op_io();
op_io();
op_io();
op_io();
op_io();
ya = regs.y * regs.a;
regs.a = ya;
regs.y = ya >> 8;
//result is set based on y (high-byte) only
regs.p.n = !!(regs.y & 0x80);
regs.p.z = (regs.y == 0);
}
void SMPcore::op_div_ya_x() {
op_io();
op_io();
op_io();
op_io();
op_io();
op_io();
op_io();
op_io();
op_io();
op_io();
op_io();
ya = regs.ya;
//overflow set if quotient >= 256
regs.p.v = !!(regs.y >= regs.x);
regs.p.h = !!((regs.y & 15) >= (regs.x & 15));
if(regs.y < (regs.x << 1)) {
//if quotient is <= 511 (will fit into 9-bit result)
regs.a = ya / regs.x;
regs.y = ya % regs.x;
} else {
//otherwise, the quotient won't fit into regs.p.v + regs.a
//this emulates the odd behavior of the S-SMP in this case
regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x);
regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x);
}
//result is set based on a (quotient) only
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
#endif

View File

@ -1,200 +0,0 @@
#ifdef SMPCORE_CPP
template<int to, int from> void SMPcore::op_mov_reg_reg() {
op_io();
regs.r[to] = regs.r[from];
regs.p.n = (regs.r[to] & 0x80);
regs.p.z = (regs.r[to] == 0);
}
void SMPcore::op_mov_sp_x() {
op_io();
regs.sp = regs.x;
}
template<int n> void SMPcore::op_mov_reg_const() {
regs.r[n] = op_readpc();
regs.p.n = (regs.r[n] & 0x80);
regs.p.z = (regs.r[n] == 0);
}
void SMPcore::op_mov_a_ix() {
op_io();
regs.a = op_readdp(regs.x);
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
void SMPcore::op_mov_a_ixinc() {
op_io();
regs.a = op_readdp(regs.x++);
op_io();
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
template<int n> void SMPcore::op_mov_reg_dp() {
sp = op_readpc();
regs.r[n] = op_readdp(sp);
regs.p.n = (regs.r[n] & 0x80);
regs.p.z = (regs.r[n] == 0);
}
template<int n, int i> void SMPcore::op_mov_reg_dpr() {
sp = op_readpc();
op_io();
regs.r[n] = op_readdp(sp + regs.r[i]);
regs.p.n = (regs.r[n] & 0x80);
regs.p.z = (regs.r[n] == 0);
}
template<int n> void SMPcore::op_mov_reg_addr() {
sp = op_readpc() << 0;
sp |= op_readpc() << 8;
regs.r[n] = op_readaddr(sp);
regs.p.n = (regs.r[n] & 0x80);
regs.p.z = (regs.r[n] == 0);
}
template<int i> void SMPcore::op_mov_a_addrr() {
sp = op_readpc() << 0;
sp |= op_readpc() << 8;
op_io();
regs.a = op_readaddr(sp + regs.r[i]);
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
void SMPcore::op_mov_a_idpx() {
dp = op_readpc() + regs.x;
op_io();
sp = op_readdp(dp + 0) << 0;
sp |= op_readdp(dp + 1) << 8;
regs.a = op_readaddr(sp);
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
void SMPcore::op_mov_a_idpy() {
dp = op_readpc();
op_io();
sp = op_readdp(dp + 0) << 0;
sp |= op_readdp(dp + 1) << 8;
regs.a = op_readaddr(sp + regs.y);
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
void SMPcore::op_mov_dp_dp() {
sp = op_readpc();
rd = op_readdp(sp);
dp = op_readpc();
op_writedp(dp, rd);
}
void SMPcore::op_mov_dp_const() {
rd = op_readpc();
dp = op_readpc();
op_readdp(dp);
op_writedp(dp, rd);
}
void SMPcore::op_mov_ix_a() {
op_io();
op_readdp(regs.x);
op_writedp(regs.x, regs.a);
}
void SMPcore::op_mov_ixinc_a() {
op_io();
op_io();
op_writedp(regs.x++, regs.a);
}
template<int n> void SMPcore::op_mov_dp_reg() {
dp = op_readpc();
op_readdp(dp);
op_writedp(dp, regs.r[n]);
}
template<int n, int i> void SMPcore::op_mov_dpr_reg() {
dp = op_readpc();
op_io();
dp += regs.r[i];
op_readdp(dp);
op_writedp(dp, regs.r[n]);
}
template<int n> void SMPcore::op_mov_addr_reg() {
dp = op_readpc() << 0;
dp |= op_readpc() << 8;
op_readaddr(dp);
op_writeaddr(dp, regs.r[n]);
}
template<int i> void SMPcore::op_mov_addrr_a() {
dp = op_readpc() << 0;
dp |= op_readpc() << 8;
op_io();
dp += regs.r[i];
op_readaddr(dp);
op_writeaddr(dp, regs.a);
}
void SMPcore::op_mov_idpx_a() {
sp = op_readpc();
op_io();
sp += regs.x;
dp = op_readdp(sp + 0) << 0;
dp |= op_readdp(sp + 1) << 8;
op_readaddr(dp);
op_writeaddr(dp, regs.a);
}
void SMPcore::op_mov_idpy_a() {
sp = op_readpc();
dp = op_readdp(sp + 0) << 0;
dp |= op_readdp(sp + 1) << 8;
op_io();
dp += regs.y;
op_readaddr(dp);
op_writeaddr(dp, regs.a);
}
void SMPcore::op_movw_ya_dp() {
sp = op_readpc();
regs.a = op_readdp(sp + 0);
op_io();
regs.y = op_readdp(sp + 1);
regs.p.n = (regs.ya & 0x8000);
regs.p.z = (regs.ya == 0);
}
void SMPcore::op_movw_dp_ya() {
dp = op_readpc();
op_readdp(dp);
op_writedp(dp + 0, regs.a);
op_writedp(dp + 1, regs.y);
}
void SMPcore::op_mov1_c_bit() {
sp = op_readpc() << 0;
sp |= op_readpc() << 8;
bit = sp >> 13;
sp &= 0x1fff;
rd = op_readaddr(sp);
regs.p.c = (rd & (1 << bit));
}
void SMPcore::op_mov1_bit_c() {
dp = op_readpc() << 0;
dp |= op_readpc() << 8;
bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
(regs.p.c) ? rd |= (1 << bit) : rd &= ~(1 << bit);
op_io();
op_writeaddr(dp, rd);
}
#endif

View File

@ -1,152 +0,0 @@
#ifdef SMPCORE_CPP
void SMPcore::op_bra() {
rd = op_readpc();
op_io();
op_io();
regs.pc += (int8)rd;
}
template<int flag, int value> void SMPcore::op_branch() {
rd = op_readpc();
if((bool)(regs.p & flag) != value) return;
op_io();
op_io();
regs.pc += (int8)rd;
}
template<int mask, int value> void SMPcore::op_bitbranch() {
dp = op_readpc();
sp = op_readdp(dp);
rd = op_readpc();
op_io();
if((bool)(sp & mask) != value) return;
op_io();
op_io();
regs.pc += (int8)rd;
}
void SMPcore::op_cbne_dp() {
dp = op_readpc();
sp = op_readdp(dp);
rd = op_readpc();
op_io();
if(regs.a == sp) return;
op_io();
op_io();
regs.pc += (int8)rd;
}
void SMPcore::op_cbne_dpx() {
dp = op_readpc();
op_io();
sp = op_readdp(dp + regs.x);
rd = op_readpc();
op_io();
if(regs.a == sp) return;
op_io();
op_io();
regs.pc += (int8)rd;
}
void SMPcore::op_dbnz_dp() {
dp = op_readpc();
wr = op_readdp(dp);
op_writedp(dp, --wr);
rd = op_readpc();
if(wr == 0) return;
op_io();
op_io();
regs.pc += (int8)rd;
}
void SMPcore::op_dbnz_y() {
rd = op_readpc();
op_io();
regs.y--;
op_io();
if(regs.y == 0) return;
op_io();
op_io();
regs.pc += (int8)rd;
}
void SMPcore::op_jmp_addr() {
rd = op_readpc() << 0;
rd |= op_readpc() << 8;
regs.pc = rd;
}
void SMPcore::op_jmp_iaddrx() {
dp = op_readpc() << 0;
dp |= op_readpc() << 8;
op_io();
dp += regs.x;
rd = op_readaddr(dp + 0) << 0;
rd |= op_readaddr(dp + 1) << 8;
regs.pc = rd;
}
void SMPcore::op_call() {
rd = op_readpc() << 0;
rd |= op_readpc() << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc >> 0);
regs.pc = rd;
}
void SMPcore::op_pcall() {
rd = op_readpc();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc >> 0);
regs.pc = 0xff00 | rd;
}
template<int n> void SMPcore::op_tcall() {
dp = 0xffde - (n << 1);
rd = op_readaddr(dp + 0) << 0;
rd |= op_readaddr(dp + 1) << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc >> 0);
regs.pc = rd;
}
void SMPcore::op_brk() {
rd = op_readaddr(0xffde) << 0;
rd |= op_readaddr(0xffdf) << 8;
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc >> 0);
op_writestack(regs.p);
regs.pc = rd;
regs.p.b = 1;
regs.p.i = 0;
}
void SMPcore::op_ret() {
rd = op_readstack() << 0;
rd |= op_readstack() << 8;
op_io();
op_io();
regs.pc = rd;
}
void SMPcore::op_reti() {
regs.p = op_readstack();
rd = op_readstack() << 0;
rd |= op_readstack() << 8;
op_io();
op_io();
regs.pc = rd;
}
#endif

View File

@ -1,154 +0,0 @@
#ifdef SMPCORE_CPP
template<uint8 (SMPcore::*op)(uint8, uint8), int n>
void SMPcore::op_read_reg_const() {
rd = op_readpc();
regs.r[n] = (this->*op)(regs.r[n], rd);
}
template<uint8 (SMPcore::*op)(uint8, uint8)>
void SMPcore::op_read_a_ix() {
op_io();
rd = op_readdp(regs.x);
regs.a = (this->*op)(regs.a, rd);
}
template<uint8 (SMPcore::*op)(uint8, uint8), int n>
void SMPcore::op_read_reg_dp() {
dp = op_readpc();
rd = op_readdp(dp);
regs.r[n] = (this->*op)(regs.r[n], rd);
}
template<uint8 (SMPcore::*op)(uint8, uint8)>
void SMPcore::op_read_a_dpx() {
dp = op_readpc();
op_io();
rd = op_readdp(dp + regs.x);
regs.a = (this->*op)(regs.a, rd);
}
template<uint8 (SMPcore::*op)(uint8, uint8), int n>
void SMPcore::op_read_reg_addr() {
dp = op_readpc() << 0;
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
regs.r[n] = (this->*op)(regs.r[n], rd);
}
template<uint8 (SMPcore::*op)(uint8, uint8), int i>
void SMPcore::op_read_a_addrr() {
dp = op_readpc() << 0;
dp |= op_readpc() << 8;
op_io();
rd = op_readaddr(dp + regs.r[i]);
regs.a = (this->*op)(regs.a, rd);
}
template<uint8 (SMPcore::*op)(uint8, uint8)>
void SMPcore::op_read_a_idpx() {
dp = op_readpc() + regs.x;
op_io();
sp = op_readdp(dp + 0) << 0;
sp |= op_readdp(dp + 1) << 8;
rd = op_readaddr(sp);
regs.a = (this->*op)(regs.a, rd);
}
template<uint8 (SMPcore::*op)(uint8, uint8)>
void SMPcore::op_read_a_idpy() {
dp = op_readpc();
op_io();
sp = op_readdp(dp + 0) << 0;
sp |= op_readdp(dp + 1) << 8;
rd = op_readaddr(sp + regs.y);
regs.a = (this->*op)(regs.a, rd);
}
template<uint8 (SMPcore::*op)(uint8, uint8)>
void SMPcore::op_read_ix_iy() {
op_io();
rd = op_readdp(regs.y);
wr = op_readdp(regs.x);
wr = (this->*op)(wr, rd);
static uint8 (SMPcore::*cmp)(uint8, uint8) = &SMPcore::op_cmp;
(op != cmp) ? op_writedp(regs.x, wr) : op_io();
}
template<uint8 (SMPcore::*op)(uint8, uint8)>
void SMPcore::op_read_dp_dp() {
sp = op_readpc();
rd = op_readdp(sp);
dp = op_readpc();
wr = op_readdp(dp);
wr = (this->*op)(wr, rd);
static uint8 (SMPcore::*cmp)(uint8, uint8) = &SMPcore::op_cmp;
(op != cmp) ? op_writedp(dp, wr) : op_io();
}
template<uint8 (SMPcore::*op)(uint8, uint8)>
void SMPcore::op_read_dp_const() {
rd = op_readpc();
dp = op_readpc();
wr = op_readdp(dp);
wr = (this->*op)(wr, rd);
static uint8 (SMPcore::*cmp)(uint8, uint8) = &SMPcore::op_cmp;
(op != cmp) ? op_writedp(dp, wr) : op_io();
}
template<uint16 (SMPcore::*op)(uint16, uint16)>
void SMPcore::op_read_ya_dp() {
dp = op_readpc();
rd = op_readdp(dp + 0) << 0;
op_io();
rd |= op_readdp(dp + 1) << 8;
regs.ya = (this->*op)(regs.ya, rd);
}
void SMPcore::op_cmpw_ya_dp() {
dp = op_readpc();
rd = op_readdp(dp + 0) << 0;
rd |= op_readdp(dp + 1) << 8;
op_cmpw(regs.ya, rd);
}
template<int op> void SMPcore::op_and1_bit() {
dp = op_readpc() << 0;
dp |= op_readpc() << 8;
bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
regs.p.c = regs.p.c & ((bool)(rd & (1 << bit)) ^ op);
}
void SMPcore::op_eor1_bit() {
dp = op_readpc() << 0;
dp |= op_readpc() << 8;
bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
op_io();
regs.p.c = regs.p.c ^ (bool)(rd & (1 << bit));
}
void SMPcore::op_not1_bit() {
dp = op_readpc() << 0;
dp |= op_readpc() << 8;
bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
rd ^= 1 << bit;
op_writeaddr(dp, rd);
}
template<int op> void SMPcore::op_or1_bit() {
dp = op_readpc() << 0;
dp |= op_readpc() << 8;
bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
op_io();
regs.p.c = regs.p.c | ((bool)(rd & (1 << bit)) ^ op);
}
#endif

View File

@ -1,58 +0,0 @@
#ifdef SMPCORE_CPP
template<uint8 (SMPcore::*op)(uint8), int n>
void SMPcore::op_adjust_reg() {
op_io();
regs.r[n] = (this->*op)(regs.r[n]);
}
template<uint8 (SMPcore::*op)(uint8)>
void SMPcore::op_adjust_dp() {
dp = op_readpc();
rd = op_readdp(dp);
rd = (this->*op)(rd);
op_writedp(dp, rd);
}
template<uint8 (SMPcore::*op)(uint8)>
void SMPcore::op_adjust_dpx() {
dp = op_readpc();
op_io();
rd = op_readdp(dp + regs.x);
rd = (this->*op)(rd);
op_writedp(dp + regs.x, rd);
}
template<uint8 (SMPcore::*op)(uint8)>
void SMPcore::op_adjust_addr() {
dp = op_readpc() << 0;
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
rd = (this->*op)(rd);
op_writeaddr(dp, rd);
}
template<int op>
void SMPcore::op_adjust_addr_a() {
dp = op_readpc() << 0;
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
regs.p.n = ((regs.a - rd) & 0x80);
regs.p.z = ((regs.a - rd) == 0);
op_readaddr(dp);
op_writeaddr(dp, (op ? rd | regs.a : rd & ~regs.a));
}
template<int adjust>
void SMPcore::op_adjustw_dp() {
dp = op_readpc();
rd = op_readdp(dp) << 0;
rd += adjust;
op_writedp(dp++, rd);
rd += op_readdp(dp) << 8;
op_writedp(dp, rd >> 8);
regs.p.n = (rd & 0x8000);
regs.p.z = (rd == 0);
}
#endif

View File

@ -1,44 +0,0 @@
struct regya_t {
uint8_t &hi, &lo;
inline operator uint16_t() const {
return (hi << 8) + lo;
}
inline regya_t& operator=(uint16_t data) {
hi = data >> 8;
lo = data;
return *this;
}
regya_t(uint8_t &hi_, uint8_t &lo_) : hi(hi_), lo(lo_) {}
};
struct flag_t {
bool n, v, p, b, h, i, z, c;
inline operator unsigned() const {
return (n << 7) + (v << 6) + (p << 5) + (b << 4)
+ (h << 3) + (i << 2) + (z << 1) + (c << 0);
}
inline unsigned operator=(uint8_t data) {
n = data & 0x80; v = data & 0x40; p = data & 0x20; b = data & 0x10;
h = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01;
return data;
}
inline unsigned operator|=(unsigned data) { return operator=(operator unsigned() | data); }
inline unsigned operator^=(unsigned data) { return operator=(operator unsigned() ^ data); }
inline unsigned operator&=(unsigned data) { return operator=(operator unsigned() & data); }
flag_t() : n(0), v(0), p(0), b(0), h(0), i(0), z(0), c(0) {}
};
struct regs_t {
uint16_t pc;
uint8_t r[4], &a, &x, &y, &sp;
regya_t ya;
flag_t p;
regs_t() : a(r[0]), x(r[1]), y(r[2]), sp(r[3]), ya(r[2], r[0]) {}
};

View File

@ -1,26 +0,0 @@
#ifdef SMPCORE_CPP
void SMPcore::core_serialize(serializer &s) {
s.integer(regs.pc);
s.integer(regs.a);
s.integer(regs.x);
s.integer(regs.y);
s.integer(regs.sp);
s.integer(regs.p.n);
s.integer(regs.p.v);
s.integer(regs.p.p);
s.integer(regs.p.b);
s.integer(regs.p.h);
s.integer(regs.p.i);
s.integer(regs.p.z);
s.integer(regs.p.c);
s.integer(dp);
s.integer(sp);
s.integer(rd);
s.integer(wr);
s.integer(bit);
s.integer(ya);
}
#endif

View File

@ -1,264 +0,0 @@
#ifdef SMPCORE_CPP
void SMPcore::initialize_opcode_table() {
#define op opcode_table
op[0x00] = &SMPcore::op_nop;
op[0x01] = &SMPcore::op_tcall<0>;
op[0x02] = &SMPcore::op_setbit_dp<1, 0x01>;
op[0x03] = &SMPcore::op_bitbranch<0x01, true>;
op[0x04] = &SMPcore::op_read_reg_dp<&SMPcore::op_or, A>;
op[0x05] = &SMPcore::op_read_reg_addr<&SMPcore::op_or, A>;
op[0x06] = &SMPcore::op_read_a_ix<&SMPcore::op_or>;
op[0x07] = &SMPcore::op_read_a_idpx<&SMPcore::op_or>;
op[0x08] = &SMPcore::op_read_reg_const<&SMPcore::op_or, A>;
op[0x09] = &SMPcore::op_read_dp_dp<&SMPcore::op_or>;
op[0x0a] = &SMPcore::op_or1_bit<0>;
op[0x0b] = &SMPcore::op_adjust_dp<&SMPcore::op_asl>;
op[0x0c] = &SMPcore::op_adjust_addr<&SMPcore::op_asl>;
op[0x0d] = &SMPcore::op_push_p;
op[0x0e] = &SMPcore::op_adjust_addr_a<1>;
op[0x0f] = &SMPcore::op_brk;
op[0x10] = &SMPcore::op_branch<0x80, false>;
op[0x11] = &SMPcore::op_tcall<1>;
op[0x12] = &SMPcore::op_setbit_dp<0, 0x01>;
op[0x13] = &SMPcore::op_bitbranch<0x01, false>;
op[0x14] = &SMPcore::op_read_a_dpx<&SMPcore::op_or>;
op[0x15] = &SMPcore::op_read_a_addrr<&SMPcore::op_or, X>;
op[0x16] = &SMPcore::op_read_a_addrr<&SMPcore::op_or, Y>;
op[0x17] = &SMPcore::op_read_a_idpy<&SMPcore::op_or>;
op[0x18] = &SMPcore::op_read_dp_const<&SMPcore::op_or>;
op[0x19] = &SMPcore::op_read_ix_iy<&SMPcore::op_or>;
op[0x1a] = &SMPcore::op_adjustw_dp<-1>;
op[0x1b] = &SMPcore::op_adjust_dpx<&SMPcore::op_asl>;
op[0x1c] = &SMPcore::op_adjust_reg<&SMPcore::op_asl, A>;
op[0x1d] = &SMPcore::op_adjust_reg<&SMPcore::op_dec, X>;
op[0x1e] = &SMPcore::op_read_reg_addr<&SMPcore::op_cmp, X>;
op[0x1f] = &SMPcore::op_jmp_iaddrx;
op[0x20] = &SMPcore::op_setbit<0x20, 0x00>;
op[0x21] = &SMPcore::op_tcall<2>;
op[0x22] = &SMPcore::op_setbit_dp<1, 0x02>;
op[0x23] = &SMPcore::op_bitbranch<0x02, true>;
op[0x24] = &SMPcore::op_read_reg_dp<&SMPcore::op_and, A>;
op[0x25] = &SMPcore::op_read_reg_addr<&SMPcore::op_and, A>;
op[0x26] = &SMPcore::op_read_a_ix<&SMPcore::op_and>;
op[0x27] = &SMPcore::op_read_a_idpx<&SMPcore::op_and>;
op[0x28] = &SMPcore::op_read_reg_const<&SMPcore::op_and, A>;
op[0x29] = &SMPcore::op_read_dp_dp<&SMPcore::op_and>;
op[0x2a] = &SMPcore::op_or1_bit<1>;
op[0x2b] = &SMPcore::op_adjust_dp<&SMPcore::op_rol>;
op[0x2c] = &SMPcore::op_adjust_addr<&SMPcore::op_rol>;
op[0x2d] = &SMPcore::op_push_reg<A>;
op[0x2e] = &SMPcore::op_cbne_dp;
op[0x2f] = &SMPcore::op_bra;
op[0x30] = &SMPcore::op_branch<0x80, true>;
op[0x31] = &SMPcore::op_tcall<3>;
op[0x32] = &SMPcore::op_setbit_dp<0, 0x02>;
op[0x33] = &SMPcore::op_bitbranch<0x02, false>;
op[0x34] = &SMPcore::op_read_a_dpx<&SMPcore::op_and>;
op[0x35] = &SMPcore::op_read_a_addrr<&SMPcore::op_and, X>;
op[0x36] = &SMPcore::op_read_a_addrr<&SMPcore::op_and, Y>;
op[0x37] = &SMPcore::op_read_a_idpy<&SMPcore::op_and>;
op[0x38] = &SMPcore::op_read_dp_const<&SMPcore::op_and>;
op[0x39] = &SMPcore::op_read_ix_iy<&SMPcore::op_and>;
op[0x3a] = &SMPcore::op_adjustw_dp<+1>;
op[0x3b] = &SMPcore::op_adjust_dpx<&SMPcore::op_rol>;
op[0x3c] = &SMPcore::op_adjust_reg<&SMPcore::op_rol, A>;
op[0x3d] = &SMPcore::op_adjust_reg<&SMPcore::op_inc, X>;
op[0x3e] = &SMPcore::op_read_reg_dp<&SMPcore::op_cmp, X>;
op[0x3f] = &SMPcore::op_call;
op[0x40] = &SMPcore::op_setbit<0x20, 0x20>;
op[0x41] = &SMPcore::op_tcall<4>;
op[0x42] = &SMPcore::op_setbit_dp<1, 0x04>;
op[0x43] = &SMPcore::op_bitbranch<0x04, true>;
op[0x44] = &SMPcore::op_read_reg_dp<&SMPcore::op_eor, A>;
op[0x45] = &SMPcore::op_read_reg_addr<&SMPcore::op_eor, A>;
op[0x46] = &SMPcore::op_read_a_ix<&SMPcore::op_eor>;
op[0x47] = &SMPcore::op_read_a_idpx<&SMPcore::op_eor>;
op[0x48] = &SMPcore::op_read_reg_const<&SMPcore::op_eor, A>;
op[0x49] = &SMPcore::op_read_dp_dp<&SMPcore::op_eor>;
op[0x4a] = &SMPcore::op_and1_bit<0>;
op[0x4b] = &SMPcore::op_adjust_dp<&SMPcore::op_lsr>;
op[0x4c] = &SMPcore::op_adjust_addr<&SMPcore::op_lsr>;
op[0x4d] = &SMPcore::op_push_reg<X>;
op[0x4e] = &SMPcore::op_adjust_addr_a<0>;
op[0x4f] = &SMPcore::op_pcall;
op[0x50] = &SMPcore::op_branch<0x40, false>;
op[0x51] = &SMPcore::op_tcall<5>;
op[0x52] = &SMPcore::op_setbit_dp<0, 0x04>;
op[0x53] = &SMPcore::op_bitbranch<0x04, false>;
op[0x54] = &SMPcore::op_read_a_dpx<&SMPcore::op_eor>;
op[0x55] = &SMPcore::op_read_a_addrr<&SMPcore::op_eor, X>;
op[0x56] = &SMPcore::op_read_a_addrr<&SMPcore::op_eor, Y>;
op[0x57] = &SMPcore::op_read_a_idpy<&SMPcore::op_eor>;
op[0x58] = &SMPcore::op_read_dp_const<&SMPcore::op_eor>;
op[0x59] = &SMPcore::op_read_ix_iy<&SMPcore::op_eor>;
op[0x5a] = &SMPcore::op_cmpw_ya_dp;
op[0x5b] = &SMPcore::op_adjust_dpx<&SMPcore::op_lsr>;
op[0x5c] = &SMPcore::op_adjust_reg<&SMPcore::op_lsr, A>;
op[0x5d] = &SMPcore::op_mov_reg_reg<X, A>;
op[0x5e] = &SMPcore::op_read_reg_addr<&SMPcore::op_cmp, Y>;
op[0x5f] = &SMPcore::op_jmp_addr;
op[0x60] = &SMPcore::op_setbit<0x01, 0x00>;
op[0x61] = &SMPcore::op_tcall<6>;
op[0x62] = &SMPcore::op_setbit_dp<1, 0x08>;
op[0x63] = &SMPcore::op_bitbranch<0x08, true>;
op[0x64] = &SMPcore::op_read_reg_dp<&SMPcore::op_cmp, A>;
op[0x65] = &SMPcore::op_read_reg_addr<&SMPcore::op_cmp, A>;
op[0x66] = &SMPcore::op_read_a_ix<&SMPcore::op_cmp>;
op[0x67] = &SMPcore::op_read_a_idpx<&SMPcore::op_cmp>;
op[0x68] = &SMPcore::op_read_reg_const<&SMPcore::op_cmp, A>;
op[0x69] = &SMPcore::op_read_dp_dp<&SMPcore::op_cmp>;
op[0x6a] = &SMPcore::op_and1_bit<1>;
op[0x6b] = &SMPcore::op_adjust_dp<&SMPcore::op_ror>;
op[0x6c] = &SMPcore::op_adjust_addr<&SMPcore::op_ror>;
op[0x6d] = &SMPcore::op_push_reg<Y>;
op[0x6e] = &SMPcore::op_dbnz_dp;
op[0x6f] = &SMPcore::op_ret;
op[0x70] = &SMPcore::op_branch<0x40, true>;
op[0x71] = &SMPcore::op_tcall<7>;
op[0x72] = &SMPcore::op_setbit_dp<0, 0x08>;
op[0x73] = &SMPcore::op_bitbranch<0x08, false>;
op[0x74] = &SMPcore::op_read_a_dpx<&SMPcore::op_cmp>;
op[0x75] = &SMPcore::op_read_a_addrr<&SMPcore::op_cmp, X>;
op[0x76] = &SMPcore::op_read_a_addrr<&SMPcore::op_cmp, Y>;
op[0x77] = &SMPcore::op_read_a_idpy<&SMPcore::op_cmp>;
op[0x78] = &SMPcore::op_read_dp_const<&SMPcore::op_cmp>;
op[0x79] = &SMPcore::op_read_ix_iy<&SMPcore::op_cmp>;
op[0x7a] = &SMPcore::op_read_ya_dp<&SMPcore::op_addw>;
op[0x7b] = &SMPcore::op_adjust_dpx<&SMPcore::op_ror>;
op[0x7c] = &SMPcore::op_adjust_reg<&SMPcore::op_ror, A>;
op[0x7d] = &SMPcore::op_mov_reg_reg<A, X>;
op[0x7e] = &SMPcore::op_read_reg_dp<&SMPcore::op_cmp, Y>;
op[0x7f] = &SMPcore::op_reti;
op[0x80] = &SMPcore::op_setbit<0x01, 0x01>;
op[0x81] = &SMPcore::op_tcall<8>;
op[0x82] = &SMPcore::op_setbit_dp<1, 0x10>;
op[0x83] = &SMPcore::op_bitbranch<0x10, true>;
op[0x84] = &SMPcore::op_read_reg_dp<&SMPcore::op_adc, A>;
op[0x85] = &SMPcore::op_read_reg_addr<&SMPcore::op_adc, A>;
op[0x86] = &SMPcore::op_read_a_ix<&SMPcore::op_adc>;
op[0x87] = &SMPcore::op_read_a_idpx<&SMPcore::op_adc>;
op[0x88] = &SMPcore::op_read_reg_const<&SMPcore::op_adc, A>;
op[0x89] = &SMPcore::op_read_dp_dp<&SMPcore::op_adc>;
op[0x8a] = &SMPcore::op_eor1_bit;
op[0x8b] = &SMPcore::op_adjust_dp<&SMPcore::op_dec>;
op[0x8c] = &SMPcore::op_adjust_addr<&SMPcore::op_dec>;
op[0x8d] = &SMPcore::op_mov_reg_const<Y>;
op[0x8e] = &SMPcore::op_pop_p;
op[0x8f] = &SMPcore::op_mov_dp_const;
op[0x90] = &SMPcore::op_branch<0x01, false>;
op[0x91] = &SMPcore::op_tcall<9>;
op[0x92] = &SMPcore::op_setbit_dp<0, 0x10>;
op[0x93] = &SMPcore::op_bitbranch<0x10, false>;
op[0x94] = &SMPcore::op_read_a_dpx<&SMPcore::op_adc>;
op[0x95] = &SMPcore::op_read_a_addrr<&SMPcore::op_adc, X>;
op[0x96] = &SMPcore::op_read_a_addrr<&SMPcore::op_adc, Y>;
op[0x97] = &SMPcore::op_read_a_idpy<&SMPcore::op_adc>;
op[0x98] = &SMPcore::op_read_dp_const<&SMPcore::op_adc>;
op[0x99] = &SMPcore::op_read_ix_iy<&SMPcore::op_adc>;
op[0x9a] = &SMPcore::op_read_ya_dp<&SMPcore::op_subw>;
op[0x9b] = &SMPcore::op_adjust_dpx<&SMPcore::op_dec>;
op[0x9c] = &SMPcore::op_adjust_reg<&SMPcore::op_dec, A>;
op[0x9d] = &SMPcore::op_mov_reg_reg<X, SP>;
op[0x9e] = &SMPcore::op_div_ya_x;
op[0x9f] = &SMPcore::op_xcn;
op[0xa0] = &SMPcore::op_seti<1>;
op[0xa1] = &SMPcore::op_tcall<10>;
op[0xa2] = &SMPcore::op_setbit_dp<1, 0x20>;
op[0xa3] = &SMPcore::op_bitbranch<0x20, true>;
op[0xa4] = &SMPcore::op_read_reg_dp<&SMPcore::op_sbc, A>;
op[0xa5] = &SMPcore::op_read_reg_addr<&SMPcore::op_sbc, A>;
op[0xa6] = &SMPcore::op_read_a_ix<&SMPcore::op_sbc>;
op[0xa7] = &SMPcore::op_read_a_idpx<&SMPcore::op_sbc>;
op[0xa8] = &SMPcore::op_read_reg_const<&SMPcore::op_sbc, A>;
op[0xa9] = &SMPcore::op_read_dp_dp<&SMPcore::op_sbc>;
op[0xaa] = &SMPcore::op_mov1_c_bit;
op[0xab] = &SMPcore::op_adjust_dp<&SMPcore::op_inc>;
op[0xac] = &SMPcore::op_adjust_addr<&SMPcore::op_inc>;
op[0xad] = &SMPcore::op_read_reg_const<&SMPcore::op_cmp, Y>;
op[0xae] = &SMPcore::op_pop_reg<A>;
op[0xaf] = &SMPcore::op_mov_ixinc_a;
op[0xb0] = &SMPcore::op_branch<0x01, true>;
op[0xb1] = &SMPcore::op_tcall<11>;
op[0xb2] = &SMPcore::op_setbit_dp<0, 0x20>;
op[0xb3] = &SMPcore::op_bitbranch<0x20, false>;
op[0xb4] = &SMPcore::op_read_a_dpx<&SMPcore::op_sbc>;
op[0xb5] = &SMPcore::op_read_a_addrr<&SMPcore::op_sbc, X>;
op[0xb6] = &SMPcore::op_read_a_addrr<&SMPcore::op_sbc, Y>;
op[0xb7] = &SMPcore::op_read_a_idpy<&SMPcore::op_sbc>;
op[0xb8] = &SMPcore::op_read_dp_const<&SMPcore::op_sbc>;
op[0xb9] = &SMPcore::op_read_ix_iy<&SMPcore::op_sbc>;
op[0xba] = &SMPcore::op_movw_ya_dp;
op[0xbb] = &SMPcore::op_adjust_dpx<&SMPcore::op_inc>;
op[0xbc] = &SMPcore::op_adjust_reg<&SMPcore::op_inc, A>;
op[0xbd] = &SMPcore::op_mov_sp_x;
op[0xbe] = &SMPcore::op_das;
op[0xbf] = &SMPcore::op_mov_a_ixinc;
op[0xc0] = &SMPcore::op_seti<0>;
op[0xc1] = &SMPcore::op_tcall<12>;
op[0xc2] = &SMPcore::op_setbit_dp<1, 0x40>;
op[0xc3] = &SMPcore::op_bitbranch<0x40, true>;
op[0xc4] = &SMPcore::op_mov_dp_reg<A>;
op[0xc5] = &SMPcore::op_mov_addr_reg<A>;
op[0xc6] = &SMPcore::op_mov_ix_a;
op[0xc7] = &SMPcore::op_mov_idpx_a;
op[0xc8] = &SMPcore::op_read_reg_const<&SMPcore::op_cmp, X>;
op[0xc9] = &SMPcore::op_mov_addr_reg<X>;
op[0xca] = &SMPcore::op_mov1_bit_c;
op[0xcb] = &SMPcore::op_mov_dp_reg<Y>;
op[0xcc] = &SMPcore::op_mov_addr_reg<Y>;
op[0xcd] = &SMPcore::op_mov_reg_const<X>;
op[0xce] = &SMPcore::op_pop_reg<X>;
op[0xcf] = &SMPcore::op_mul_ya;
op[0xd0] = &SMPcore::op_branch<0x02, false>;
op[0xd1] = &SMPcore::op_tcall<13>;
op[0xd2] = &SMPcore::op_setbit_dp<0, 0x40>;
op[0xd3] = &SMPcore::op_bitbranch<0x40, false>;
op[0xd4] = &SMPcore::op_mov_dpr_reg<A, X>;
op[0xd5] = &SMPcore::op_mov_addrr_a<X>;
op[0xd6] = &SMPcore::op_mov_addrr_a<Y>;
op[0xd7] = &SMPcore::op_mov_idpy_a;
op[0xd8] = &SMPcore::op_mov_dp_reg<X>;
op[0xd9] = &SMPcore::op_mov_dpr_reg<X, Y>;
op[0xda] = &SMPcore::op_movw_dp_ya;
op[0xdb] = &SMPcore::op_mov_dpr_reg<Y, X>;
op[0xdc] = &SMPcore::op_adjust_reg<&SMPcore::op_dec, Y>;
op[0xdd] = &SMPcore::op_mov_reg_reg<A, Y>;
op[0xde] = &SMPcore::op_cbne_dpx;
op[0xdf] = &SMPcore::op_daa;
op[0xe0] = &SMPcore::op_setbit<0x48, 0x00>;
op[0xe1] = &SMPcore::op_tcall<14>;
op[0xe2] = &SMPcore::op_setbit_dp<1, 0x80>;
op[0xe3] = &SMPcore::op_bitbranch<0x80, true>;
op[0xe4] = &SMPcore::op_mov_reg_dp<A>;
op[0xe5] = &SMPcore::op_mov_reg_addr<A>;
op[0xe6] = &SMPcore::op_mov_a_ix;
op[0xe7] = &SMPcore::op_mov_a_idpx;
op[0xe8] = &SMPcore::op_mov_reg_const<A>;
op[0xe9] = &SMPcore::op_mov_reg_addr<X>;
op[0xea] = &SMPcore::op_not1_bit;
op[0xeb] = &SMPcore::op_mov_reg_dp<Y>;
op[0xec] = &SMPcore::op_mov_reg_addr<Y>;
op[0xed] = &SMPcore::op_notc;
op[0xee] = &SMPcore::op_pop_reg<Y>;
op[0xef] = &SMPcore::op_wait;
op[0xf0] = &SMPcore::op_branch<0x02, true>;
op[0xf1] = &SMPcore::op_tcall<15>;
op[0xf2] = &SMPcore::op_setbit_dp<0, 0x80>;
op[0xf3] = &SMPcore::op_bitbranch<0x80, false>;
op[0xf4] = &SMPcore::op_mov_reg_dpr<A, X>;
op[0xf5] = &SMPcore::op_mov_a_addrr<X>;
op[0xf6] = &SMPcore::op_mov_a_addrr<Y>;
op[0xf7] = &SMPcore::op_mov_a_idpy;
op[0xf8] = &SMPcore::op_mov_reg_dp<X>;
op[0xf9] = &SMPcore::op_mov_reg_dpr<X, Y>;
op[0xfa] = &SMPcore::op_mov_dp_dp;
op[0xfb] = &SMPcore::op_mov_reg_dpr<Y, X>;
op[0xfc] = &SMPcore::op_adjust_reg<&SMPcore::op_inc, Y>;
op[0xfd] = &SMPcore::op_mov_reg_reg<Y, A>;
op[0xfe] = &SMPcore::op_dbnz_y;
op[0xff] = &SMPcore::op_wait;
#undef op
}
#endif

View File

@ -1,6 +1,32 @@
#ifdef SMP_CPP
static void smp_state_save(unsigned char **out, void *in, size_t size) {
memcpy(*out, in, size);
*out += size;
}
static void smp_state_load(unsigned char **in, void *out, size_t size) {
memcpy(out, *in, size);
*in += size;
}
void SMP::serialize(serializer &s) {
Processor::serialize(s);
s.integer(snes_spc_time);
s.array(samplebuffer);
unsigned char state[SNES_SPC::state_size];
unsigned char *p = state;
memset(&state, 0, SNES_SPC::state_size);
if(s.mode() == serializer::Save) {
snes_spc.copy_state(&p, smp_state_save);
s.array(state);
} else if(s.mode() == serializer::Load) {
s.array(state);
snes_spc.copy_state(&p, smp_state_load);
} else {
s.array(state);
}
}
#endif

View File

@ -21,9 +21,19 @@ void SMP::step(unsigned clocks) {
}
void SMP::synchronize_cpu() {
if(CPU::Threaded == true) {
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread);
} else {
while(clock >= 0) cpu.enter();
}
}
void SMP::synchronize_dsp() {
if(DSP::Threaded == true) {
if(dsp.clock < 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(dsp.thread);
} else {
while(dsp.clock < 0) dsp.enter();
}
}
uint8 SMP::port_read(uint8 port) {
@ -34,7 +44,7 @@ void SMP::port_write(uint8 port, uint8 data) {
snes_spc.write_port(snes_spc_time, port & 3, data);
}
void SMP::run() {
void SMP::enter() {
step(24);
if(++snes_spc_time >= snes_spc.clock_rate / 60) {
snes_spc.end_frame(snes_spc_time);

View File

@ -2,6 +2,7 @@
class SMP : public Processor {
public:
enum : bool { Threaded = false };
alwaysinline void step(unsigned clocks);
alwaysinline void synchronize_cpu();
alwaysinline void synchronize_dsp();
@ -9,7 +10,7 @@ public:
uint8 port_read(uint8 port);
void port_write(uint8 port, uint8 data);
void run();
void enter();
void power();
void reset();

View File

@ -22,7 +22,11 @@ void PPU::step(unsigned clocks) {
}
void PPU::synchronize_cpu() {
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread);
if(CPU::Threaded == true) {
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread);
} else {
while(clock >= 0) cpu.enter();
}
}
void PPU::Enter() { ppu.enter(); }

View File

@ -1,5 +1,6 @@
class PPU : public Processor, public PPUcounter, public MMIO {
public:
enum : bool { Threaded = true };
alwaysinline void step(unsigned clocks);
alwaysinline void synchronize_cpu();
@ -8,6 +9,7 @@ public:
bool overscan() const;
bool hires() const;
void enter();
void power();
void reset();
@ -42,7 +44,6 @@ private:
} display;
static void Enter();
void enter();
void add_clocks(unsigned);
void scanline();

View File

@ -1,10 +0,0 @@
namespace Info {
static const char Name[] = "asnes";
static const char Version[] = "067.20";
static const unsigned SerializerVersion = 12;
}
#include <cpu/cpu.hpp>
#include <smp/smp.hpp>
#include <dsp/dsp.hpp>
#include <ppu/ppu.hpp>

9
snes/profile-baseline.hpp Executable file
View File

@ -0,0 +1,9 @@
namespace Info {
static const char Profile[] = "Baseline";
static const char ProfileName[] = "Supersedence";
}
#include <cpu/cpu.hpp>
#include <smp/smp.hpp>
#include <fast/dsp/dsp.hpp>
#include <fast/ppu/ppu.hpp>

View File

@ -1,10 +0,0 @@
namespace Info {
static const char Name[] = "bsnes";
static const char Version[] = "067.20";
static const unsigned SerializerVersion = 12;
}
#include <cpu/cpu.hpp>
#include <smp/smp.hpp>
#include <fast/dsp/dsp.hpp>
#include <fast/ppu/ppu.hpp>

View File

@ -1,10 +0,0 @@
namespace Info {
static const char Name[] = "csnes";
static const char Version[] = "067.20";
static const unsigned SerializerVersion = 12;
}
#include <fast/cpu/cpu.hpp>
#include <fast/smp/smp.hpp>
#include <fast/dsp/dsp.hpp>
#include <fast/ppu/ppu.hpp>

9
snes/profile-performance.hpp Executable file
View File

@ -0,0 +1,9 @@
namespace Info {
static const char Profile[] = "Performance";
static const char ProfileName[] = "Supersonic";
}
#include <fast/cpu/cpu.hpp>
#include <smp/smp.hpp>
#include <fast/dsp/dsp.hpp>
#include <fast/ppu/ppu.hpp>

9
snes/profile-research.hpp Executable file
View File

@ -0,0 +1,9 @@
namespace Info {
static const char Profile[] = "Research";
static const char ProfileName[] = "Superfluous";
}
#include <cpu/cpu.hpp>
#include <smp/smp.hpp>
#include <dsp/dsp.hpp>
#include <ppu/ppu.hpp>

View File

@ -21,15 +21,19 @@ void SMP::step(unsigned clocks) {
}
void SMP::synchronize_cpu() {
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread);
if(CPU::Threaded == true) {
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread);
} else {
while(clock >= 0) cpu.enter();
}
}
void SMP::synchronize_dsp() {
#if defined(PROFILE_ASNES)
if(dsp.clock < 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(dsp.thread);
#else
while(dsp.clock < 0 && scheduler.sync != Scheduler::SynchronizeMode::All) dsp.run();
#endif
if(DSP::Threaded == true) {
if(dsp.clock < 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(dsp.thread);
} else {
while(dsp.clock < 0) dsp.enter();
}
}
void SMP::Enter() { smp.enter(); }

View File

@ -1,5 +1,6 @@
class SMP : public Processor, public SMPcore {
public:
enum : bool { Threaded = true };
alwaysinline void step(unsigned clocks);
alwaysinline void synchronize_cpu();
alwaysinline void synchronize_dsp();
@ -7,6 +8,7 @@ public:
uint8 port_read(uint8 port);
void port_write(uint8 port, uint8 data);
void enter();
void power();
void reset();
@ -45,7 +47,6 @@ private:
} status;
static void Enter();
void enter();
debugvirtual void op_step();
friend class SMPcore;

View File

@ -1,3 +1,11 @@
namespace SNES {
namespace Info {
static const char Name[] = "bsnes";
static const char Version[] = "067.21";
static const unsigned SerializerVersion = 12;
}
}
//#define DEBUGGER
#define CHEAT_SYSTEM
@ -14,6 +22,7 @@
#include <nall/function.hpp>
#include <nall/moduloarray.hpp>
#include <nall/platform.hpp>
#include <nall/priorityqueue.hpp>
#include <nall/property.hpp>
#include <nall/serializer.hpp>
#include <nall/stdint.hpp>
@ -67,12 +76,12 @@ namespace SNES {
#include <smp/core/core.hpp>
#include <ppu/counter/counter.hpp>
#if defined(PROFILE_ASNES)
#include "profile-asnes.hpp"
#elif defined(PROFILE_BSNES)
#include "profile-bsnes.hpp"
#elif defined(PROFILE_CSNES)
#include "profile-csnes.hpp"
#if defined(PROFILE_RESEARCH)
#include "profile-research.hpp"
#elif defined(PROFILE_BASELINE)
#include "profile-baseline.hpp"
#elif defined(PROFILE_PERFORMANCE)
#include "profile-performance.hpp"
#endif
#include <system/system.hpp>

View File

@ -6,6 +6,7 @@ serializer System::serialize() {
unsigned signature = 0x31545342, version = Info::SerializerVersion, crc32 = cartridge.crc32();
char description[512];
memset(&description, 0, sizeof description);
strcpy(description, Info::Profile);
s.integer(signature);
s.integer(version);
@ -28,6 +29,7 @@ bool System::unserialize(serializer &s) {
if(signature != 0x31545342) return false;
if(version != Info::SerializerVersion) return false;
//if(crc32 != cartridge.crc32()) return false;
if(strcmp(description, Info::Profile)) return false;
reset();
serialize_all(s);

View File

@ -26,19 +26,25 @@ void System::run() {
}
void System::runtosave() {
scheduler.sync = Scheduler::SynchronizeMode::CPU;
runthreadtosave();
if(CPU::Threaded == true) {
scheduler.sync = Scheduler::SynchronizeMode::CPU;
runthreadtosave();
}
scheduler.thread = smp.thread;
runthreadtosave();
if(SMP::Threaded == true) {
scheduler.thread = smp.thread;
runthreadtosave();
}
scheduler.thread = ppu.thread;
runthreadtosave();
if(PPU::Threaded == true) {
scheduler.thread = ppu.thread;
runthreadtosave();
}
#if !defined(DSP_STATE_MACHINE)
scheduler.thread = dsp.thread;
runthreadtosave();
#endif
if(DSP::Threaded == true) {
scheduler.thread = dsp.thread;
runthreadtosave();
}
for(unsigned i = 0; i < cpu.coprocessors.size(); i++) {
Processor &chip = *cpu.coprocessors[i];