mirror of
https://github.com/ares-emulator/ares.git
synced 2026-11-08 08:03:07 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97a3a28d86 | ||
|
|
6ec765f2c4 | ||
|
|
54c7b4692d | ||
|
|
66067f0015 | ||
|
|
4c66de6f27 | ||
|
|
6a17b5ed4f | ||
|
|
8135dfdac9 | ||
|
|
a0000c7846 | ||
|
|
b6a85353bf | ||
|
|
c2453cb634 | ||
|
|
59b86cd3a8 | ||
|
|
c26f9d912a |
No files matched your search
+32
-75
@@ -25,25 +25,25 @@ link :=
|
||||
ifeq ($(platform),x)
|
||||
link += -s
|
||||
|
||||
ruby := video.glx video.xv video.sdl video.qtimage
|
||||
ruby += audio.alsa audio.openal audio.oss audio.pulseaudio audio.ao
|
||||
ruby := video.glx video.xv video.qtraster video.sdl
|
||||
ruby += audio.alsa audio.openal audio.oss audio.pulseaudio audio.pulseaudiosimple audio.ao
|
||||
ruby += input.sdl input.x
|
||||
|
||||
link += $(if $(findstring audio.openal,$(ruby)),-lopenal)
|
||||
else ifeq ($(platform),osx)
|
||||
ruby := video.qtimage
|
||||
ruby := video.qtopengl video.qtraster
|
||||
ruby += audio.openal
|
||||
ruby += input.carbon
|
||||
|
||||
link += $(if $(findstring audio.openal,$(ruby)),-framework OpenAL)
|
||||
else ifeq ($(platform),win)
|
||||
link += -mwindows
|
||||
# link += -mconsole
|
||||
link += -mwindows -mthreads
|
||||
# link += -mconsole -mthreads
|
||||
link += -s -luuid -lkernel32 -luser32 -lgdi32 -lshell32
|
||||
# statically link Qt for Windows build
|
||||
link += -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
|
||||
|
||||
ruby := video.direct3d video.wgl video.directdraw video.gdi video.qtimage
|
||||
ruby := video.direct3d video.wgl video.directdraw video.gdi video.qtraster
|
||||
ruby += audio.directsound
|
||||
ruby += input.rawinput input.directinput
|
||||
|
||||
@@ -72,24 +72,16 @@ link += $(call ifhas,audio.pulseaudio,$(ruby),-lpulse-simple)
|
||||
link += $(call ifhas,input.directinput,$(ruby),-ldinput8 -ldxguid)
|
||||
link += $(call ifhas,input.rawinput,$(ruby),-ldinput8 -ldxguid)
|
||||
|
||||
####################
|
||||
### core objects ###
|
||||
####################
|
||||
###############
|
||||
### objects ###
|
||||
###############
|
||||
|
||||
objects := libco ruby libreader libfilter
|
||||
objects := libco ruby
|
||||
objects += system cartridge cheat
|
||||
objects += memory smemory cpu cpucore scpu smp smpcore ssmp sdsp ppu bppu
|
||||
objects += sgb superfx sa1 bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010
|
||||
|
||||
ifeq ($(enable_gzip),true)
|
||||
objects += adler32 compress crc32 deflate gzio inffast inflate inftrees ioapi trees unzip zip zutil
|
||||
flags += -DGZIP_SUPPORT
|
||||
endif
|
||||
|
||||
ifeq ($(enable_jma),true)
|
||||
objects += jma jcrc32 lzmadec 7zlzma iiostrm inbyte lzma winout
|
||||
flags += -DJMA_SUPPORT
|
||||
endif
|
||||
objects += supergameboy superfx sa1
|
||||
objects += bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010 st011 st018
|
||||
objects += 21fx
|
||||
|
||||
######################
|
||||
### implicit rules ###
|
||||
@@ -120,9 +112,6 @@ rubydef := $(foreach c,$(subst .,_,$(call strupper,$(ruby))),-D$c)
|
||||
obj/ruby.o: lib/ruby/ruby.cpp $(call rwildcard,lib/ruby/*)
|
||||
$(call compile,$(rubydef) $(rubyflags))
|
||||
obj/libco.o: lib/libco/libco.c lib/libco/*
|
||||
$(c) -O3 -fomit-frame-pointer -static -Ilib -c $< -o $@
|
||||
obj/libreader.o: lib/libreader/libreader.cpp lib/libreader/*
|
||||
obj/libfilter.o: lib/libfilter/libfilter.cpp lib/libfilter/*
|
||||
|
||||
#################
|
||||
### utilities ###
|
||||
@@ -166,7 +155,7 @@ obj/sdsp.o: dsp/sdsp/sdsp.cpp dsp/sdsp/*
|
||||
###########
|
||||
|
||||
obj/ppu.o : ppu/ppu.cpp ppu/*
|
||||
obj/bppu.o: ppu/bppu/bppu.cpp ppu/bppu/*
|
||||
obj/bppu.o: ppu/bppu/bppu.cpp $(call rwildcard,ppu/bppu/)
|
||||
|
||||
##############
|
||||
### system ###
|
||||
@@ -178,51 +167,23 @@ obj/system.o: system/system.cpp $(call rwildcard,system/)
|
||||
### special chips ###
|
||||
#####################
|
||||
|
||||
obj/sgb.o : chip/sgb/sgb.cpp $(call rwildcard,chip/sgb/)
|
||||
obj/superfx.o: chip/superfx/superfx.cpp $(call rwildcard,chip/superfx/)
|
||||
obj/sa1.o : chip/sa1/sa1.cpp $(call rwildcard,chip/sa1/)
|
||||
obj/bsx.o : chip/bsx/bsx.cpp chip/bsx/*
|
||||
obj/srtc.o : chip/srtc/srtc.cpp chip/srtc/*
|
||||
obj/sdd1.o : chip/sdd1/sdd1.cpp chip/sdd1/*
|
||||
obj/spc7110.o: chip/spc7110/spc7110.cpp chip/spc7110/*
|
||||
obj/cx4.o : chip/cx4/cx4.cpp chip/cx4/*
|
||||
obj/dsp1.o : chip/dsp1/dsp1.cpp chip/dsp1/*
|
||||
obj/dsp2.o : chip/dsp2/dsp2.cpp chip/dsp2/*
|
||||
obj/dsp3.o : chip/dsp3/dsp3.cpp chip/dsp3/*
|
||||
obj/dsp4.o : chip/dsp4/dsp4.cpp chip/dsp4/*
|
||||
obj/obc1.o : chip/obc1/obc1.cpp chip/obc1/*
|
||||
obj/st010.o : chip/st010/st010.cpp chip/st010/*
|
||||
|
||||
############
|
||||
### zlib ###
|
||||
############
|
||||
|
||||
obj/adler32.o : lib/zlib/adler32.c lib/zlib/*
|
||||
obj/compress.o: lib/zlib/compress.c lib/zlib/*
|
||||
obj/crc32.o : lib/zlib/crc32.c lib/zlib/*
|
||||
obj/deflate.o : lib/zlib/deflate.c lib/zlib/*
|
||||
obj/gzio.o : lib/zlib/gzio.c lib/zlib/*
|
||||
obj/inffast.o : lib/zlib/inffast.c lib/zlib/*
|
||||
obj/inflate.o : lib/zlib/inflate.c lib/zlib/*
|
||||
obj/inftrees.o: lib/zlib/inftrees.c lib/zlib/*
|
||||
obj/ioapi.o : lib/zlib/ioapi.c lib/zlib/*
|
||||
obj/trees.o : lib/zlib/trees.c lib/zlib/*
|
||||
obj/unzip.o : lib/zlib/unzip.c lib/zlib/*
|
||||
obj/zip.o : lib/zlib/zip.c lib/zlib/*
|
||||
obj/zutil.o : lib/zlib/zutil.c lib/zlib/*
|
||||
|
||||
##############
|
||||
### libjma ###
|
||||
##############
|
||||
|
||||
obj/jma.o : lib/libjma/jma.cpp lib/libjma/*
|
||||
obj/jcrc32.o : lib/libjma/jcrc32.cpp lib/libjma/*
|
||||
obj/lzmadec.o: lib/libjma/lzmadec.cpp lib/libjma/*
|
||||
obj/7zlzma.o : lib/libjma/7zlzma.cpp lib/libjma/*
|
||||
obj/iiostrm.o: lib/libjma/iiostrm.cpp lib/libjma/*
|
||||
obj/inbyte.o : lib/libjma/inbyte.cpp lib/libjma/*
|
||||
obj/lzma.o : lib/libjma/lzma.cpp lib/libjma/*
|
||||
obj/winout.o : lib/libjma/winout.cpp lib/libjma/*
|
||||
obj/supergameboy.o: chip/supergameboy/supergameboy.cpp $(call rwildcard,chip/supergameboy/)
|
||||
obj/superfx.o : chip/superfx/superfx.cpp $(call rwildcard,chip/superfx/)
|
||||
obj/sa1.o : chip/sa1/sa1.cpp $(call rwildcard,chip/sa1/)
|
||||
obj/bsx.o : chip/bsx/bsx.cpp chip/bsx/*
|
||||
obj/srtc.o : chip/srtc/srtc.cpp chip/srtc/*
|
||||
obj/sdd1.o : chip/sdd1/sdd1.cpp chip/sdd1/*
|
||||
obj/spc7110.o : chip/spc7110/spc7110.cpp chip/spc7110/*
|
||||
obj/cx4.o : chip/cx4/cx4.cpp chip/cx4/*
|
||||
obj/dsp1.o : chip/dsp1/dsp1.cpp chip/dsp1/*
|
||||
obj/dsp2.o : chip/dsp2/dsp2.cpp chip/dsp2/*
|
||||
obj/dsp3.o : chip/dsp3/dsp3.cpp chip/dsp3/*
|
||||
obj/dsp4.o : chip/dsp4/dsp4.cpp chip/dsp4/*
|
||||
obj/obc1.o : chip/obc1/obc1.cpp chip/obc1/*
|
||||
obj/st010.o : chip/st010/st010.cpp chip/st010/*
|
||||
obj/st011.o : chip/st011/st011.cpp chip/st011/*
|
||||
obj/st018.o : chip/st018/st018.cpp chip/st018/*
|
||||
obj/21fx.o : chip/21fx/21fx.cpp chip/21fx/*
|
||||
|
||||
###############
|
||||
### targets ###
|
||||
@@ -262,9 +223,5 @@ help:
|
||||
@echo " mingw32-gcc - MinGW compiler"
|
||||
@echo " i586-mingw32-gcc - MinGW cross compiler"
|
||||
@echo ""
|
||||
@echo "Available options:"
|
||||
@echo " enable_gzip=[true|false] - Enable ZIP / GZ support (default=false)"
|
||||
@echo " enable_jma=[true|false] - Enable JMA support (default=false)"
|
||||
@echo ""
|
||||
@echo "Example: $(MAKE) platform=x compiler=gcc enable_gzip=true"
|
||||
@echo "Example: $(MAKE) platform=x compiler=gcc"
|
||||
@echo ""
|
||||
+12
-9
@@ -1,11 +1,6 @@
|
||||
#define BSNES_VERSION "0.047"
|
||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||
|
||||
#define BUSCORE sBus
|
||||
#define CPUCORE sCPU
|
||||
#define SMPCORE sSMP
|
||||
#define DSPCORE sDSP
|
||||
#define PPUCORE bPPU
|
||||
static const char bsnesVersion[] = "0.059";
|
||||
static const char bsnesTitle[] = "bsnes";
|
||||
static const unsigned bsnesSerializerVersion = 4;
|
||||
|
||||
//S-DSP can be encapsulated into a state machine using #define magic
|
||||
//this avoids ~2.048m co_switch() calls per second (~5% speedup)
|
||||
@@ -14,19 +9,25 @@
|
||||
//game genie + pro action replay code support (~2% speed hit)
|
||||
#define CHEAT_SYSTEM
|
||||
|
||||
//enable debugging extensions (~15% speed hit)
|
||||
//#define DEBUGGER
|
||||
|
||||
#include <libco/libco.h>
|
||||
|
||||
#include <nall/algorithm.hpp>
|
||||
#include <nall/any.hpp>
|
||||
#include <nall/array.hpp>
|
||||
#include <nall/bit.hpp>
|
||||
#include <nall/detect.hpp>
|
||||
#include <nall/dl.hpp>
|
||||
#include <nall/endian.hpp>
|
||||
#include <nall/file.hpp>
|
||||
#include <nall/function.hpp>
|
||||
#include <nall/moduloarray.hpp>
|
||||
#include <nall/new.hpp>
|
||||
#include <nall/platform.hpp>
|
||||
#include <nall/priorityqueue.hpp>
|
||||
#include <nall/property.hpp>
|
||||
#include <nall/serializer.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/string.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
@@ -36,8 +37,10 @@ using namespace nall;
|
||||
typedef int8_t int8;
|
||||
typedef int16_t int16;
|
||||
typedef int32_t int32;
|
||||
typedef int64_t int64;
|
||||
typedef uint8_t uint8;
|
||||
typedef uint16_t uint16;
|
||||
typedef uint32_t uint32;
|
||||
typedef uint64_t uint64;
|
||||
|
||||
#include "interface.hpp"
|
||||
Binary file not shown.
+61
-85
@@ -1,47 +1,54 @@
|
||||
#include <../base.hpp>
|
||||
#include <nall/crc32.hpp>
|
||||
#include <nall/sha256.hpp>
|
||||
|
||||
#define CARTRIDGE_CPP
|
||||
namespace SNES {
|
||||
|
||||
#include "header.cpp"
|
||||
#include "gameboyheader.cpp"
|
||||
#include "serialization.cpp"
|
||||
|
||||
namespace memory {
|
||||
MappedRAM cartrom, cartram, cartrtc;
|
||||
MappedRAM bsxflash, bsxram, bsxpram;
|
||||
MappedRAM stArom, stAram;
|
||||
MappedRAM stBrom, stBram;
|
||||
MappedRAM gbrom, gbram;
|
||||
MappedRAM gbrom, gbram, gbrtc;
|
||||
};
|
||||
|
||||
Cartridge cartridge;
|
||||
|
||||
void Cartridge::load(Mode cartridge_mode) {
|
||||
cartinfo_t cartinfo;
|
||||
read_header(cartinfo, memory::cartrom.data(), memory::cartrom.size());
|
||||
set_cartinfo(cartinfo);
|
||||
mode = cartridge_mode;
|
||||
read_header(memory::cartrom.data(), memory::cartrom.size());
|
||||
|
||||
set(mode, cartridge_mode);
|
||||
|
||||
if(cartinfo.ram_size > 0) {
|
||||
memory::cartram.map(new(zeromemory) uint8_t[cartinfo.ram_size], cartinfo.ram_size);
|
||||
if(ram_size > 0) {
|
||||
memory::cartram.map(allocate<uint8_t>(ram_size, 0xff), ram_size);
|
||||
}
|
||||
|
||||
if(cartinfo.srtc || cartinfo.spc7110rtc) {
|
||||
memory::cartrtc.map(new(zeromemory) uint8_t[20], 20);
|
||||
if(has_srtc || has_spc7110rtc) {
|
||||
memory::cartrtc.map(allocate<uint8_t>(20, 0xff), 20);
|
||||
}
|
||||
|
||||
if(mode() == ModeBsx) {
|
||||
memory::bsxram.map (new(zeromemory) uint8_t[ 32 * 1024], 32 * 1024);
|
||||
memory::bsxpram.map(new(zeromemory) uint8_t[512 * 1024], 512 * 1024);
|
||||
if(mode == ModeBsx) {
|
||||
memory::bsxram.map (allocate<uint8_t>( 32 * 1024, 0xff), 32 * 1024);
|
||||
memory::bsxpram.map(allocate<uint8_t>(512 * 1024, 0xff), 512 * 1024);
|
||||
}
|
||||
|
||||
if(mode() == ModeSufamiTurbo) {
|
||||
if(memory::stArom.data()) memory::stAram.map(new(zeromemory) uint8_t[128 * 1024], 128 * 1024);
|
||||
if(memory::stBrom.data()) memory::stBram.map(new(zeromemory) uint8_t[128 * 1024], 128 * 1024);
|
||||
if(mode == ModeSufamiTurbo) {
|
||||
if(memory::stArom.data()) memory::stAram.map(allocate<uint8_t>(128 * 1024, 0xff), 128 * 1024);
|
||||
if(memory::stBrom.data()) memory::stBram.map(allocate<uint8_t>(128 * 1024, 0xff), 128 * 1024);
|
||||
}
|
||||
|
||||
if(mode() == ModeSuperGameBoy) {
|
||||
if(memory::gbrom.data()) memory::gbram.map(new(zeromemory) uint8_t[64 * 1024], 64 * 1024);
|
||||
if(mode == ModeSuperGameBoy) {
|
||||
if(memory::gbrom.data()) {
|
||||
unsigned ram_size = gameboy_ram_size();
|
||||
unsigned rtc_size = gameboy_rtc_size();
|
||||
|
||||
if(ram_size) memory::gbram.map(allocate<uint8_t>(ram_size, 0xff), ram_size);
|
||||
if(rtc_size) memory::gbrtc.map(allocate<uint8_t>(rtc_size, 0x00), rtc_size);
|
||||
}
|
||||
}
|
||||
|
||||
memory::cartrom.write_protect(true);
|
||||
@@ -56,9 +63,38 @@ void Cartridge::load(Mode cartridge_mode) {
|
||||
memory::stBram.write_protect(false);
|
||||
memory::gbrom.write_protect(true);
|
||||
memory::gbram.write_protect(false);
|
||||
memory::gbrtc.write_protect(false);
|
||||
|
||||
unsigned checksum = ~0;
|
||||
for(unsigned n = 0; n < memory::cartrom.size(); n++) checksum = crc32_adjust(checksum, memory::cartrom[n]);
|
||||
if(memory::bsxflash.size() != 0 && memory::bsxflash.size() != ~0)
|
||||
for(unsigned n = 0; n < memory::bsxflash.size(); n++) checksum = crc32_adjust(checksum, memory::bsxflash[n]);
|
||||
if(memory::stArom.size() != 0 && memory::stArom.size() != ~0)
|
||||
for(unsigned n = 0; n < memory::stArom.size(); n++) checksum = crc32_adjust(checksum, memory::stArom[n]);
|
||||
if(memory::stBrom.size() != 0 && memory::stBrom.size() != ~0)
|
||||
for(unsigned n = 0; n < memory::stBrom.size(); n++) checksum = crc32_adjust(checksum, memory::stBrom[n]);
|
||||
if(memory::gbrom.size() != 0 && memory::gbrom.size() != ~0)
|
||||
for(unsigned n = 0; n < memory::gbrom.size(); n++) checksum = crc32_adjust(checksum, memory::gbrom[n]);
|
||||
crc32 = ~checksum;
|
||||
|
||||
#if 0
|
||||
fprintf(stdout, "crc32 = %.8x\n", (unsigned)crc32);
|
||||
|
||||
sha256_ctx sha;
|
||||
uint8_t shahash[32];
|
||||
sha256_init(&sha);
|
||||
sha256_chunk(&sha, memory::cartrom.data(), memory::cartrom.size());
|
||||
sha256_final(&sha);
|
||||
sha256_hash(&sha, shahash);
|
||||
|
||||
fprintf(stdout, "sha256 = ");
|
||||
for(unsigned i = 0; i < 32; i++) fprintf(stdout, "%.2x", shahash[i]);
|
||||
fprintf(stdout, "\n");
|
||||
#endif
|
||||
|
||||
bus.load_cart();
|
||||
set(loaded, true);
|
||||
system.serialize_init();
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
void Cartridge::unload() {
|
||||
@@ -74,20 +110,19 @@ void Cartridge::unload() {
|
||||
memory::stBram.reset();
|
||||
memory::gbrom.reset();
|
||||
memory::gbram.reset();
|
||||
memory::gbrtc.reset();
|
||||
|
||||
if(loaded() == false) return;
|
||||
if(loaded == false) return;
|
||||
bus.unload_cart();
|
||||
set(loaded, false);
|
||||
loaded = false;
|
||||
}
|
||||
|
||||
Cartridge::Type Cartridge::detect_image_type(uint8_t *data, unsigned size) const {
|
||||
cartinfo_t info;
|
||||
read_header(info, data, size);
|
||||
return info.type;
|
||||
bool Cartridge::has_21fx() const {
|
||||
return s21fx.exists();
|
||||
}
|
||||
|
||||
Cartridge::Cartridge() {
|
||||
set(loaded, false);
|
||||
loaded = false;
|
||||
unload();
|
||||
}
|
||||
|
||||
@@ -95,63 +130,4 @@ Cartridge::~Cartridge() {
|
||||
unload();
|
||||
}
|
||||
|
||||
void Cartridge::set_cartinfo(const Cartridge::cartinfo_t &source) {
|
||||
set(region, source.region);
|
||||
set(mapper, source.mapper);
|
||||
set(dsp1_mapper, source.dsp1_mapper);
|
||||
|
||||
set(has_bsx_slot, source.bsx_slot);
|
||||
set(has_superfx, source.superfx);
|
||||
set(has_sa1, source.sa1);
|
||||
set(has_srtc, source.srtc);
|
||||
set(has_sdd1, source.sdd1);
|
||||
set(has_spc7110, source.spc7110);
|
||||
set(has_spc7110rtc, source.spc7110rtc);
|
||||
set(has_cx4, source.cx4);
|
||||
set(has_dsp1, source.dsp1);
|
||||
set(has_dsp2, source.dsp2);
|
||||
set(has_dsp3, source.dsp3);
|
||||
set(has_dsp4, source.dsp4);
|
||||
set(has_obc1, source.obc1);
|
||||
set(has_st010, source.st010);
|
||||
set(has_st011, source.st011);
|
||||
set(has_st018, source.st018);
|
||||
}
|
||||
|
||||
//==========
|
||||
//cartinfo_t
|
||||
//==========
|
||||
|
||||
void Cartridge::cartinfo_t::reset() {
|
||||
type = TypeUnknown;
|
||||
mapper = LoROM;
|
||||
dsp1_mapper = DSP1Unmapped;
|
||||
region = NTSC;
|
||||
|
||||
rom_size = 0;
|
||||
ram_size = 0;
|
||||
|
||||
bsx_slot = false;
|
||||
superfx = false;
|
||||
sa1 = false;
|
||||
srtc = false;
|
||||
sdd1 = false;
|
||||
spc7110 = false;
|
||||
spc7110rtc = false;
|
||||
cx4 = false;
|
||||
dsp1 = false;
|
||||
dsp2 = false;
|
||||
dsp3 = false;
|
||||
dsp4 = false;
|
||||
obc1 = false;
|
||||
st010 = false;
|
||||
st011 = false;
|
||||
st018 = false;
|
||||
}
|
||||
|
||||
Cartridge::cartinfo_t::cartinfo_t() {
|
||||
reset();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
+34
-49
@@ -1,4 +1,4 @@
|
||||
class Cartridge : public property {
|
||||
class Cartridge : property<Cartridge> {
|
||||
public:
|
||||
enum Mode {
|
||||
ModeNormal,
|
||||
@@ -15,7 +15,8 @@ public:
|
||||
TypeBsx,
|
||||
TypeSufamiTurboBios,
|
||||
TypeSufamiTurbo,
|
||||
TypeSuperGameBoyBios,
|
||||
TypeSuperGameBoy1Bios,
|
||||
TypeSuperGameBoy2Bios,
|
||||
TypeGameBoy,
|
||||
TypeUnknown,
|
||||
};
|
||||
@@ -46,60 +47,41 @@ public:
|
||||
DSP1HiROM,
|
||||
};
|
||||
|
||||
//properties can be read via operator(), eg "if(cartridge.loaded() == true)";
|
||||
//warning: if loaded() == false, no other property is considered valid!
|
||||
readonly<bool> loaded; //is a base cartridge inserted?
|
||||
readonly<unsigned> crc32; //crc32 of all cartridges (base+slot(s))
|
||||
|
||||
property_t<bool> loaded; //is a base cartridge inserted?
|
||||
readonly<Mode> mode;
|
||||
readonly<Type> type;
|
||||
readonly<Region> region;
|
||||
readonly<MemoryMapper> mapper;
|
||||
readonly<DSP1MemoryMapper> dsp1_mapper;
|
||||
|
||||
property_t<Mode> mode;
|
||||
property_t<Region> region;
|
||||
property_t<MemoryMapper> mapper;
|
||||
property_t<DSP1MemoryMapper> dsp1_mapper;
|
||||
readonly<bool> has_bsx_slot;
|
||||
readonly<bool> has_superfx;
|
||||
readonly<bool> has_sa1;
|
||||
readonly<bool> has_srtc;
|
||||
readonly<bool> has_sdd1;
|
||||
readonly<bool> has_spc7110;
|
||||
readonly<bool> has_spc7110rtc;
|
||||
readonly<bool> has_cx4;
|
||||
readonly<bool> has_dsp1;
|
||||
readonly<bool> has_dsp2;
|
||||
readonly<bool> has_dsp3;
|
||||
readonly<bool> has_dsp4;
|
||||
readonly<bool> has_obc1;
|
||||
readonly<bool> has_st010;
|
||||
readonly<bool> has_st011;
|
||||
readonly<bool> has_st018;
|
||||
bool has_21fx() const;
|
||||
|
||||
property_t<bool> has_bsx_slot;
|
||||
property_t<bool> has_superfx;
|
||||
property_t<bool> has_sa1;
|
||||
property_t<bool> has_srtc;
|
||||
property_t<bool> has_sdd1;
|
||||
property_t<bool> has_spc7110, has_spc7110rtc;
|
||||
property_t<bool> has_cx4;
|
||||
property_t<bool> has_dsp1, has_dsp2, has_dsp3, has_dsp4;
|
||||
property_t<bool> has_obc1;
|
||||
property_t<bool> has_st010, has_st011, has_st018;
|
||||
|
||||
//main interface
|
||||
void load(Mode);
|
||||
//void read();
|
||||
//void load();
|
||||
void unload();
|
||||
Type detect_image_type(uint8_t *data, unsigned size) const;
|
||||
|
||||
void serialize(serializer&);
|
||||
Cartridge();
|
||||
~Cartridge();
|
||||
|
||||
private:
|
||||
struct cartinfo_t {
|
||||
Type type;
|
||||
Region region;
|
||||
MemoryMapper mapper;
|
||||
DSP1MemoryMapper dsp1_mapper;
|
||||
unsigned rom_size, ram_size;
|
||||
|
||||
bool bsx_slot;
|
||||
bool superfx;
|
||||
bool sa1;
|
||||
bool srtc;
|
||||
bool sdd1;
|
||||
bool spc7110, spc7110rtc;
|
||||
bool cx4;
|
||||
bool dsp1, dsp2, dsp3, dsp4;
|
||||
bool obc1;
|
||||
bool st010, st011, st018;
|
||||
|
||||
void reset();
|
||||
cartinfo_t();
|
||||
};
|
||||
|
||||
enum HeaderField {
|
||||
CartName = 0x00,
|
||||
Mapper = 0x15,
|
||||
@@ -114,10 +96,13 @@ private:
|
||||
ResetVector = 0x3c,
|
||||
};
|
||||
|
||||
void read_header(cartinfo_t &info, const uint8_t *data, unsigned size) const;
|
||||
unsigned ram_size;
|
||||
void read_header(const uint8_t *data, unsigned size);
|
||||
unsigned find_header(const uint8_t *data, unsigned size) const;
|
||||
unsigned score_header(const uint8_t *data, unsigned size, unsigned addr) const;
|
||||
void set_cartinfo(const cartinfo_t&);
|
||||
|
||||
unsigned gameboy_ram_size() const;
|
||||
unsigned gameboy_rtc_size() const;
|
||||
};
|
||||
|
||||
namespace memory {
|
||||
@@ -125,7 +110,7 @@ namespace memory {
|
||||
extern MappedRAM bsxflash, bsxram, bsxpram;
|
||||
extern MappedRAM stArom, stAram;
|
||||
extern MappedRAM stBrom, stBram;
|
||||
extern MappedRAM gbrom, gbram;
|
||||
extern MappedRAM gbrom, gbram, gbrtc;
|
||||
};
|
||||
|
||||
extern Cartridge cartridge;
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifdef CARTRIDGE_CPP
|
||||
|
||||
unsigned Cartridge::gameboy_ram_size() const {
|
||||
if(memory::gbrom.size() < 512) return 0;
|
||||
switch(memory::gbrom[0x0149]) {
|
||||
case 0x00: return 0 * 1024;
|
||||
case 0x01: return 8 * 1024;
|
||||
case 0x02: return 8 * 1024;
|
||||
case 0x03: return 32 * 1024;
|
||||
case 0x04: return 128 * 1024;
|
||||
case 0x05: return 128 * 1024;
|
||||
default: return 128 * 1024;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned Cartridge::gameboy_rtc_size() const {
|
||||
if(memory::gbrom.size() < 512) return 0;
|
||||
if(memory::gbrom[0x0147] == 0x0f || memory::gbrom[0x0147] == 0x10) return 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
+104
-77
@@ -1,7 +1,28 @@
|
||||
#ifdef CARTRIDGE_CPP
|
||||
|
||||
void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size) const {
|
||||
info.reset();
|
||||
void Cartridge::read_header(const uint8_t *data, unsigned size) {
|
||||
type = TypeUnknown;
|
||||
mapper = LoROM;
|
||||
dsp1_mapper = DSP1Unmapped;
|
||||
region = NTSC;
|
||||
ram_size = 0;
|
||||
|
||||
has_bsx_slot = false;
|
||||
has_superfx = false;
|
||||
has_sa1 = false;
|
||||
has_srtc = false;
|
||||
has_sdd1 = false;
|
||||
has_spc7110 = false;
|
||||
has_spc7110rtc = false;
|
||||
has_cx4 = false;
|
||||
has_dsp1 = false;
|
||||
has_dsp2 = false;
|
||||
has_dsp3 = false;
|
||||
has_dsp4 = false;
|
||||
has_obc1 = false;
|
||||
has_st010 = false;
|
||||
has_st011 = false;
|
||||
has_st018 = false;
|
||||
|
||||
//=====================
|
||||
//detect Game Boy carts
|
||||
@@ -10,23 +31,23 @@ void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size
|
||||
if(size >= 0x0140) {
|
||||
if(data[0x0104] == 0xce && data[0x0105] == 0xed && data[0x0106] == 0x66 && data[0x0107] == 0x66
|
||||
&& data[0x0108] == 0xcc && data[0x0109] == 0x0d && data[0x010a] == 0x00 && data[0x010b] == 0x0b) {
|
||||
info.type = TypeGameBoy;
|
||||
type = TypeGameBoy;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned index = find_header(data, size);
|
||||
const uint8 mapper = data[index + Mapper];
|
||||
const uint8 mapperid = data[index + Mapper];
|
||||
const uint8 rom_type = data[index + RomType];
|
||||
const uint8 rom_size = data[index + RomSize];
|
||||
const uint8 company = data[index + Company];
|
||||
const uint8 region = data[index + CartRegion] & 0x7f;
|
||||
const uint8 regionid = data[index + CartRegion] & 0x7f;
|
||||
|
||||
info.ram_size = 1024 << (data[index + RamSize] & 7);
|
||||
if(info.ram_size == 1024) info.ram_size = 0; //no RAM present, eg RamSize == 0
|
||||
ram_size = 1024 << (data[index + RamSize] & 7);
|
||||
if(ram_size == 1024) ram_size = 0; //no RAM present
|
||||
|
||||
//0, 1, 13 = NTSC; 2 - 12 = PAL
|
||||
info.region = (region <= 1 || region >= 13) ? NTSC : PAL;
|
||||
region = (regionid <= 1 || regionid >= 13) ? NTSC : PAL;
|
||||
|
||||
//=======================
|
||||
//detect BS-X flash carts
|
||||
@@ -37,9 +58,9 @@ void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size
|
||||
const uint8_t n15 = data[index + 0x15];
|
||||
if(n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc) {
|
||||
if(data[index + 0x1a] == 0x33 || data[index + 0x1a] == 0xff) {
|
||||
info.type = TypeBsx;
|
||||
info.mapper = BSXROM;
|
||||
info.region = NTSC; //BS-X only released in Japan
|
||||
type = TypeBsx;
|
||||
mapper = BSXROM;
|
||||
region = NTSC; //BS-X only released in Japan
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -52,21 +73,26 @@ void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size
|
||||
|
||||
if(!memcmp(data, "BANDAI SFC-ADX", 14)) {
|
||||
if(!memcmp(data + 16, "SFC-ADX BACKUP", 14)) {
|
||||
info.type = TypeSufamiTurboBios;
|
||||
type = TypeSufamiTurboBios;
|
||||
} else {
|
||||
info.type = TypeSufamiTurbo;
|
||||
type = TypeSufamiTurbo;
|
||||
}
|
||||
info.mapper = STROM;
|
||||
info.region = NTSC; //Sufami Turbo only released in Japan
|
||||
return; //RAM size handled internally by load_cart_st();
|
||||
mapper = STROM;
|
||||
region = NTSC; //Sufami Turbo only released in Japan
|
||||
return; //RAM size handled outside this routine
|
||||
}
|
||||
|
||||
//==========================
|
||||
//detect Super Game Boy BIOS
|
||||
//==========================
|
||||
|
||||
if(!memcmp(data + index, "Super GAMEBOY2", 14)) {
|
||||
type = TypeSuperGameBoy2Bios;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!memcmp(data + index, "Super GAMEBOY", 13)) {
|
||||
info.type = TypeSuperGameBoyBios;
|
||||
type = TypeSuperGameBoy1Bios;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -80,118 +106,119 @@ void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size
|
||||
uint8 n13 = data[index - 13];
|
||||
if((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9')) {
|
||||
if(company == 0x33 || (data[index - 10] == 0x00 && data[index - 4] == 0x00)) {
|
||||
info.bsx_slot = true;
|
||||
has_bsx_slot = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(info.bsx_slot == true) {
|
||||
if(has_bsx_slot) {
|
||||
if(!memcmp(data + index, "Satellaview BS-X ", 21)) {
|
||||
//BS-X base cart
|
||||
info.type = TypeBsxBios;
|
||||
info.mapper = BSXROM;
|
||||
info.region = NTSC; //BS-X only released in Japan
|
||||
return; //RAM size handled internally by load_cart_bsx() -> BSXCart class
|
||||
type = TypeBsxBios;
|
||||
mapper = BSXROM;
|
||||
region = NTSC; //BS-X only released in Japan
|
||||
return; //RAM size handled internally by load_cart_bsx() -> BSXCart class
|
||||
} else {
|
||||
info.type = TypeBsxSlotted;
|
||||
info.mapper = (index == 0x7fc0 ? BSCLoROM : BSCHiROM);
|
||||
type = TypeBsxSlotted;
|
||||
mapper = (index == 0x7fc0 ? BSCLoROM : BSCHiROM);
|
||||
region = NTSC; //BS-X slotted cartridges only released in Japan
|
||||
}
|
||||
} else {
|
||||
//standard cart
|
||||
info.type = TypeNormal;
|
||||
type = TypeNormal;
|
||||
|
||||
if(index == 0x7fc0 && size >= 0x401000) {
|
||||
info.mapper = ExLoROM;
|
||||
} else if(index == 0x7fc0 && mapper == 0x32) {
|
||||
info.mapper = ExLoROM;
|
||||
mapper = ExLoROM;
|
||||
} else if(index == 0x7fc0 && mapperid == 0x32) {
|
||||
mapper = ExLoROM;
|
||||
} else if(index == 0x7fc0) {
|
||||
info.mapper = LoROM;
|
||||
mapper = LoROM;
|
||||
} else if(index == 0xffc0) {
|
||||
info.mapper = HiROM;
|
||||
mapper = HiROM;
|
||||
} else { //index == 0x40ffc0
|
||||
info.mapper = ExHiROM;
|
||||
mapper = ExHiROM;
|
||||
}
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && (rom_type == 0x13 || rom_type == 0x14 || rom_type == 0x15 || rom_type == 0x1a)) {
|
||||
info.superfx = true;
|
||||
info.mapper = SuperFXROM;
|
||||
info.ram_size = 1024 << (data[index - 3] & 7);
|
||||
if(info.ram_size == 1024) info.ram_size = 0;
|
||||
if(mapperid == 0x20 && (rom_type == 0x13 || rom_type == 0x14 || rom_type == 0x15 || rom_type == 0x1a)) {
|
||||
has_superfx = true;
|
||||
mapper = SuperFXROM;
|
||||
ram_size = 1024 << (data[index - 3] & 7);
|
||||
if(ram_size == 1024) ram_size = 0;
|
||||
}
|
||||
|
||||
if(mapper == 0x23 && (rom_type == 0x32 || rom_type == 0x34 || rom_type == 0x35)) {
|
||||
info.sa1 = true;
|
||||
info.mapper = SA1ROM;
|
||||
if(mapperid == 0x23 && (rom_type == 0x32 || rom_type == 0x34 || rom_type == 0x35)) {
|
||||
has_sa1 = true;
|
||||
mapper = SA1ROM;
|
||||
}
|
||||
|
||||
if(mapper == 0x35 && rom_type == 0x55) {
|
||||
info.srtc = true;
|
||||
if(mapperid == 0x35 && rom_type == 0x55) {
|
||||
has_srtc = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
|
||||
info.sdd1 = true;
|
||||
if(mapperid == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
|
||||
has_sdd1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x3a && (rom_type == 0xf5 || rom_type == 0xf9)) {
|
||||
info.spc7110 = true;
|
||||
info.spc7110rtc = (rom_type == 0xf9);
|
||||
info.mapper = SPC7110ROM;
|
||||
if(mapperid == 0x3a && (rom_type == 0xf5 || rom_type == 0xf9)) {
|
||||
has_spc7110 = true;
|
||||
has_spc7110rtc = (rom_type == 0xf9);
|
||||
mapper = SPC7110ROM;
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && rom_type == 0xf3) {
|
||||
info.cx4 = true;
|
||||
if(mapperid == 0x20 && rom_type == 0xf3) {
|
||||
has_cx4 = true;
|
||||
}
|
||||
|
||||
if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) {
|
||||
info.dsp1 = true;
|
||||
if((mapperid == 0x20 || mapperid == 0x21) && rom_type == 0x03) {
|
||||
has_dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x05 && company != 0xb2) {
|
||||
info.dsp1 = true;
|
||||
if(mapperid == 0x30 && rom_type == 0x05 && company != 0xb2) {
|
||||
has_dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) {
|
||||
info.dsp1 = true;
|
||||
if(mapperid == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) {
|
||||
has_dsp1 = true;
|
||||
}
|
||||
|
||||
if(info.dsp1 == true) {
|
||||
if((mapper & 0x2f) == 0x20 && size <= 0x100000) {
|
||||
info.dsp1_mapper = DSP1LoROM1MB;
|
||||
} else if((mapper & 0x2f) == 0x20) {
|
||||
info.dsp1_mapper = DSP1LoROM2MB;
|
||||
} else if((mapper & 0x2f) == 0x21) {
|
||||
info.dsp1_mapper = DSP1HiROM;
|
||||
if(has_dsp1 == true) {
|
||||
if((mapperid & 0x2f) == 0x20 && size <= 0x100000) {
|
||||
dsp1_mapper = DSP1LoROM1MB;
|
||||
} else if((mapperid & 0x2f) == 0x20) {
|
||||
dsp1_mapper = DSP1LoROM2MB;
|
||||
} else if((mapperid & 0x2f) == 0x21) {
|
||||
dsp1_mapper = DSP1HiROM;
|
||||
}
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && rom_type == 0x05) {
|
||||
info.dsp2 = true;
|
||||
if(mapperid == 0x20 && rom_type == 0x05) {
|
||||
has_dsp2 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x05 && company == 0xb2) {
|
||||
info.dsp3 = true;
|
||||
if(mapperid == 0x30 && rom_type == 0x05 && company == 0xb2) {
|
||||
has_dsp3 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x03) {
|
||||
info.dsp4 = true;
|
||||
if(mapperid == 0x30 && rom_type == 0x03) {
|
||||
has_dsp4 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x25) {
|
||||
info.obc1 = true;
|
||||
if(mapperid == 0x30 && rom_type == 0x25) {
|
||||
has_obc1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0xf6 && rom_size >= 10) {
|
||||
info.st010 = true;
|
||||
if(mapperid == 0x30 && rom_type == 0xf6 && rom_size >= 10) {
|
||||
has_st010 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0xf6 && rom_size < 10) {
|
||||
info.st011 = true;
|
||||
if(mapperid == 0x30 && rom_type == 0xf6 && rom_size < 10) {
|
||||
has_st011 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0xf5) {
|
||||
info.st018 = true;
|
||||
if(mapperid == 0x30 && rom_type == 0xf5) {
|
||||
has_st018 = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifdef CARTRIDGE_CPP
|
||||
|
||||
void Cartridge::serialize(serializer &s) {
|
||||
if(memory::cartram.size() != 0 && memory::cartram.size() != ~0) {
|
||||
s.array(memory::cartram.data(), memory::cartram.size());
|
||||
}
|
||||
|
||||
if(memory::cartrtc.size() != 0 && memory::cartrtc.size() != ~0) {
|
||||
s.array(memory::cartrtc.data(), memory::cartrtc.size());
|
||||
}
|
||||
|
||||
if(memory::bsxram.size() != 0 && memory::bsxram.size() != ~0) {
|
||||
s.array(memory::bsxram.data(), memory::bsxram.size());
|
||||
}
|
||||
|
||||
if(memory::bsxpram.size() != 0 && memory::bsxpram.size() != ~0) {
|
||||
s.array(memory::bsxpram.data(), memory::bsxpram.size());
|
||||
}
|
||||
|
||||
if(memory::stAram.size() != 0 && memory::stAram.size() != ~0) {
|
||||
s.array(memory::stAram.data(), memory::stAram.size());
|
||||
}
|
||||
|
||||
if(memory::stBram.size() != 0 && memory::stBram.size() != ~0) {
|
||||
s.array(memory::stBram.data(), memory::stBram.size());
|
||||
}
|
||||
|
||||
if(memory::gbram.size() != 0 && memory::gbram.size() != ~0) {
|
||||
s.array(memory::gbram.data(), memory::gbram.size());
|
||||
}
|
||||
|
||||
if(memory::gbrtc.size() != 0 && memory::gbrtc.size() != ~0) {
|
||||
s.array(memory::gbrtc.data(), memory::gbrtc.size());
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,3 @@
|
||||
@mingw32-make
|
||||
|
||||
::@mingw32-make enable_gzip=true enable_jma=true
|
||||
|
||||
@pause
|
||||
@@ -0,0 +1,2 @@
|
||||
bool Cheat::active() const { return cheat_enabled; }
|
||||
bool Cheat::exists(unsigned addr) const { return bitmask[addr >> 3] & 1 << (addr & 7); }
|
||||
+88
-283
@@ -5,226 +5,73 @@ namespace SNES {
|
||||
|
||||
Cheat cheat;
|
||||
|
||||
Cheat::cheat_t& Cheat::cheat_t::operator=(const Cheat::cheat_t& source) {
|
||||
enabled = source.enabled;
|
||||
code = source.code;
|
||||
desc = source.desc;
|
||||
count = source.count;
|
||||
bool Cheat::enabled() const {
|
||||
return system_enabled;
|
||||
}
|
||||
|
||||
addr.reset();
|
||||
data.reset();
|
||||
for(unsigned n = 0; n < count; n++) {
|
||||
addr[n] = source.addr[n];
|
||||
data[n] = source.data[n];
|
||||
void Cheat::enable(bool state) {
|
||||
system_enabled = state;
|
||||
cheat_enabled = system_enabled && code_enabled;
|
||||
}
|
||||
|
||||
void Cheat::synchronize() {
|
||||
memset(bitmask, 0x00, sizeof bitmask);
|
||||
code_enabled = false;
|
||||
|
||||
for(unsigned i = 0; i < size(); i++) {
|
||||
const CheatCode &code = operator[](i);
|
||||
if(code.enabled == false) continue;
|
||||
|
||||
for(unsigned n = 0; n < code.addr.size(); n++) {
|
||||
code_enabled = true;
|
||||
|
||||
unsigned addr = mirror(code.addr[n]);
|
||||
bitmask[addr >> 3] |= 1 << (addr & 7);
|
||||
if((addr & 0xffe000) == 0x7e0000) {
|
||||
//mirror $7e:0000-1fff to $00-3f|80-bf:0000-1fff
|
||||
unsigned mirroraddr;
|
||||
for(unsigned x = 0; x <= 0x3f; x++) {
|
||||
mirroraddr = ((0x00 + x) << 16) + (addr & 0x1fff);
|
||||
bitmask[mirroraddr >> 3] |= 1 << (mirroraddr & 7);
|
||||
|
||||
mirroraddr = ((0x80 + x) << 16) + (addr & 0x1fff);
|
||||
bitmask[mirroraddr >> 3] |= 1 << (mirroraddr & 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
cheat_enabled = system_enabled && code_enabled;
|
||||
}
|
||||
|
||||
//used to sort cheat code list by description
|
||||
bool Cheat::cheat_t::operator<(const Cheat::cheat_t& source) {
|
||||
return strcmp(desc, source.desc) < 0;
|
||||
}
|
||||
bool Cheat::read(unsigned addr, uint8 &data) const {
|
||||
addr = mirror(addr);
|
||||
|
||||
//parse item ("0123-4567+89AB-CDEF"), return cheat_t item
|
||||
//return true if code is valid, false otherwise
|
||||
bool Cheat::decode(const char *s, Cheat::cheat_t &item) const {
|
||||
item.enabled = false;
|
||||
item.count = 0;
|
||||
for(unsigned i = 0; i < size(); i++) {
|
||||
const CheatCode &code = operator[](i);
|
||||
if(code.enabled == false) continue;
|
||||
|
||||
lstring list;
|
||||
list.split("+", s);
|
||||
|
||||
for(unsigned n = 0; n < list.size(); n++) {
|
||||
unsigned addr;
|
||||
uint8_t data;
|
||||
type_t type;
|
||||
if(decode(list[n], addr, data, type) == false) return false;
|
||||
|
||||
item.addr[item.count] = addr;
|
||||
item.data[item.count] = data;
|
||||
item.count++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//read() is used by MemBus::read() if Cheat::enabled(addr) returns true to look up cheat code.
|
||||
//returns true if cheat code was found, false if it was not.
|
||||
//when true, cheat code substitution value is stored in data.
|
||||
bool Cheat::read(unsigned addr, uint8_t &data) const {
|
||||
addr = mirror_address(addr);
|
||||
for(unsigned i = 0; i < code.size(); i++) {
|
||||
if(enabled(i) == false) continue;
|
||||
|
||||
for(unsigned n = 0; n < code[i].count; n++) {
|
||||
if(addr == mirror_address(code[i].addr[n])) {
|
||||
data = code[i].data[n];
|
||||
for(unsigned n = 0; n < code.addr.size(); n++) {
|
||||
if(addr == mirror(code.addr[n])) {
|
||||
data = code.data[n];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//code not found, or code is disabled
|
||||
return false;
|
||||
}
|
||||
|
||||
//==============
|
||||
//master control
|
||||
//==============
|
||||
|
||||
//global cheat system enable/disable:
|
||||
//if disabled, *all* cheat codes are disabled;
|
||||
//otherwise only individually disabled codes are.
|
||||
|
||||
bool Cheat::enabled() const {
|
||||
return cheat_system_enabled;
|
||||
Cheat::Cheat() {
|
||||
system_enabled = true;
|
||||
synchronize();
|
||||
}
|
||||
|
||||
void Cheat::enable() {
|
||||
cheat_system_enabled = true;
|
||||
cheat_enabled = (cheat_system_enabled && cheat_enabled_code_exists);
|
||||
}
|
||||
//===============
|
||||
//encode / decode
|
||||
//===============
|
||||
|
||||
void Cheat::disable() {
|
||||
cheat_system_enabled = false;
|
||||
cheat_enabled = false;
|
||||
}
|
||||
|
||||
//================================
|
||||
//cheat list manipulation routines
|
||||
//================================
|
||||
|
||||
bool Cheat::add(bool enable, const char *code_, const char *desc_) {
|
||||
cheat_t item;
|
||||
if(decode(code_, item) == false) return false;
|
||||
|
||||
unsigned i = code.size();
|
||||
code[i] = item;
|
||||
code[i].enabled = enable;
|
||||
code[i].desc = desc_;
|
||||
code[i].code = code_;
|
||||
encode_description(code[i].desc);
|
||||
update(code[i]);
|
||||
|
||||
update_cheat_status();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cheat::edit(unsigned i, bool enable, const char *code_, const char *desc_) {
|
||||
cheat_t item;
|
||||
if(decode(code_, item) == false) return false;
|
||||
|
||||
//disable current code and clear from code lookup table
|
||||
code[i].enabled = false;
|
||||
update(code[i]);
|
||||
|
||||
code[i] = item;
|
||||
code[i].enabled = enable;
|
||||
code[i].desc = desc_;
|
||||
code[i].code = code_;
|
||||
encode_description(code[i].desc);
|
||||
update(code[i]);
|
||||
|
||||
update_cheat_status();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cheat::remove(unsigned i) {
|
||||
unsigned size = code.size();
|
||||
if(i >= size) return false; //also verifies size cannot be < 1
|
||||
|
||||
for(unsigned n = i; n < size - 1; n++) code[n] = code[n + 1];
|
||||
code.resize(size - 1);
|
||||
|
||||
update_cheat_status();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cheat::get(unsigned i, cheat_t &item) const {
|
||||
if(i >= code.size()) return false;
|
||||
|
||||
item = code[i];
|
||||
decode_description(item.desc);
|
||||
return true;
|
||||
}
|
||||
|
||||
//==============================
|
||||
//cheat status modifier routines
|
||||
//==============================
|
||||
|
||||
bool Cheat::enabled(unsigned i) const {
|
||||
return (i < code.size() ? code[i].enabled : false);
|
||||
}
|
||||
|
||||
void Cheat::enable(unsigned i) {
|
||||
if(i >= code.size()) return;
|
||||
|
||||
code[i].enabled = true;
|
||||
update(code[i]);
|
||||
update_cheat_status();
|
||||
}
|
||||
|
||||
void Cheat::disable(unsigned i) {
|
||||
if(i >= code.size()) return;
|
||||
|
||||
code[i].enabled = false;
|
||||
update(code[i]);
|
||||
update_cheat_status();
|
||||
}
|
||||
|
||||
//===============================
|
||||
//cheat file load / save routines
|
||||
//
|
||||
//file format:
|
||||
//"description", status, nnnn-nnnn[+nnnn-nnnn...]\r\n
|
||||
//...
|
||||
//===============================
|
||||
|
||||
void Cheat::load(string data) {
|
||||
data.replace("\r\n", "\n");
|
||||
data.qreplace(" ", "");
|
||||
|
||||
lstring line;
|
||||
line.split("\n", data);
|
||||
for(unsigned i = 0; i < line.size(); i++) {
|
||||
lstring part;
|
||||
part.qsplit(",", line[i]);
|
||||
if(part.size() != 3) continue;
|
||||
trim(part[0], "\"");
|
||||
add(part[1] == "enabled", /* code = */ part[2], /* desc = */ part[0]);
|
||||
}
|
||||
}
|
||||
|
||||
string Cheat::save() const {
|
||||
string data;
|
||||
for(unsigned i = 0; i < code.size(); i++) {
|
||||
data << "\"" << code[i].desc << "\", "
|
||||
<< (code[i].enabled ? "enabled, " : "disabled, ")
|
||||
<< code[i].code << "\r\n";
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void Cheat::clear() {
|
||||
cheat_enabled_code_exists = false;
|
||||
memset(mask, 0, 0x200000);
|
||||
code.reset();
|
||||
}
|
||||
|
||||
Cheat::Cheat() : cheat_system_enabled(true) {
|
||||
clear();
|
||||
}
|
||||
|
||||
//==================
|
||||
//internal functions
|
||||
//==================
|
||||
|
||||
//string <> binary code translation routines
|
||||
//decode() "7e123456" -> 0x7e123456
|
||||
//encode() 0x7e123456 -> "7e123456"
|
||||
|
||||
bool Cheat::decode(const char *s, unsigned &addr, uint8_t &data, type_t &type) const {
|
||||
bool Cheat::decode(const char *s, unsigned &addr, uint8 &data, Type &type) {
|
||||
string t = s;
|
||||
strlower(t);
|
||||
|
||||
@@ -270,9 +117,11 @@ bool Cheat::decode(const char *s, unsigned &addr, uint8_t &data, type_t &type) c
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
#undef ischr
|
||||
}
|
||||
|
||||
bool Cheat::encode(string &s, unsigned addr, uint8_t data, type_t type) const {
|
||||
bool Cheat::encode(string &s, unsigned addr, uint8 data, Type type) {
|
||||
char t[16];
|
||||
|
||||
if(type == ProActionReplay) {
|
||||
@@ -302,90 +151,46 @@ bool Cheat::encode(string &s, unsigned addr, uint8_t data, type_t type) const {
|
||||
}
|
||||
}
|
||||
|
||||
//speed up S-CPU memory reads by disabling cheat code lookup when either:
|
||||
//a) cheat system is disabled by user, or b) no enabled cheat codes exist
|
||||
void Cheat::update_cheat_status() {
|
||||
for(unsigned i = 0; i < code.size(); i++) {
|
||||
if(code[i].enabled) {
|
||||
cheat_enabled_code_exists = true;
|
||||
cheat_enabled = (cheat_system_enabled && cheat_enabled_code_exists);
|
||||
return;
|
||||
//========
|
||||
//internal
|
||||
//========
|
||||
|
||||
unsigned Cheat::mirror(unsigned addr) const {
|
||||
//$00-3f|80-bf:0000-1fff -> $7e:0000-1fff
|
||||
if((addr & 0x40e000) == 0x000000) return (0x7e0000 + (addr & 0x1fff));
|
||||
return addr;
|
||||
}
|
||||
|
||||
//=========
|
||||
//CheatCode
|
||||
//=========
|
||||
|
||||
bool CheatCode::operator=(string s) {
|
||||
addr.reset();
|
||||
data.reset();
|
||||
|
||||
lstring list;
|
||||
list.split("+", s.replace(" ", ""));
|
||||
|
||||
for(unsigned i = 0; i < list.size(); i++) {
|
||||
unsigned addr_;
|
||||
uint8 data_;
|
||||
Cheat::Type type_;
|
||||
if(Cheat::decode(list[i], addr_, data_, type_) == false) {
|
||||
addr.reset();
|
||||
data.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
addr.add(addr_);
|
||||
data.add(data_);
|
||||
}
|
||||
cheat_enabled_code_exists = false;
|
||||
cheat_enabled = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//address lookup table manipulation and mirroring
|
||||
//mirror_address() 0x000000 -> 0x7e0000
|
||||
//set() enable specified address, mirror accordingly
|
||||
//clear() disable specified address, mirror accordingly
|
||||
unsigned Cheat::mirror_address(unsigned addr) const {
|
||||
if((addr & 0x40e000) != 0x0000) return addr;
|
||||
//8k WRAM mirror
|
||||
//$[00-3f|80-bf]:[0000-1fff] -> $7e:[0000-1fff]
|
||||
return (0x7e0000 + (addr & 0x1fff));
|
||||
CheatCode::CheatCode() {
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
//updates mask[] table enabled bits;
|
||||
//must be called after modifying item.enabled state.
|
||||
void Cheat::update(const cheat_t &item) {
|
||||
for(unsigned n = 0; n < item.count; n++) {
|
||||
(item.enabled) ? set(item.addr[n]) : clear(item.addr[n]);
|
||||
}
|
||||
}
|
||||
|
||||
void Cheat::set(unsigned addr) {
|
||||
addr = mirror_address(addr);
|
||||
|
||||
mask[addr >> 3] |= 1 << (addr & 7);
|
||||
if((addr & 0xffe000) == 0x7e0000) {
|
||||
//mirror $7e:[0000-1fff] to $[00-3f|80-bf]:[0000-1fff]
|
||||
unsigned mirror;
|
||||
for(unsigned x = 0; x <= 0x3f; x++) {
|
||||
mirror = ((0x00 + x) << 16) + (addr & 0x1fff);
|
||||
mask[mirror >> 3] |= 1 << (mirror & 7);
|
||||
mirror = ((0x80 + x) << 16) + (addr & 0x1fff);
|
||||
mask[mirror >> 3] |= 1 << (mirror & 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cheat::clear(unsigned addr) {
|
||||
addr = mirror_address(addr);
|
||||
|
||||
//if there is more than one cheat code using the same address,
|
||||
//(eg with a different override value) then do not clear code
|
||||
//lookup table entry.
|
||||
uint8_t r;
|
||||
if(read(addr, r) == true) return;
|
||||
|
||||
mask[addr >> 3] &= ~(1 << (addr & 7));
|
||||
if((addr & 0xffe000) == 0x7e0000) {
|
||||
//mirror $7e:[0000-1fff] to $[00-3f|80-bf]:[0000-1fff]
|
||||
unsigned mirror;
|
||||
for(unsigned x = 0; x <= 0x3f; x++) {
|
||||
mirror = ((0x00 + x) << 16) + (addr & 0x1fff);
|
||||
mask[mirror >> 3] &= ~(1 << (mirror & 7));
|
||||
mirror = ((0x80 + x) << 16) + (addr & 0x1fff);
|
||||
mask[mirror >> 3] &= ~(1 << (mirror & 7));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//these two functions are used to safely store description text inside .cfg file format.
|
||||
|
||||
string& Cheat::encode_description(string &desc) const {
|
||||
desc.replace("\"", "\\q");
|
||||
desc.replace("\n", "\\n");
|
||||
return desc;
|
||||
}
|
||||
|
||||
string& Cheat::decode_description(string &desc) const {
|
||||
desc.replace("\\q", "\"");
|
||||
desc.replace("\\n", "\n");
|
||||
return desc;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
+24
-58
@@ -1,69 +1,35 @@
|
||||
class Cheat {
|
||||
struct CheatCode {
|
||||
bool enabled;
|
||||
array<unsigned> addr;
|
||||
array<uint8> data;
|
||||
|
||||
bool operator=(string);
|
||||
CheatCode();
|
||||
};
|
||||
|
||||
class Cheat : public vector<CheatCode> {
|
||||
public:
|
||||
enum type_t {
|
||||
ProActionReplay,
|
||||
GameGenie,
|
||||
};
|
||||
|
||||
struct cheat_t {
|
||||
bool enabled;
|
||||
string code;
|
||||
string desc;
|
||||
|
||||
unsigned count;
|
||||
array<unsigned> addr;
|
||||
array<uint8_t> data;
|
||||
|
||||
cheat_t& operator=(const cheat_t&);
|
||||
bool operator<(const cheat_t&);
|
||||
};
|
||||
|
||||
bool decode(const char *s, cheat_t &item) const;
|
||||
bool read(unsigned addr, uint8_t &data) const;
|
||||
enum Type { ProActionReplay, GameGenie };
|
||||
|
||||
bool enabled() const;
|
||||
void enable();
|
||||
void disable();
|
||||
void enable(bool);
|
||||
void synchronize();
|
||||
bool read(unsigned, uint8&) const;
|
||||
|
||||
inline unsigned count() const { return code.size(); }
|
||||
inline bool active() const { return cheat_enabled; }
|
||||
inline bool exists(unsigned addr) const { return mask[addr >> 3] & 1 << (addr & 7); }
|
||||
|
||||
bool add(bool enable, const char *code, const char *desc);
|
||||
bool edit(unsigned i, bool enable, const char *code, const char *desc);
|
||||
bool remove(unsigned i);
|
||||
bool get(unsigned i, cheat_t &item) const;
|
||||
|
||||
bool enabled(unsigned i) const;
|
||||
void enable(unsigned i);
|
||||
void disable(unsigned i);
|
||||
|
||||
void load(string data);
|
||||
string save() const;
|
||||
void clear();
|
||||
inline bool active() const;
|
||||
inline bool exists(unsigned addr) const;
|
||||
|
||||
Cheat();
|
||||
|
||||
static bool decode(const char*, unsigned&, uint8&, Type&);
|
||||
static bool encode(string&, unsigned, uint8, Type);
|
||||
|
||||
private:
|
||||
bool cheat_enabled; //cheat_enabled == (cheat_enabled_code_exists && cheat_system_enabled);
|
||||
bool cheat_enabled_code_exists;
|
||||
bool cheat_system_enabled;
|
||||
|
||||
uint8_t mask[0x200000];
|
||||
vector<cheat_t> code;
|
||||
|
||||
bool decode(const char *str, unsigned &addr, uint8_t &data, type_t &type) const;
|
||||
bool encode(string &str, unsigned addr, uint8_t data, type_t type) const;
|
||||
|
||||
void update_cheat_status();
|
||||
unsigned mirror_address(unsigned addr) const;
|
||||
|
||||
void update(const cheat_t& item);
|
||||
void set(unsigned addr);
|
||||
void clear(unsigned addr);
|
||||
|
||||
string& encode_description(string &desc) const;
|
||||
string& decode_description(string &desc) const;
|
||||
uint8 bitmask[0x200000];
|
||||
bool system_enabled;
|
||||
bool code_enabled;
|
||||
bool cheat_enabled;
|
||||
unsigned mirror(unsigned) const;
|
||||
};
|
||||
|
||||
extern Cheat cheat;
|
||||
@@ -0,0 +1,195 @@
|
||||
#include <../base.hpp>
|
||||
|
||||
//B-bus interface
|
||||
|
||||
//$21f0 command port (r/w)
|
||||
//-------------------------
|
||||
//$00 set data port address (sr[3-0] = address)
|
||||
//$01 set audio track number (sr[1-0] = track number)
|
||||
//$02 set volume (sr[1] = left, sr[0] = right)
|
||||
//$03 set audio state (sr[0].d1 = pause, sr[0].d0 = repeat)
|
||||
//
|
||||
//d7 = data port busy
|
||||
//d6 = audio port busy
|
||||
//d5 = audio playing
|
||||
//d4 = reserved (0)
|
||||
//d3-d0 = version (0)
|
||||
//
|
||||
//
|
||||
//$21f1 parameter port (w)
|
||||
//-------------------------
|
||||
//(shift register)
|
||||
//
|
||||
//
|
||||
//$21f2 data port (r)
|
||||
//--------------------
|
||||
//(auto-increment read port)
|
||||
|
||||
//A-bus interface
|
||||
|
||||
//$2200 command port (r/w)
|
||||
//-------------------------
|
||||
//$00 set data port address (sr[3-0] = address)
|
||||
//$01 set audio track number (sr[1-0] = track number)
|
||||
//$02 set volume (sr[1] = left, sr[0] = right)
|
||||
//$03 set audio state (sr[0].d1 = pause, sr[0].d0 = repeat)
|
||||
//
|
||||
//d7 = data port busy
|
||||
//d6 = audio port busy
|
||||
//d5 = audio playing
|
||||
//d4 = reserved (0)
|
||||
//d3-d0 = version (0)
|
||||
//
|
||||
//$2201 data port (r/w)
|
||||
//----------------------
|
||||
//(shift register)
|
||||
//
|
||||
//(auto-increment read port)
|
||||
|
||||
#define S21FX_CPP
|
||||
namespace SNES {
|
||||
|
||||
S21fx s21fx;
|
||||
|
||||
#include "serialization.cpp"
|
||||
|
||||
void S21fx::enter() {
|
||||
scheduler.clock.cop_freq = 44100;
|
||||
|
||||
while(true) {
|
||||
if(scheduler.sync == Scheduler::SyncAll) {
|
||||
scheduler.exit(Scheduler::SynchronizeEvent);
|
||||
}
|
||||
|
||||
int16 left = 0, right = 0;
|
||||
|
||||
if((mmio.status & AudioPlaying) && !mmio.audio_pause) {
|
||||
if(audiofile.open()) {
|
||||
if(audiofile.end()) {
|
||||
if(!mmio.audio_repeat) mmio.status &= ~AudioPlaying;
|
||||
audiofile.seek(mmio.audio_offset = 58);
|
||||
} else {
|
||||
mmio.audio_offset += 4;
|
||||
left = audiofile.readl(2);
|
||||
right = audiofile.readl(2);
|
||||
}
|
||||
} else {
|
||||
mmio.status &= ~AudioPlaying;
|
||||
}
|
||||
}
|
||||
|
||||
left = sclamp<16>((double)left * (double)mmio.audio_volume_left / 255.0);
|
||||
right = sclamp<16>((double)right * (double)mmio.audio_volume_right / 255.0);
|
||||
|
||||
audio.coprocessor_sample(left, right);
|
||||
scheduler.addclocks_cop(1);
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
}
|
||||
|
||||
void S21fx::init() {
|
||||
}
|
||||
|
||||
void S21fx::enable() {
|
||||
audio.coprocessor_enable(true);
|
||||
audio.coprocessor_frequency(44100.0);
|
||||
|
||||
for(unsigned i = 0x21f0; i <= 0x21f7; i++) {
|
||||
memory::mmio.map(i, *this);
|
||||
}
|
||||
|
||||
memory::mmio.map(0x2200, *this);
|
||||
memory::mmio.map(0x2201, *this);
|
||||
|
||||
if(datafile.open()) datafile.close();
|
||||
datafile.open(string() << basepath << "21fx.bin", file::mode_read);
|
||||
}
|
||||
|
||||
void S21fx::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void S21fx::reset() {
|
||||
mmio.status = DataPortBusy | AudioBusy;
|
||||
mmio.shift_register = 0;
|
||||
|
||||
mmio.data_offset = 0;
|
||||
mmio.audio_offset = 0;
|
||||
mmio.audio_track = 0;
|
||||
mmio.audio_volume_left = 255;
|
||||
mmio.audio_volume_right = 255;
|
||||
mmio.audio_repeat = false;
|
||||
mmio.audio_pause = false;
|
||||
}
|
||||
|
||||
uint8 S21fx::mmio_read(unsigned addr) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if((addr == 0x21f0) || (addr == 0x2200)) {
|
||||
return mmio.status | 0x00;
|
||||
}
|
||||
|
||||
if((addr == 0x21f2) || (addr == 0x2201)) {
|
||||
if(mmio.status & DataPortBusy) return 0x00;
|
||||
mmio.data_offset++;
|
||||
if(datafile.open()) return datafile.read();
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void S21fx::mmio_write(unsigned addr, uint8 data) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if((addr == 0x21f0) || (addr == 0x2200)) {
|
||||
if(data == 0x00) {
|
||||
mmio.data_offset = mmio.shift_register & 0xffffffff;
|
||||
if(datafile.open()) {
|
||||
datafile.seek(mmio.data_offset);
|
||||
}
|
||||
mmio.status &= ~DataPortBusy;
|
||||
}
|
||||
|
||||
if(data == 0x01) {
|
||||
mmio.audio_track = mmio.shift_register & 0xffff;
|
||||
if(audiofile.open()) audiofile.close();
|
||||
char track[16];
|
||||
sprintf(track, "%.5u", mmio.audio_track);
|
||||
if(audiofile.open(string() << basepath << "audio" << track << ".wav", file::mode_read)) {
|
||||
audiofile.seek(mmio.audio_offset = 58); //skip WAV header
|
||||
}
|
||||
mmio.status &= ~(AudioBusy | AudioPlaying);
|
||||
}
|
||||
|
||||
if(data == 0x02) {
|
||||
mmio.audio_volume_left = mmio.shift_register >> 8;
|
||||
mmio.audio_volume_right = mmio.shift_register >> 0;
|
||||
}
|
||||
|
||||
if(data == 0x03) {
|
||||
mmio.status |= AudioPlaying;
|
||||
mmio.audio_repeat = mmio.shift_register & 1;
|
||||
mmio.audio_pause = mmio.shift_register & 2;
|
||||
}
|
||||
|
||||
mmio.shift_register = 0;
|
||||
}
|
||||
|
||||
if((addr == 0x21f1) || (addr == 0x2201)) {
|
||||
mmio.shift_register = (mmio.shift_register << 8) | data;
|
||||
}
|
||||
}
|
||||
|
||||
void S21fx::base(const string& path) {
|
||||
basepath = path;
|
||||
}
|
||||
|
||||
bool S21fx::exists() {
|
||||
return file::exists(string() << basepath << "21fx.bin");
|
||||
}
|
||||
|
||||
S21fx::S21fx() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
class S21fx : public MMIO {
|
||||
public:
|
||||
void enter();
|
||||
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
|
||||
void base(const string &path);
|
||||
bool exists();
|
||||
|
||||
void serialize(serializer&);
|
||||
S21fx();
|
||||
|
||||
private:
|
||||
string basepath;
|
||||
file datafile;
|
||||
file audiofile;
|
||||
|
||||
enum Flag {
|
||||
DataPortBusy = 0x80,
|
||||
AudioBusy = 0x40,
|
||||
AudioPlaying = 0x20,
|
||||
};
|
||||
|
||||
struct MMIO {
|
||||
uint8 status;
|
||||
uint64 shift_register;
|
||||
|
||||
uint32 data_offset;
|
||||
uint32 audio_offset;
|
||||
uint16 audio_track;
|
||||
uint8 audio_volume_left;
|
||||
uint8 audio_volume_right;
|
||||
bool audio_repeat;
|
||||
bool audio_pause;
|
||||
} mmio;
|
||||
};
|
||||
|
||||
extern S21fx s21fx;
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifdef S21FX_CPP
|
||||
|
||||
void S21fx::serialize(serializer &s) {
|
||||
s.integer(mmio.status);
|
||||
s.integer(mmio.shift_register);
|
||||
|
||||
s.integer(mmio.data_offset);
|
||||
s.integer(mmio.audio_offset);
|
||||
s.integer(mmio.audio_track);
|
||||
s.integer(mmio.audio_volume_left);
|
||||
s.integer(mmio.audio_volume_right);
|
||||
s.integer(mmio.audio_repeat);
|
||||
s.integer(mmio.audio_pause);
|
||||
|
||||
//flush file handles and indices, as a different track may be playing,
|
||||
//or the file offsets may be at the wrong location ...
|
||||
|
||||
if(datafile.open()) datafile.close();
|
||||
if(datafile.open(string() << basepath << "21fx.bin", file::mode_read)) {
|
||||
datafile.seek(mmio.data_offset);
|
||||
}
|
||||
|
||||
if(audiofile.open()) audiofile.close();
|
||||
char track[16];
|
||||
sprintf(track, "%.5u", mmio.audio_track);
|
||||
if(audiofile.open(string() << basepath << "audio" << track << ".wav", file::mode_read)) {
|
||||
audiofile.seek(mmio.audio_offset);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
+4
-1
@@ -1,4 +1,4 @@
|
||||
#include "sgb/sgb.hpp"
|
||||
#include "supergameboy/supergameboy.hpp"
|
||||
#include "superfx/superfx.hpp"
|
||||
#include "sa1/sa1.hpp"
|
||||
#include "bsx/bsx.hpp"
|
||||
@@ -12,3 +12,6 @@
|
||||
#include "dsp4/dsp4.hpp"
|
||||
#include "obc1/obc1.hpp"
|
||||
#include "st010/st010.hpp"
|
||||
#include "st011/st011.hpp"
|
||||
#include "st018/st018.hpp"
|
||||
#include "21fx/21fx.hpp"
|
||||
+38
-30
@@ -1,9 +1,8 @@
|
||||
/*
|
||||
C4 emulation
|
||||
|
||||
Used in Rockman X2/X3 (Megaman X2/X3)
|
||||
Portions (c) anomie, Overload, zsKnight, Nach, byuu
|
||||
*/
|
||||
//=============
|
||||
//Cx4 emulation
|
||||
//=============
|
||||
//Used in Rockman X2/X3 (Megaman X2/X3)
|
||||
//Portions (c) anomie, Overload, zsKnight, Nach, byuu
|
||||
|
||||
#include <../base.hpp>
|
||||
|
||||
@@ -12,29 +11,37 @@ namespace SNES {
|
||||
|
||||
Cx4 cx4;
|
||||
|
||||
#include "cx4data.cpp"
|
||||
#include "cx4fn.cpp"
|
||||
#include "cx4oam.cpp"
|
||||
#include "cx4ops.cpp"
|
||||
#include "serialization.cpp"
|
||||
#include "data.cpp"
|
||||
#include "functions.cpp"
|
||||
#include "oam.cpp"
|
||||
#include "opcodes.cpp"
|
||||
|
||||
void Cx4::init() {}
|
||||
void Cx4::enable() {}
|
||||
void Cx4::init() {
|
||||
}
|
||||
|
||||
void Cx4::enable() {
|
||||
bus.map(Bus::MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, *this);
|
||||
bus.map(Bus::MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, *this);
|
||||
}
|
||||
|
||||
uint32 Cx4::ldr(uint8 r) {
|
||||
uint16 addr = 0x0080 + (r * 3);
|
||||
return (reg[addr]) | (reg[addr + 1] << 8) | (reg[addr + 2] << 16);
|
||||
uint16 addr = 0x0080 + (r * 3);
|
||||
return (reg[addr + 0] << 0)
|
||||
| (reg[addr + 1] << 8)
|
||||
| (reg[addr + 2] << 16);
|
||||
}
|
||||
|
||||
void Cx4::str(uint8 r, uint32 data) {
|
||||
uint16 addr = 0x0080 + (r * 3);
|
||||
reg[addr ] = (data);
|
||||
reg[addr + 1] = (data >> 8);
|
||||
uint16 addr = 0x0080 + (r * 3);
|
||||
reg[addr + 0] = (data >> 0);
|
||||
reg[addr + 1] = (data >> 8);
|
||||
reg[addr + 2] = (data >> 16);
|
||||
}
|
||||
|
||||
void Cx4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) {
|
||||
int64_t rx = x & 0xffffff;
|
||||
int64_t ry = y & 0xffffff;
|
||||
int64 rx = x & 0xffffff;
|
||||
int64 ry = y & 0xffffff;
|
||||
if(rx & 0x800000)rx |= ~0x7fffff;
|
||||
if(ry & 0x800000)ry |= ~0x7fffff;
|
||||
|
||||
@@ -71,8 +78,9 @@ void Cx4::immediate_reg(uint32 start) {
|
||||
}
|
||||
|
||||
void Cx4::transfer_data() {
|
||||
uint32 src;
|
||||
uint16 dest, count;
|
||||
uint32 src;
|
||||
uint16 dest, count;
|
||||
|
||||
src = (reg[0x40]) | (reg[0x41] << 8) | (reg[0x42] << 16);
|
||||
count = (reg[0x43]) | (reg[0x44] << 8);
|
||||
dest = (reg[0x45]) | (reg[0x46] << 8);
|
||||
@@ -86,29 +94,29 @@ void Cx4::write(unsigned addr, uint8 data) {
|
||||
addr &= 0x1fff;
|
||||
|
||||
if(addr < 0x0c00) {
|
||||
//ram
|
||||
//ram
|
||||
ram[addr] = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr < 0x1f00) {
|
||||
//unmapped
|
||||
//unmapped
|
||||
return;
|
||||
}
|
||||
|
||||
//command register
|
||||
//command register
|
||||
reg[addr & 0xff] = data;
|
||||
|
||||
if(addr == 0x1f47) {
|
||||
//memory transfer
|
||||
//memory transfer
|
||||
transfer_data();
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x1f4f) {
|
||||
//c4 command
|
||||
//c4 command
|
||||
if(reg[0x4d] == 0x0e && !(data & 0xc3)) {
|
||||
//c4 test command
|
||||
//c4 test command
|
||||
reg[0x80] = data >> 2;
|
||||
return;
|
||||
}
|
||||
@@ -154,12 +162,12 @@ void Cx4::writeb(uint16 addr, uint8 data) {
|
||||
}
|
||||
|
||||
void Cx4::writew(uint16 addr, uint16 data) {
|
||||
write(addr, data);
|
||||
write(addr + 0, data >> 0);
|
||||
write(addr + 1, data >> 8);
|
||||
}
|
||||
|
||||
void Cx4::writel(uint16 addr, uint32 data) {
|
||||
write(addr, data);
|
||||
write(addr + 0, data >> 0);
|
||||
write(addr + 1, data >> 8);
|
||||
write(addr + 2, data >> 16);
|
||||
}
|
||||
@@ -198,5 +206,5 @@ void Cx4::reset() {
|
||||
memset(ram, 0, 0x0c00);
|
||||
memset(reg, 0, 0x0100);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
+11
-13
@@ -1,4 +1,15 @@
|
||||
class Cx4 : public Memory {
|
||||
public:
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
void serialize(serializer&);
|
||||
|
||||
private:
|
||||
uint8 ram[0x0c00];
|
||||
uint8 reg[0x0100];
|
||||
@@ -15,9 +26,6 @@ private:
|
||||
int16 C4WFXVal, C4WFYVal, C4WFZVal, C4WFX2Val, C4WFY2Val, C4WFDist, C4WFScale;
|
||||
int16 C41FXVal, C41FYVal, C41FAngleRes, C41FDist, C41FDistVal;
|
||||
|
||||
double tanval;
|
||||
double c4x,c4y,c4z, c4x2,c4y2,c4z2;
|
||||
|
||||
void C4TransfWireFrame();
|
||||
void C4TransfWireFrame2();
|
||||
void C4CalcWireFrame();
|
||||
@@ -82,16 +90,6 @@ public:
|
||||
void writeb(uint16 addr, uint8 data);
|
||||
void writew(uint16 addr, uint16 data);
|
||||
void writel(uint16 addr, uint32 data);
|
||||
|
||||
//
|
||||
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 read (unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
};
|
||||
|
||||
extern Cx4 cx4;
|
||||
File renamed without changes.
@@ -10,26 +10,27 @@
|
||||
|
||||
//Wireframe Helpers
|
||||
void Cx4::C4TransfWireFrame() {
|
||||
c4x = (double)C4WFXVal;
|
||||
c4y = (double)C4WFYVal;
|
||||
c4z = (double)C4WFZVal - 0x95;
|
||||
double c4x = (double)C4WFXVal;
|
||||
double c4y = (double)C4WFYVal;
|
||||
double c4z = (double)C4WFZVal - 0x95;
|
||||
double tanval, c4x2, c4y2, c4z2;
|
||||
|
||||
//Rotate X
|
||||
//Rotate X
|
||||
tanval = -(double)C4WFX2Val * PI * 2 / 128;
|
||||
c4y2 = c4y * ::cos(tanval) - c4z * ::sin(tanval);
|
||||
c4z2 = c4y * ::sin(tanval) + c4z * ::cos(tanval);
|
||||
|
||||
//Rotate Y
|
||||
//Rotate Y
|
||||
tanval = -(double)C4WFY2Val * PI * 2 / 128;
|
||||
c4x2 = c4x * ::cos(tanval) + c4z2 * ::sin(tanval);
|
||||
c4z = c4x * -::sin(tanval) + c4z2 * ::cos(tanval);
|
||||
|
||||
//Rotate Z
|
||||
//Rotate Z
|
||||
tanval = -(double)C4WFDist * PI * 2 / 128;
|
||||
c4x = c4x2 * ::cos(tanval) - c4y2 * ::sin(tanval);
|
||||
c4y = c4x2 * ::sin(tanval) + c4y2 * ::cos(tanval);
|
||||
|
||||
//Scale
|
||||
//Scale
|
||||
C4WFXVal = (int16)(c4x * C4WFScale / (0x90 * (c4z + 0x95)) * 0x95);
|
||||
C4WFYVal = (int16)(c4y * C4WFScale / (0x90 * (c4z + 0x95)) * 0x95);
|
||||
}
|
||||
@@ -52,39 +53,41 @@ void Cx4::C4CalcWireFrame() {
|
||||
}
|
||||
|
||||
void Cx4::C4TransfWireFrame2() {
|
||||
c4x = (double)C4WFXVal;
|
||||
c4y = (double)C4WFYVal;
|
||||
c4z = (double)C4WFZVal;
|
||||
double c4x = (double)C4WFXVal;
|
||||
double c4y = (double)C4WFYVal;
|
||||
double c4z = (double)C4WFZVal;
|
||||
double tanval, c4x2, c4y2, c4z2;
|
||||
|
||||
//Rotate X
|
||||
//Rotate X
|
||||
tanval = -(double)C4WFX2Val * PI * 2 / 128;
|
||||
c4y2 = c4y * ::cos(tanval) - c4z * ::sin(tanval);
|
||||
c4z2 = c4y * ::sin(tanval) + c4z * ::cos(tanval);
|
||||
|
||||
//Rotate Y
|
||||
//Rotate Y
|
||||
tanval = -(double)C4WFY2Val * PI * 2 / 128;
|
||||
c4x2 = c4x * ::cos(tanval) + c4z2 * ::sin(tanval);
|
||||
c4z = c4x * -::sin(tanval) + c4z2 * ::cos(tanval);
|
||||
|
||||
//Rotate Z
|
||||
//Rotate Z
|
||||
tanval = -(double)C4WFDist * PI * 2 / 128;
|
||||
c4x = c4x2 * ::cos(tanval) - c4y2 * ::sin(tanval);
|
||||
c4y = c4x2 * ::sin(tanval) + c4y2 * ::cos(tanval);
|
||||
|
||||
//Scale
|
||||
//Scale
|
||||
C4WFXVal = (int16)(c4x * C4WFScale / 0x100);
|
||||
C4WFYVal = (int16)(c4y * C4WFScale / 0x100);
|
||||
}
|
||||
|
||||
void Cx4::C4DrawWireFrame() {
|
||||
uint32 line = readl(0x1f80);
|
||||
uint32 point1, point2;
|
||||
int16 X1, Y1, Z1;
|
||||
int16 X2, Y2, Z2;
|
||||
uint8 Color;
|
||||
uint32 line = readl(0x1f80);
|
||||
uint32 point1, point2;
|
||||
int16 X1, Y1, Z1;
|
||||
int16 X2, Y2, Z2;
|
||||
uint8 Color;
|
||||
|
||||
for(int32 i = ram[0x0295]; i > 0; i--, line += 5) {
|
||||
if(bus.read(line) == 0xff && bus.read(line + 1) == 0xff) {
|
||||
int32 tmp = line - 5;
|
||||
int32 tmp = line - 5;
|
||||
while(bus.read(tmp + 2) == 0xff && bus.read(tmp + 3) == 0xff && (tmp + 2) >= 0) { tmp -= 5; }
|
||||
point1 = (read(0x1f82) << 16) | (bus.read(tmp + 2) << 8) | bus.read(tmp + 3);
|
||||
} else {
|
||||
@@ -104,7 +107,7 @@ uint8 Color;
|
||||
}
|
||||
|
||||
void Cx4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color) {
|
||||
//Transform coordinates
|
||||
//Transform coordinates
|
||||
C4WFXVal = (int16)X1;
|
||||
C4WFYVal = (int16)Y1;
|
||||
C4WFZVal = Z1;
|
||||
@@ -123,7 +126,7 @@ void Cx4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2,
|
||||
X2 = (C4WFXVal + 48) << 8;
|
||||
Y2 = (C4WFYVal + 48) << 8;
|
||||
|
||||
//Get line info
|
||||
//Get line info
|
||||
C4WFXVal = (int16)(X1 >> 8);
|
||||
C4WFYVal = (int16)(Y1 >> 8);
|
||||
C4WFX2Val = (int16)(X2 >> 8);
|
||||
@@ -132,15 +135,15 @@ void Cx4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2,
|
||||
X2 = (int16)C4WFXVal;
|
||||
Y2 = (int16)C4WFYVal;
|
||||
|
||||
//Render line
|
||||
//Render line
|
||||
for(int32 i = C4WFDist ? C4WFDist : 1; i > 0; i--) {
|
||||
if(X1 > 0xff && Y1 > 0xff && X1 < 0x6000 && Y1 < 0x6000) {
|
||||
uint16 addr = (((Y1 >> 8) >> 3) << 8) - (((Y1 >> 8) >> 3) << 6) + (((X1 >> 8) >> 3) << 4) + ((Y1 >> 8) & 7) * 2;
|
||||
uint8 bit = 0x80 >> ((X1 >> 8) & 7);
|
||||
uint16 addr = (((Y1 >> 8) >> 3) << 8) - (((Y1 >> 8) >> 3) << 6) + (((X1 >> 8) >> 3) << 4) + ((Y1 >> 8) & 7) * 2;
|
||||
uint8 bit = 0x80 >> ((X1 >> 8) & 7);
|
||||
ram[addr + 0x300] &= ~bit;
|
||||
ram[addr + 0x301] &= ~bit;
|
||||
if(Color & 1) { ram[addr + 0x300] |= bit; }
|
||||
if(Color & 2) { ram[addr + 0x301] |= bit; }
|
||||
if(Color & 1) ram[addr + 0x300] |= bit;
|
||||
if(Color & 2) ram[addr + 0x301] |= bit;
|
||||
}
|
||||
X1 += X2;
|
||||
Y1 += Y2;
|
||||
@@ -148,30 +151,31 @@ void Cx4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2,
|
||||
}
|
||||
|
||||
void Cx4::C4DoScaleRotate(int row_padding) {
|
||||
int16 A, B, C, D;
|
||||
int16 A, B, C, D;
|
||||
|
||||
//Calculate matrix
|
||||
int32 XScale = readw(0x1f8f);
|
||||
int32 YScale = readw(0x1f92);
|
||||
|
||||
//Calculate matrix
|
||||
int32 XScale = readw(0x1f8f);
|
||||
int32 YScale = readw(0x1f92);
|
||||
if(XScale & 0x8000)XScale = 0x7fff;
|
||||
if(YScale & 0x8000)YScale = 0x7fff;
|
||||
|
||||
if(readw(0x1f80) == 0) { //no rotation
|
||||
if(readw(0x1f80) == 0) { //no rotation
|
||||
A = (int16)XScale;
|
||||
B = 0;
|
||||
C = 0;
|
||||
D = (int16)YScale;
|
||||
} else if(readw(0x1f80) == 128) { //90 degree rotation
|
||||
} else if(readw(0x1f80) == 128) { //90 degree rotation
|
||||
A = 0;
|
||||
B = (int16)(-YScale);
|
||||
C = (int16)XScale;
|
||||
D = 0;
|
||||
} else if(readw(0x1f80) == 256) { //180 degree rotation
|
||||
} else if(readw(0x1f80) == 256) { //180 degree rotation
|
||||
A = (int16)(-XScale);
|
||||
B = 0;
|
||||
C = 0;
|
||||
D = (int16)(-YScale);
|
||||
} else if(readw(0x1f80) == 384) { //270 degree rotation
|
||||
} else if(readw(0x1f80) == 384) { //270 degree rotation
|
||||
A = 0;
|
||||
B = (int16)YScale;
|
||||
C = (int16)(-XScale);
|
||||
@@ -183,28 +187,29 @@ int32 YScale = readw(0x1f92);
|
||||
D = (int16) sar(CosTable[readw(0x1f80) & 0x1ff] * YScale, 15);
|
||||
}
|
||||
|
||||
//Calculate Pixel Resolution
|
||||
uint8 w = read(0x1f89) & ~7;
|
||||
uint8 h = read(0x1f8c) & ~7;
|
||||
//Calculate Pixel Resolution
|
||||
uint8 w = read(0x1f89) & ~7;
|
||||
uint8 h = read(0x1f8c) & ~7;
|
||||
|
||||
//Clear the output RAM
|
||||
//Clear the output RAM
|
||||
memset(ram, 0, (w + row_padding / 4) * h / 2);
|
||||
|
||||
int32 Cx = (int16)readw(0x1f83);
|
||||
int32 Cy = (int16)readw(0x1f86);
|
||||
int32 Cx = (int16)readw(0x1f83);
|
||||
int32 Cy = (int16)readw(0x1f86);
|
||||
|
||||
//Calculate start position (i.e. (Ox, Oy) = (0, 0))
|
||||
//The low 12 bits are fractional, so (Cx<<12) gives us the Cx we want in
|
||||
//the function. We do Cx*A etc normally because the matrix parameters
|
||||
//already have the fractional parts.
|
||||
int32 LineX = (Cx << 12) - Cx * A - Cx * B;
|
||||
int32 LineY = (Cy << 12) - Cy * C - Cy * D;
|
||||
//Calculate start position (i.e. (Ox, Oy) = (0, 0))
|
||||
//The low 12 bits are fractional, so (Cx<<12) gives us the Cx we want in
|
||||
//the function. We do Cx*A etc normally because the matrix parameters
|
||||
//already have the fractional parts.
|
||||
int32 LineX = (Cx << 12) - Cx * A - Cx * B;
|
||||
int32 LineY = (Cy << 12) - Cy * C - Cy * D;
|
||||
|
||||
//Start loop
|
||||
uint32 X, Y;
|
||||
uint8 byte;
|
||||
int32 outidx = 0;
|
||||
uint8 bit = 0x80;
|
||||
|
||||
//Start loop
|
||||
uint32 X, Y;
|
||||
uint8 byte;
|
||||
int32 outidx = 0;
|
||||
uint8 bit = 0x80;
|
||||
for(int32 y = 0; y < h; y++) {
|
||||
X = LineX;
|
||||
Y = LineY;
|
||||
@@ -212,16 +217,16 @@ uint8 bit = 0x80;
|
||||
if((X >> 12) >= w || (Y >> 12) >= h) {
|
||||
byte = 0;
|
||||
} else {
|
||||
uint32 addr = (Y >> 12) * w + (X >> 12);
|
||||
uint32 addr = (Y >> 12) * w + (X >> 12);
|
||||
byte = read(0x600 + (addr >> 1));
|
||||
if(addr & 1) { byte >>= 4; }
|
||||
}
|
||||
|
||||
//De-bitplanify
|
||||
if(byte & 1) { ram[outidx ] |= bit; }
|
||||
if(byte & 2) { ram[outidx + 1] |= bit; }
|
||||
if(byte & 4) { ram[outidx + 16] |= bit; }
|
||||
if(byte & 8) { ram[outidx + 17] |= bit; }
|
||||
//De-bitplanify
|
||||
if(byte & 1) ram[outidx ] |= bit;
|
||||
if(byte & 2) ram[outidx + 1] |= bit;
|
||||
if(byte & 4) ram[outidx + 16] |= bit;
|
||||
if(byte & 8) ram[outidx + 17] |= bit;
|
||||
|
||||
bit >>= 1;
|
||||
if(!bit) {
|
||||
@@ -229,7 +234,7 @@ uint8 bit = 0x80;
|
||||
outidx += 32;
|
||||
}
|
||||
|
||||
X += A; //Add 1 to output x => add an A and a C
|
||||
X += A; //Add 1 to output x => add an A and a C
|
||||
Y += C;
|
||||
}
|
||||
outidx += 2 + row_padding;
|
||||
@@ -238,7 +243,7 @@ uint8 bit = 0x80;
|
||||
} else {
|
||||
outidx -= w * 4 + row_padding;
|
||||
}
|
||||
LineX += B; //Add 1 to output y => add a B and a D
|
||||
LineX += B; //Add 1 to output y => add a B and a D
|
||||
LineY += D;
|
||||
}
|
||||
}
|
||||
@@ -2,35 +2,37 @@
|
||||
|
||||
//Build OAM
|
||||
void Cx4::op00_00() {
|
||||
uint32 oamptr = ram[0x626] << 2;
|
||||
uint32 oamptr = ram[0x626] << 2;
|
||||
for(int32 i = 0x1fd; i > oamptr && i >= 0; i -= 4) {
|
||||
//clear oam-to-be
|
||||
if(i >= 0)ram[i] = 0xe0;
|
||||
//clear oam-to-be
|
||||
if(i >= 0) ram[i] = 0xe0;
|
||||
}
|
||||
|
||||
uint16 globalx, globaly;
|
||||
uint32 oamptr2;
|
||||
int16 sprx, spry;
|
||||
uint8 sprname, sprattr;
|
||||
uint8 sprcount;
|
||||
uint16 globalx, globaly;
|
||||
uint32 oamptr2;
|
||||
int16 sprx, spry;
|
||||
uint8 sprname, sprattr;
|
||||
uint8 sprcount;
|
||||
|
||||
globalx = readw(0x621);
|
||||
globaly = readw(0x623);
|
||||
oamptr2 = 0x200 + (ram[0x626] >> 2);
|
||||
|
||||
if(!ram[0x620])return;
|
||||
if(!ram[0x620]) return;
|
||||
|
||||
sprcount = 128 - ram[0x626];
|
||||
uint8 offset = (ram[0x626] & 3) * 2;
|
||||
uint32 srcptr = 0x220;
|
||||
uint8 offset = (ram[0x626] & 3) * 2;
|
||||
uint32 srcptr = 0x220;
|
||||
|
||||
for(int i = ram[0x620]; i > 0 && sprcount > 0; i--, srcptr += 16) {
|
||||
sprx = readw(srcptr) - globalx;
|
||||
spry = readw(srcptr + 2) - globaly;
|
||||
sprname = ram[srcptr + 5];
|
||||
sprattr = ram[srcptr + 4] | ram[srcptr + 6];
|
||||
|
||||
uint32 spraddr = readl(srcptr + 7);
|
||||
uint32 spraddr = readl(srcptr + 7);
|
||||
if(bus.read(spraddr)) {
|
||||
int16 x, y;
|
||||
int16 x, y;
|
||||
for(int sprcnt = bus.read(spraddr++); sprcnt > 0 && sprcount > 0; sprcnt--, spraddr += 4) {
|
||||
x = (int8)bus.read(spraddr + 1);
|
||||
if(sprattr & 0x40) {
|
||||
@@ -49,8 +51,8 @@ uint32 srcptr = 0x220;
|
||||
ram[oamptr + 2] = sprname + bus.read(spraddr + 3);
|
||||
ram[oamptr + 3] = sprattr ^ (bus.read(spraddr) & 0xc0);
|
||||
ram[oamptr2] &= ~(3 << offset);
|
||||
if(x & 0x100)ram[oamptr2] |= 1 << offset;
|
||||
if(bus.read(spraddr) & 0x20)ram[oamptr2] |= 2 << offset;
|
||||
if(x & 0x100) ram[oamptr2] |= 1 << offset;
|
||||
if(bus.read(spraddr) & 0x20) ram[oamptr2] |= 2 << offset;
|
||||
oamptr += 4;
|
||||
sprcount--;
|
||||
offset = (offset + 2) & 6;
|
||||
@@ -64,12 +66,12 @@ uint32 srcptr = 0x220;
|
||||
ram[oamptr + 2] = sprname;
|
||||
ram[oamptr + 3] = sprattr;
|
||||
ram[oamptr2] &= ~(3 << offset);
|
||||
if(sprx & 0x100)ram[oamptr2] |= 3 << offset;
|
||||
if(sprx & 0x100) ram[oamptr2] |= 3 << offset;
|
||||
else ram[oamptr2] |= 2 << offset;
|
||||
oamptr += 4;
|
||||
sprcount--;
|
||||
offset = (offset + 2) & 6;
|
||||
if(!offset)oamptr2++;
|
||||
if(!offset) oamptr2++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,7 +96,7 @@ uint32 ptr = 0;
|
||||
C4WFZVal = readw(ptr + 9);
|
||||
C4TransfWireFrame();
|
||||
|
||||
//Displace
|
||||
//Displace
|
||||
writew(ptr + 1, C4WFXVal + 0x80);
|
||||
writew(ptr + 5, C4WFYVal + 0x50);
|
||||
}
|
||||
@@ -107,7 +109,8 @@ uint32 ptr = 0;
|
||||
writew(0x605 + 8, 0x40);
|
||||
|
||||
ptr = 0xb02;
|
||||
uint32 ptr2 = 0;
|
||||
uint32 ptr2 = 0;
|
||||
|
||||
for(int32 i = readw(0xb00); i > 0; i--, ptr += 2, ptr2 += 8) {
|
||||
C4WFXVal = readw((read(ptr + 0) << 4) + 1);
|
||||
C4WFYVal = readw((read(ptr + 0) << 4) + 5);
|
||||
@@ -132,13 +135,14 @@ void Cx4::op00_08() {
|
||||
|
||||
//Disintegrate
|
||||
void Cx4::op00_0b() {
|
||||
uint8 width, height;
|
||||
uint32 startx, starty;
|
||||
uint32 srcptr;
|
||||
uint32 x, y;
|
||||
int32 scalex, scaley;
|
||||
int32 cx, cy;
|
||||
int32 i, j;
|
||||
uint8 width, height;
|
||||
uint32 startx, starty;
|
||||
uint32 srcptr;
|
||||
uint32 x, y;
|
||||
int32 scalex, scaley;
|
||||
int32 cx, cy;
|
||||
int32 i, j;
|
||||
|
||||
width = read(0x1f89);
|
||||
height = read(0x1f8c);
|
||||
cx = readw(0x1f80);
|
||||
@@ -157,31 +161,32 @@ int32 i, j;
|
||||
for(y = starty, i = 0;i < height; i++, y += scaley) {
|
||||
for(x = startx, j = 0;j < width; j++, x += scalex) {
|
||||
if((x >> 8) < width && (y >> 8) < height && (y >> 8) * width + (x >> 8) < 0x2000) {
|
||||
uint8 pixel = (j & 1) ? (ram[srcptr] >> 4) : (ram[srcptr]);
|
||||
int32 index = (y >> 11) * width * 4 + (x >> 11) * 32 + ((y >> 8) & 7) * 2;
|
||||
uint8 mask = 0x80 >> ((x >> 8) & 7);
|
||||
if(pixel & 1)ram[index ] |= mask;
|
||||
if(pixel & 2)ram[index + 1] |= mask;
|
||||
if(pixel & 4)ram[index + 16] |= mask;
|
||||
if(pixel & 8)ram[index + 17] |= mask;
|
||||
uint8 pixel = (j & 1) ? (ram[srcptr] >> 4) : (ram[srcptr]);
|
||||
int32 index = (y >> 11) * width * 4 + (x >> 11) * 32 + ((y >> 8) & 7) * 2;
|
||||
uint8 mask = 0x80 >> ((x >> 8) & 7);
|
||||
|
||||
if(pixel & 1) ram[index ] |= mask;
|
||||
if(pixel & 2) ram[index + 1] |= mask;
|
||||
if(pixel & 4) ram[index + 16] |= mask;
|
||||
if(pixel & 8) ram[index + 17] |= mask;
|
||||
}
|
||||
if(j & 1)srcptr++;
|
||||
if(j & 1) srcptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Bitplane Wave
|
||||
void Cx4::op00_0c() {
|
||||
uint32 destptr = 0;
|
||||
uint32 waveptr = read(0x1f83);
|
||||
uint16 mask1 = 0xc0c0;
|
||||
uint16 mask2 = 0x3f3f;
|
||||
uint32 destptr = 0;
|
||||
uint32 waveptr = read(0x1f83);
|
||||
uint16 mask1 = 0xc0c0;
|
||||
uint16 mask2 = 0x3f3f;
|
||||
|
||||
for(int j = 0; j < 0x10; j++) {
|
||||
do {
|
||||
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
|
||||
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
|
||||
for(int i = 0; i < 40; i++) {
|
||||
uint16 temp = readw(destptr + wave_data[i]) & mask2;
|
||||
uint16 temp = readw(destptr + wave_data[i]) & mask2;
|
||||
if(height >= 0) {
|
||||
if(height < 8) {
|
||||
temp |= mask1 & readw(0xa00 + height * 2);
|
||||
@@ -199,9 +204,9 @@ uint16 mask2 = 0x3f3f;
|
||||
destptr += 16;
|
||||
|
||||
do {
|
||||
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
|
||||
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
|
||||
for(int i = 0; i < 40; i++) {
|
||||
uint16 temp = readw(destptr + wave_data[i]) & mask2;
|
||||
uint16 temp = readw(destptr + wave_data[i]) & mask2;
|
||||
if(height >= 0) {
|
||||
if(height < 8) {
|
||||
temp |= mask1 & readw(0xa10 + height * 2);
|
||||
@@ -3,13 +3,13 @@
|
||||
//Sprite Functions
|
||||
void Cx4::op00() {
|
||||
switch(reg[0x4d]) {
|
||||
case 0x00:op00_00();break;
|
||||
case 0x03:op00_03();break;
|
||||
case 0x05:op00_05();break;
|
||||
case 0x07:op00_07();break;
|
||||
case 0x08:op00_08();break;
|
||||
case 0x0b:op00_0b();break;
|
||||
case 0x0c:op00_0c();break;
|
||||
case 0x00: op00_00(); break;
|
||||
case 0x03: op00_03(); break;
|
||||
case 0x05: op00_05(); break;
|
||||
case 0x07: op00_07(); break;
|
||||
case 0x08: op00_08(); break;
|
||||
case 0x0b: op00_0b(); break;
|
||||
case 0x0c: op00_0c(); break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ void Cx4::op01() {
|
||||
|
||||
//Propulsion
|
||||
void Cx4::op05() {
|
||||
int32 temp = 0x10000;
|
||||
int32 temp = 0x10000;
|
||||
if(readw(0x1f83)) {
|
||||
temp = sar((temp / readw(0x1f83)) * readw(0x1f81), 8);
|
||||
}
|
||||
@@ -33,7 +33,7 @@ void Cx4::op0d() {
|
||||
C41FXVal = readw(0x1f80);
|
||||
C41FYVal = readw(0x1f83);
|
||||
C41FDistVal = readw(0x1f86);
|
||||
tanval = sqrt(((double)C41FYVal) * ((double)C41FYVal) + ((double)C41FXVal) * ((double)C41FXVal));
|
||||
double tanval = sqrt(((double)C41FYVal) * ((double)C41FYVal) + ((double)C41FXVal) * ((double)C41FXVal));
|
||||
tanval = (double)C41FDistVal / tanval;
|
||||
C41FYVal = (int16)(((double)C41FYVal * tanval) * 0.99);
|
||||
C41FXVal = (int16)(((double)C41FXVal * tanval) * 0.98);
|
||||
@@ -103,7 +103,7 @@ void Cx4::op1f() {
|
||||
if(!C41FXVal) {
|
||||
C41FAngleRes = (C41FYVal > 0) ? 0x080 : 0x180;
|
||||
} else {
|
||||
tanval = ((double)C41FYVal) / ((double)C41FXVal);
|
||||
double tanval = ((double)C41FYVal) / ((double)C41FXVal);
|
||||
C41FAngleRes = (short)(atan(tanval) / (PI * 2) * 512);
|
||||
C41FAngleRes = C41FAngleRes;
|
||||
if(C41FXVal < 0) {
|
||||
@@ -116,12 +116,13 @@ void Cx4::op1f() {
|
||||
|
||||
//Trapezoid
|
||||
void Cx4::op22() {
|
||||
int16 angle1 = readw(0x1f8c) & 0x1ff;
|
||||
int16 angle2 = readw(0x1f8f) & 0x1ff;
|
||||
int32 tan1 = Tan(angle1);
|
||||
int32 tan2 = Tan(angle2);
|
||||
int16 y = readw(0x1f83) - readw(0x1f89);
|
||||
int16 left, right;
|
||||
int16 angle1 = readw(0x1f8c) & 0x1ff;
|
||||
int16 angle2 = readw(0x1f8f) & 0x1ff;
|
||||
int32 tan1 = Tan(angle1);
|
||||
int32 tan2 = Tan(angle2);
|
||||
int16 y = readw(0x1f83) - readw(0x1f89);
|
||||
int16 left, right;
|
||||
|
||||
for(int32 j = 0; j < 225; j++, y++) {
|
||||
if(y >= 0) {
|
||||
left = sar((int32)tan1 * y, 16) - readw(0x1f80) + readw(0x1f86);
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifdef CX4_CPP
|
||||
|
||||
void Cx4::serialize(serializer &s) {
|
||||
s.array(ram);
|
||||
s.array(reg);
|
||||
|
||||
s.integer(r0);
|
||||
s.integer(r1);
|
||||
s.integer(r2);
|
||||
s.integer(r3);
|
||||
s.integer(r4);
|
||||
s.integer(r5);
|
||||
s.integer(r6);
|
||||
s.integer(r7);
|
||||
s.integer(r8);
|
||||
s.integer(r9);
|
||||
s.integer(r10);
|
||||
s.integer(r11);
|
||||
s.integer(r12);
|
||||
s.integer(r13);
|
||||
s.integer(r14);
|
||||
s.integer(r15);
|
||||
|
||||
s.integer(C4WFXVal);
|
||||
s.integer(C4WFYVal);
|
||||
s.integer(C4WFZVal);
|
||||
s.integer(C4WFX2Val);
|
||||
s.integer(C4WFY2Val);
|
||||
s.integer(C4WFDist);
|
||||
s.integer(C4WFScale);
|
||||
|
||||
s.integer(C41FXVal);
|
||||
s.integer(C41FYVal);
|
||||
s.integer(C41FAngleRes);
|
||||
s.integer(C41FDist);
|
||||
s.integer(C41FDistVal);
|
||||
}
|
||||
|
||||
#endif
|
||||
+23
-3
@@ -5,10 +5,30 @@ namespace SNES {
|
||||
|
||||
DSP1 dsp1;
|
||||
|
||||
#include "serialization.cpp"
|
||||
#include "dsp1emu.cpp"
|
||||
|
||||
void DSP1::init() {}
|
||||
void DSP1::enable() {}
|
||||
void DSP1::init() {
|
||||
}
|
||||
|
||||
void DSP1::enable() {
|
||||
switch(cartridge.dsp1_mapper()) {
|
||||
case Cartridge::DSP1LoROM1MB: {
|
||||
bus.map(Bus::MapDirect, 0x20, 0x3f, 0x8000, 0xffff, *this);
|
||||
bus.map(Bus::MapDirect, 0xa0, 0xbf, 0x8000, 0xffff, *this);
|
||||
} break;
|
||||
|
||||
case Cartridge::DSP1LoROM2MB: {
|
||||
bus.map(Bus::MapDirect, 0x60, 0x6f, 0x0000, 0x7fff, *this);
|
||||
bus.map(Bus::MapDirect, 0xe0, 0xef, 0x0000, 0x7fff, *this);
|
||||
} break;
|
||||
|
||||
case Cartridge::DSP1HiROM: {
|
||||
bus.map(Bus::MapDirect, 0x00, 0x1f, 0x6000, 0x7fff, *this);
|
||||
bus.map(Bus::MapDirect, 0x80, 0x9f, 0x6000, 0x7fff, *this);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void DSP1::power() {
|
||||
reset();
|
||||
@@ -59,5 +79,5 @@ void DSP1::write(unsigned addr, uint8 data) {
|
||||
dsp1.setDr(data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
@@ -1,10 +1,6 @@
|
||||
#include "dsp1emu.hpp"
|
||||
|
||||
class DSP1 : public Memory {
|
||||
private:
|
||||
Dsp1 dsp1;
|
||||
bool addr_decode(uint16 addr);
|
||||
|
||||
public:
|
||||
void init();
|
||||
void enable();
|
||||
@@ -13,6 +9,12 @@ public:
|
||||
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
void serialize(serializer&);
|
||||
|
||||
private:
|
||||
Dsp1 dsp1;
|
||||
bool addr_decode(uint16 addr);
|
||||
};
|
||||
|
||||
extern DSP1 dsp1;
|
||||
@@ -33,6 +33,8 @@ class Dsp1
|
||||
void setDr(uint8 iDr);
|
||||
void reset();
|
||||
|
||||
void serialize(serializer&);
|
||||
|
||||
private:
|
||||
enum FsmMajorState {WAIT_COMMAND, READ_DATA, WRITE_DATA};
|
||||
enum MaxDataAccesses {MAX_READS=7, MAX_WRITES=1024};
|
||||
@@ -72,7 +74,7 @@ class Dsp1
|
||||
uint8 mSr; // status register
|
||||
int mSrLowByteAccess;
|
||||
uint16 mDr; // "internal" representation of the data register
|
||||
FsmMajorState mFsmMajorState; // current major state of the FSM
|
||||
unsigned mFsmMajorState; // current major state of the FSM
|
||||
uint8 mCommand; // current command processed by the FSM
|
||||
uint8 mDataCounter; // #uint16 read/writes counter used by the FSM
|
||||
int16 mReadBuffer[MAX_READS];
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
#ifdef DSP1_CPP
|
||||
|
||||
void DSP1::serialize(serializer &s) {
|
||||
dsp1.serialize(s);
|
||||
}
|
||||
|
||||
void Dsp1::serialize(serializer &s) {
|
||||
for(unsigned i = 0; i < 3; i++) {
|
||||
s.array(shared.MatrixA[i]);
|
||||
s.array(shared.MatrixB[i]);
|
||||
s.array(shared.MatrixC[i]);
|
||||
}
|
||||
|
||||
s.integer(shared.CentreX);
|
||||
s.integer(shared.CentreY);
|
||||
s.integer(shared.CentreZ);
|
||||
s.integer(shared.CentreZ_C);
|
||||
s.integer(shared.CentreZ_E);
|
||||
s.integer(shared.VOffset);
|
||||
s.integer(shared.Les);
|
||||
s.integer(shared.C_Les);
|
||||
s.integer(shared.E_Les);
|
||||
s.integer(shared.SinAas);
|
||||
s.integer(shared.CosAas);
|
||||
s.integer(shared.SinAzs);
|
||||
s.integer(shared.CosAzs);
|
||||
s.integer(shared.SinAZS);
|
||||
s.integer(shared.CosAZS);
|
||||
s.integer(shared.SecAZS_C1);
|
||||
s.integer(shared.SecAZS_E1);
|
||||
s.integer(shared.SecAZS_C2);
|
||||
s.integer(shared.SecAZS_E2);
|
||||
s.integer(shared.Nx);
|
||||
s.integer(shared.Ny);
|
||||
s.integer(shared.Nz);
|
||||
s.integer(shared.Gx);
|
||||
s.integer(shared.Gy);
|
||||
s.integer(shared.Gz);
|
||||
s.integer(shared.Hx);
|
||||
s.integer(shared.Hy);
|
||||
s.integer(shared.Vx);
|
||||
s.integer(shared.Vy);
|
||||
s.integer(shared.Vz);
|
||||
|
||||
s.integer(mSr);
|
||||
s.integer(mSrLowByteAccess);
|
||||
s.integer(mDr);
|
||||
s.integer(mFsmMajorState);
|
||||
s.integer(mCommand);
|
||||
s.integer(mDataCounter);
|
||||
s.array(mReadBuffer);
|
||||
s.array(mWriteBuffer);
|
||||
s.integer(mFreeze);
|
||||
}
|
||||
|
||||
#endif
|
||||
+11
-3
@@ -5,10 +5,18 @@ namespace SNES {
|
||||
|
||||
DSP2 dsp2;
|
||||
|
||||
#include "dsp2_op.cpp"
|
||||
#include "serialization.cpp"
|
||||
#include "opcodes.cpp"
|
||||
|
||||
void DSP2::init() {}
|
||||
void DSP2::enable() {}
|
||||
void DSP2::init() {
|
||||
}
|
||||
|
||||
void DSP2::enable() {
|
||||
bus.map(Bus::MapDirect, 0x20, 0x3f, 0x6000, 0x6fff, *this);
|
||||
bus.map(Bus::MapDirect, 0x20, 0x3f, 0x8000, 0xbfff, *this);
|
||||
bus.map(Bus::MapDirect, 0xa0, 0xbf, 0x6000, 0x6fff, *this);
|
||||
bus.map(Bus::MapDirect, 0xa0, 0xbf, 0x8000, 0xbfff, *this);
|
||||
}
|
||||
|
||||
void DSP2::power() {
|
||||
reset();
|
||||
|
||||
@@ -29,6 +29,7 @@ public:
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
void serialize(serializer&);
|
||||
DSP2();
|
||||
~DSP2();
|
||||
|
||||
|
||||
File renamed without changes.
@@ -0,0 +1,26 @@
|
||||
#ifdef DSP2_CPP
|
||||
|
||||
void DSP2::serialize(serializer &s) {
|
||||
s.integer(status.waiting_for_command);
|
||||
s.integer(status.command);
|
||||
s.integer(status.in_count);
|
||||
s.integer(status.in_index);
|
||||
s.integer(status.out_count);
|
||||
s.integer(status.out_index);
|
||||
|
||||
s.array(status.parameters);
|
||||
s.array(status.output);
|
||||
|
||||
s.integer(status.op05transparent);
|
||||
s.integer(status.op05haslen);
|
||||
s.integer(status.op05len);
|
||||
s.integer(status.op06haslen);
|
||||
s.integer(status.op06len);
|
||||
s.integer(status.op09word1);
|
||||
s.integer(status.op09word2);
|
||||
s.integer(status.op0dhaslen);
|
||||
s.integer(status.op0doutlen);
|
||||
s.integer(status.op0dinlen);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -15,6 +15,8 @@ void DSP3::init() {
|
||||
}
|
||||
|
||||
void DSP3::enable() {
|
||||
bus.map(Bus::MapDirect, 0x20, 0x3f, 0x8000, 0xffff, *this);
|
||||
bus.map(Bus::MapDirect, 0xa0, 0xbf, 0x8000, 0xffff, *this);
|
||||
}
|
||||
|
||||
void DSP3::power() {
|
||||
|
||||
@@ -5,6 +5,14 @@ namespace SNES {
|
||||
|
||||
DSP4 dsp4;
|
||||
|
||||
void DSP4::init() {
|
||||
}
|
||||
|
||||
void DSP4::enable() {
|
||||
bus.map(Bus::MapDirect, 0x30, 0x3f, 0x8000, 0xffff, *this);
|
||||
bus.map(Bus::MapDirect, 0xb0, 0xbf, 0x8000, 0xffff, *this);
|
||||
}
|
||||
|
||||
namespace DSP4i {
|
||||
inline uint16 READ_WORD(uint8 *addr) {
|
||||
return (addr[0]) + (addr[1] << 8);
|
||||
@@ -24,12 +32,6 @@ namespace DSP4i {
|
||||
#undef bool8
|
||||
};
|
||||
|
||||
void DSP4::init() {
|
||||
}
|
||||
|
||||
void DSP4::enable() {
|
||||
}
|
||||
|
||||
void DSP4::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
@@ -2062,9 +2062,9 @@ void DSP4SetByte()
|
||||
// unknown
|
||||
case 0x000A:
|
||||
{
|
||||
//int16 in1a = DSP4_READ_WORD();
|
||||
int16 in1a = DSP4_READ_WORD();
|
||||
int16 in2a = DSP4_READ_WORD();
|
||||
//int16 in3a = DSP4_READ_WORD();
|
||||
int16 in3a = DSP4_READ_WORD();
|
||||
int16 out1a, out2a, out3a, out4a;
|
||||
|
||||
DSP4_OP0A(in2a, &out2a, &out1a, &out4a, &out3a);
|
||||
|
||||
@@ -5,8 +5,15 @@ namespace SNES {
|
||||
|
||||
OBC1 obc1;
|
||||
|
||||
void OBC1::init() {}
|
||||
void OBC1::enable() {}
|
||||
#include "serialization.cpp"
|
||||
|
||||
void OBC1::init() {
|
||||
}
|
||||
|
||||
void OBC1::enable() {
|
||||
bus.map(Bus::MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, *this);
|
||||
bus.map(Bus::MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, *this);
|
||||
}
|
||||
|
||||
void OBC1::power() {
|
||||
reset();
|
||||
|
||||
@@ -8,6 +8,7 @@ public:
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
void serialize(serializer&);
|
||||
OBC1();
|
||||
~OBC1();
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifdef OBC1_CPP
|
||||
|
||||
void OBC1::serialize(serializer &s) {
|
||||
s.integer(status.address);
|
||||
s.integer(status.baseptr);
|
||||
s.integer(status.shift);
|
||||
}
|
||||
|
||||
#endif
|
||||
+107
-23
@@ -1,38 +1,62 @@
|
||||
#ifdef SA1_CPP
|
||||
|
||||
VBRBus vbrbus;
|
||||
SA1Bus sa1bus;
|
||||
|
||||
namespace memory {
|
||||
static VectorSelectionPage vectorsp;
|
||||
static StaticRAM iram(2048);
|
||||
static MappedRAM &bwram = memory::cartram;
|
||||
static CC1BWRAM cc1bwram;
|
||||
static BitmapRAM bitmapram;
|
||||
StaticRAM iram(2048);
|
||||
//accessed by:
|
||||
VectorSelectionPage vectorsp; //S-CPU + SA-1
|
||||
CPUIRAM cpuiram; //S-CPU
|
||||
SA1IRAM sa1iram; //SA-1
|
||||
SA1BWRAM sa1bwram; //SA-1
|
||||
CC1BWRAM cc1bwram; //S-CPU
|
||||
BitmapRAM bitmapram; //SA-1
|
||||
}
|
||||
|
||||
//$230c (VDPL), $230d (VDPH) use this bus to read variable-length data.
|
||||
//this is used both to avoid VBR-reads from accessing MMIO registers, and
|
||||
//to avoid syncing the S-CPU and SA-1*; as both chips are able to access
|
||||
//these ports.
|
||||
//(* eg, memory::cartram is used directly, as memory::sa1bwram syncs to the S-CPU)
|
||||
void VBRBus::init() {
|
||||
map(MapDirect, 0x00, 0xff, 0x0000, 0xffff, memory::memory_unmapped);
|
||||
|
||||
map(MapLinear, 0x00, 0x3f, 0x0000, 0x07ff, memory::iram);
|
||||
map(MapLinear, 0x00, 0x3f, 0x3000, 0x37ff, memory::iram);
|
||||
map(MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::cartram);
|
||||
map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
|
||||
map(MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::cartram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x0000, 0x07ff, memory::iram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x3000, 0x37ff, memory::iram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::cartram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
|
||||
map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom);
|
||||
}
|
||||
|
||||
void SA1Bus::init() {
|
||||
map(MapDirect, 0x00, 0xff, 0x0000, 0xffff, memory::memory_unmapped);
|
||||
for(uint16_t i = 0x2200; i <= 0x23ff; i++) memory::mmio.map(i, sa1);
|
||||
for(unsigned i = 0x2200; i <= 0x23ff; i++) memory::mmio.map(i, sa1);
|
||||
|
||||
map(MapLinear, 0x00, 0x3f, 0x0000, 0x07ff, memory::iram);
|
||||
map(MapLinear, 0x00, 0x3f, 0x0000, 0x07ff, memory::sa1iram);
|
||||
map(MapDirect, 0x00, 0x3f, 0x2200, 0x23ff, memory::mmio);
|
||||
map(MapLinear, 0x00, 0x3f, 0x3000, 0x37ff, memory::iram);
|
||||
map(MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::bwram);
|
||||
map(MapLinear, 0x00, 0x3f, 0x3000, 0x37ff, memory::sa1iram);
|
||||
map(MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::sa1bwram);
|
||||
map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
|
||||
map(MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::bwram);
|
||||
map(MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::sa1bwram);
|
||||
map(MapLinear, 0x60, 0x6f, 0x0000, 0xffff, memory::bitmapram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x0000, 0x07ff, memory::iram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x0000, 0x07ff, memory::sa1iram);
|
||||
map(MapDirect, 0x80, 0xbf, 0x2200, 0x23ff, memory::mmio);
|
||||
map(MapLinear, 0x80, 0xbf, 0x3000, 0x37ff, memory::iram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::bwram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x3000, 0x37ff, memory::sa1iram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::sa1bwram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
|
||||
map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom);
|
||||
|
||||
bus.map(MapLinear, 0x00, 0x3f, 0x3000, 0x37ff, memory::iram);
|
||||
bus.map(MapLinear, 0x00, 0x3f, 0x3000, 0x37ff, memory::cpuiram);
|
||||
bus.map(MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::cc1bwram);
|
||||
bus.map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
|
||||
bus.map(MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::cc1bwram);
|
||||
bus.map(MapLinear, 0x80, 0xbf, 0x3000, 0x37ff, memory::iram);
|
||||
bus.map(MapLinear, 0x80, 0xbf, 0x3000, 0x37ff, memory::cpuiram);
|
||||
bus.map(MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::cc1bwram);
|
||||
bus.map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
|
||||
bus.map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom);
|
||||
@@ -54,7 +78,7 @@ void SA1Bus::init() {
|
||||
//$00:[ffea-ffeb|ffee-ffef] are special cased on read;
|
||||
//all other addresses return original mapped data.
|
||||
|
||||
uint8_t VectorSelectionPage::read(unsigned addr) {
|
||||
uint8 VectorSelectionPage::read(unsigned addr) {
|
||||
switch(0xff00 | (addr & 0xff)) {
|
||||
case 0xffea: case 0xffeb: {
|
||||
if(sa1.mmio.cpu_nvsw == true) return (sa1.mmio.snv >> ((addr & 1) << 3));
|
||||
@@ -68,7 +92,7 @@ uint8_t VectorSelectionPage::read(unsigned addr) {
|
||||
return access->read(addr);
|
||||
}
|
||||
|
||||
void VectorSelectionPage::write(unsigned addr, uint8_t data) {
|
||||
void VectorSelectionPage::write(unsigned addr, uint8 data) {
|
||||
return access->write(addr, data);
|
||||
}
|
||||
|
||||
@@ -85,6 +109,60 @@ void VectorSelectionPage::sync() {
|
||||
}
|
||||
}
|
||||
|
||||
//=======
|
||||
//SA1IRAM
|
||||
//=======
|
||||
|
||||
unsigned SA1IRAM::size() const {
|
||||
return memory::iram.size();
|
||||
}
|
||||
|
||||
uint8 SA1IRAM::read(unsigned addr) {
|
||||
scheduler.sync_copcpu();
|
||||
return memory::iram.read(addr);
|
||||
}
|
||||
|
||||
void SA1IRAM::write(unsigned addr, uint8 data) {
|
||||
scheduler.sync_copcpu();
|
||||
memory::iram.write(addr, data);
|
||||
}
|
||||
|
||||
//=======
|
||||
//CPUIRAM
|
||||
//=======
|
||||
|
||||
unsigned CPUIRAM::size() const {
|
||||
return memory::iram.size();
|
||||
}
|
||||
|
||||
uint8 CPUIRAM::read(unsigned addr) {
|
||||
scheduler.sync_cpucop();
|
||||
return memory::iram.read(addr);
|
||||
}
|
||||
|
||||
void CPUIRAM::write(unsigned addr, uint8 data) {
|
||||
scheduler.sync_cpucop();
|
||||
memory::iram.write(addr, data);
|
||||
}
|
||||
|
||||
//========
|
||||
//SA1BWRAM
|
||||
//========
|
||||
|
||||
unsigned SA1BWRAM::size() const {
|
||||
return memory::cartram.size();
|
||||
}
|
||||
|
||||
uint8 SA1BWRAM::read(unsigned addr) {
|
||||
scheduler.sync_copcpu();
|
||||
return memory::cartram.read(addr);
|
||||
}
|
||||
|
||||
void SA1BWRAM::write(unsigned addr, uint8 data) {
|
||||
scheduler.sync_copcpu();
|
||||
memory::cartram.write(addr, data);
|
||||
}
|
||||
|
||||
//========
|
||||
//CC1BWRAM
|
||||
//========
|
||||
@@ -93,12 +171,14 @@ unsigned CC1BWRAM::size() const {
|
||||
return memory::cartram.size();
|
||||
}
|
||||
|
||||
uint8_t CC1BWRAM::read(unsigned addr) {
|
||||
uint8 CC1BWRAM::read(unsigned addr) {
|
||||
scheduler.sync_cpucop();
|
||||
if(dma) return sa1.dma_cc1_read(addr);
|
||||
return memory::cartram.read(addr);
|
||||
}
|
||||
|
||||
void CC1BWRAM::write(unsigned addr, uint8_t data) {
|
||||
void CC1BWRAM::write(unsigned addr, uint8 data) {
|
||||
scheduler.sync_cpucop();
|
||||
memory::cartram.write(addr, data);
|
||||
}
|
||||
|
||||
@@ -110,7 +190,9 @@ unsigned BitmapRAM::size() const {
|
||||
return 0x100000;
|
||||
}
|
||||
|
||||
uint8_t BitmapRAM::read(unsigned addr) {
|
||||
uint8 BitmapRAM::read(unsigned addr) {
|
||||
scheduler.sync_copcpu();
|
||||
|
||||
if(sa1.mmio.bbf == 0) {
|
||||
//4bpp
|
||||
unsigned shift = addr & 1;
|
||||
@@ -132,10 +214,12 @@ uint8_t BitmapRAM::read(unsigned addr) {
|
||||
}
|
||||
}
|
||||
|
||||
void BitmapRAM::write(unsigned addr, uint8_t data) {
|
||||
void BitmapRAM::write(unsigned addr, uint8 data) {
|
||||
scheduler.sync_copcpu();
|
||||
|
||||
if(sa1.mmio.bbf == 0) {
|
||||
//4bpp
|
||||
uint8_t shift = addr & 1;
|
||||
unsigned shift = addr & 1;
|
||||
addr = (addr >> 1) & (memory::cartram.size() - 1);
|
||||
switch(shift) { default:
|
||||
case 0: data = (memory::cartram.read(addr) & 0xf0) | ((data & 15) << 0); break;
|
||||
@@ -143,7 +227,7 @@ void BitmapRAM::write(unsigned addr, uint8_t data) {
|
||||
}
|
||||
} else {
|
||||
//2bpp
|
||||
uint8_t shift = addr & 3;
|
||||
unsigned shift = addr & 3;
|
||||
addr = (addr >> 2) & (memory::cartram.size() - 1);
|
||||
switch(shift) { default:
|
||||
case 0: data = (memory::cartram.read(addr) & 0xfc) | ((data & 3) << 0); break;
|
||||
|
||||
@@ -1,23 +1,56 @@
|
||||
struct VBRBus : Bus {
|
||||
void init();
|
||||
};
|
||||
|
||||
struct SA1Bus : Bus {
|
||||
void init();
|
||||
};
|
||||
|
||||
struct VectorSelectionPage : Memory {
|
||||
alwaysinline uint8_t read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8_t);
|
||||
alwaysinline uint8 read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8);
|
||||
void sync();
|
||||
Memory *access;
|
||||
};
|
||||
|
||||
struct CPUIRAM : Memory {
|
||||
unsigned size() const;
|
||||
alwaysinline uint8 read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8);
|
||||
};
|
||||
|
||||
struct SA1IRAM : Memory {
|
||||
unsigned size() const;
|
||||
alwaysinline uint8 read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8);
|
||||
};
|
||||
|
||||
struct SA1BWRAM : Memory {
|
||||
unsigned size() const;
|
||||
alwaysinline uint8 read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8);
|
||||
};
|
||||
|
||||
struct CC1BWRAM : Memory {
|
||||
unsigned size() const;
|
||||
alwaysinline uint8_t read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8_t);
|
||||
alwaysinline uint8 read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8);
|
||||
bool dma;
|
||||
};
|
||||
|
||||
struct BitmapRAM : Memory {
|
||||
unsigned size() const;
|
||||
alwaysinline uint8_t read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8_t);
|
||||
alwaysinline uint8 read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8);
|
||||
};
|
||||
|
||||
namespace memory {
|
||||
extern StaticRAM iram;
|
||||
|
||||
extern VectorSelectionPage vectorsp;
|
||||
extern CPUIRAM cpuiram;
|
||||
extern SA1IRAM sa1iram;
|
||||
extern SA1BWRAM sa1bwram;
|
||||
extern CC1BWRAM cc1bwram;
|
||||
extern BitmapRAM bitmapram;
|
||||
};
|
||||
+10
-10
@@ -6,9 +6,9 @@
|
||||
|
||||
void SA1::dma_normal() {
|
||||
while(mmio.dtc--) {
|
||||
uint8_t data = regs.mdr;
|
||||
uint32_t dsa = mmio.dsa++;
|
||||
uint32_t dda = mmio.dda++;
|
||||
uint8 data = regs.mdr;
|
||||
uint32 dsa = mmio.dsa++;
|
||||
uint32 dda = mmio.dda++;
|
||||
|
||||
//source and destination cannot be the same
|
||||
if(mmio.sd == DMA::SourceBWRAM && mmio.dd == DMA::DestBWRAM) continue;
|
||||
@@ -67,7 +67,7 @@ void SA1::dma_cc1() {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t SA1::dma_cc1_read(unsigned addr) {
|
||||
uint8 SA1::dma_cc1_read(unsigned addr) {
|
||||
//16 bytes/char (2bpp); 32 bytes/char (4bpp); 64 bytes/char (8bpp)
|
||||
unsigned charmask = (1 << (6 - mmio.dmacb)) - 1;
|
||||
|
||||
@@ -75,20 +75,20 @@ uint8_t SA1::dma_cc1_read(unsigned addr) {
|
||||
//buffer next character to I-RAM
|
||||
unsigned bpp = 2 << (2 - mmio.dmacb);
|
||||
unsigned bpl = (8 << mmio.dmasize) >> mmio.dmacb;
|
||||
unsigned bwmask = memory::bwram.size() - 1;
|
||||
unsigned bwmask = memory::cartram.size() - 1;
|
||||
unsigned tile = ((addr - mmio.dsa) & bwmask) >> (6 - mmio.dmacb);
|
||||
unsigned ty = (tile >> mmio.dmasize);
|
||||
unsigned tx = tile & ((1 << mmio.dmasize) - 1);
|
||||
unsigned bwaddr = mmio.dsa + ty * 8 * bpl + tx * bpp;
|
||||
|
||||
for(unsigned y = 0; y < 8; y++) {
|
||||
uint64_t data = 0;
|
||||
uint64 data = 0;
|
||||
for(unsigned byte = 0; byte < bpp; byte++) {
|
||||
data |= (uint64_t)memory::bwram.read((bwaddr + byte) & bwmask) << (byte << 3);
|
||||
data |= (uint64)memory::cartram.read((bwaddr + byte) & bwmask) << (byte << 3);
|
||||
}
|
||||
bwaddr += bpl;
|
||||
|
||||
uint8_t out[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
uint8 out[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
for(unsigned x = 0; x < 8; x++) {
|
||||
out[0] |= (data & 1) << (7 - x); data >>= 1;
|
||||
out[1] |= (data & 1) << (7 - x); data >>= 1;
|
||||
@@ -118,7 +118,7 @@ uint8_t SA1::dma_cc1_read(unsigned addr) {
|
||||
|
||||
void SA1::dma_cc2() {
|
||||
//select register file index (0-7 or 8-15)
|
||||
const uint8_t *brf = &mmio.brf[(dma.line & 1) << 3];
|
||||
const uint8 *brf = &mmio.brf[(dma.line & 1) << 3];
|
||||
unsigned bpp = 2 << (2 - mmio.dmacb);
|
||||
unsigned addr = mmio.dda & 0x07ff;
|
||||
addr &= ~((1 << (7 - mmio.dmacb)) - 1);
|
||||
@@ -126,7 +126,7 @@ void SA1::dma_cc2() {
|
||||
addr += (dma.line & 7) * 2;
|
||||
|
||||
for(unsigned byte = 0; byte < bpp; byte++) {
|
||||
uint8_t output = 0;
|
||||
uint8 output = 0;
|
||||
for(unsigned bit = 0; bit < 8; bit++) {
|
||||
output |= ((brf[bit] >> byte) & 1) << (7 - bit);
|
||||
}
|
||||
|
||||
@@ -7,5 +7,5 @@ struct DMA {
|
||||
|
||||
void dma_normal();
|
||||
void dma_cc1();
|
||||
uint8_t dma_cc1_read(unsigned addr);
|
||||
uint8 dma_cc1_read(unsigned addr);
|
||||
void dma_cc2();
|
||||
@@ -1,39 +1,24 @@
|
||||
#ifdef SA1_CPP
|
||||
|
||||
//==========================
|
||||
//SA-1 opcode core functions
|
||||
//==========================
|
||||
|
||||
void SA1::op_io() {
|
||||
tick();
|
||||
if(regs.wai) scheduler.sync_copcpu();
|
||||
}
|
||||
|
||||
//ROM, I-RAM and MMIO registers are accessed at ~10.74MHz (2 clock ticks)
|
||||
//BW-RAM is accessed at ~5.37MHz (4 clock ticks)
|
||||
//tick() == 2 clock ticks
|
||||
//note: bus conflict delays are not emulated at this time
|
||||
|
||||
#define is_bwram(addr) (\
|
||||
((addr & 0x40e000) == 0x006000) \
|
||||
|| ((addr & 0xf00000) == 0x400000) \
|
||||
|| ((addr & 0xf00000) == 0x600000) \
|
||||
)
|
||||
|
||||
uint8_t SA1::op_read(unsigned addr) {
|
||||
void SA1::op_io() {
|
||||
tick();
|
||||
if(is_bwram(addr)) tick();
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
|
||||
uint8 SA1::op_read(unsigned addr) {
|
||||
tick();
|
||||
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
|
||||
return sa1bus.read(addr);
|
||||
}
|
||||
|
||||
void SA1::op_write(unsigned addr, uint8_t data) {
|
||||
void SA1::op_write(unsigned addr, uint8 data) {
|
||||
tick();
|
||||
if(is_bwram(addr)) tick();
|
||||
scheduler.sync_copcpu();
|
||||
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
|
||||
sa1bus.write(addr, data);
|
||||
}
|
||||
|
||||
#undef is_bwram
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,5 @@
|
||||
alwaysinline void op_io();
|
||||
alwaysinline uint8_t op_read(unsigned addr);
|
||||
alwaysinline void op_write(unsigned addr, uint8_t data);
|
||||
alwaysinline unsigned bus_speed(unsigned addr);
|
||||
alwaysinline uint8 op_read(unsigned addr);
|
||||
alwaysinline void op_write(unsigned addr, uint8 data);
|
||||
|
||||
uint8_t vbr_read(unsigned addr);
|
||||
+102
-100
@@ -9,7 +9,7 @@ Memory& SA1::mmio_access(unsigned &addr) {
|
||||
}
|
||||
|
||||
//(CCNT) SA-1 control
|
||||
void SA1::mmio_w2200(uint8_t data) {
|
||||
void SA1::mmio_w2200(uint8 data) {
|
||||
if(mmio.sa1_resb && !(data & 0x80)) {
|
||||
//reset SA-1 CPU
|
||||
regs.pc.w = mmio.crv;
|
||||
@@ -34,7 +34,7 @@ void SA1::mmio_w2200(uint8_t data) {
|
||||
}
|
||||
|
||||
//(SIE) S-CPU interrupt enable
|
||||
void SA1::mmio_w2201(uint8_t data) {
|
||||
void SA1::mmio_w2201(uint8 data) {
|
||||
if(!mmio.cpu_irqen && (data & 0x80)) {
|
||||
if(mmio.cpu_irqfl) {
|
||||
mmio.cpu_irqcl = 0;
|
||||
@@ -54,7 +54,7 @@ void SA1::mmio_w2201(uint8_t data) {
|
||||
}
|
||||
|
||||
//(SIC) S-CPU interrupt clear
|
||||
void SA1::mmio_w2202(uint8_t data) {
|
||||
void SA1::mmio_w2202(uint8 data) {
|
||||
mmio.cpu_irqcl = (data & 0x80);
|
||||
mmio.chdma_irqcl = (data & 0x20);
|
||||
|
||||
@@ -65,19 +65,19 @@ void SA1::mmio_w2202(uint8_t data) {
|
||||
}
|
||||
|
||||
//(CRV) SA-1 reset vector
|
||||
void SA1::mmio_w2203(uint8_t data) { mmio.crv = (mmio.crv & 0xff00) | data; }
|
||||
void SA1::mmio_w2204(uint8_t data) { mmio.crv = (data << 8) | (mmio.crv & 0xff); }
|
||||
void SA1::mmio_w2203(uint8 data) { mmio.crv = (mmio.crv & 0xff00) | data; }
|
||||
void SA1::mmio_w2204(uint8 data) { mmio.crv = (data << 8) | (mmio.crv & 0xff); }
|
||||
|
||||
//(CNV) SA-1 NMI vector
|
||||
void SA1::mmio_w2205(uint8_t data) { mmio.cnv = (mmio.cnv & 0xff00) | data; }
|
||||
void SA1::mmio_w2206(uint8_t data) { mmio.cnv = (data << 8) | (mmio.cnv & 0xff); }
|
||||
void SA1::mmio_w2205(uint8 data) { mmio.cnv = (mmio.cnv & 0xff00) | data; }
|
||||
void SA1::mmio_w2206(uint8 data) { mmio.cnv = (data << 8) | (mmio.cnv & 0xff); }
|
||||
|
||||
//(CIV) SA-1 IRQ vector
|
||||
void SA1::mmio_w2207(uint8_t data) { mmio.civ = (mmio.civ & 0xff00) | data; }
|
||||
void SA1::mmio_w2208(uint8_t data) { mmio.civ = (data << 8) | (mmio.civ & 0xff); }
|
||||
void SA1::mmio_w2207(uint8 data) { mmio.civ = (mmio.civ & 0xff00) | data; }
|
||||
void SA1::mmio_w2208(uint8 data) { mmio.civ = (data << 8) | (mmio.civ & 0xff); }
|
||||
|
||||
//(SCNT) S-CPU control
|
||||
void SA1::mmio_w2209(uint8_t data) {
|
||||
void SA1::mmio_w2209(uint8 data) {
|
||||
mmio.cpu_irq = (data & 0x80);
|
||||
mmio.cpu_ivsw = (data & 0x40);
|
||||
mmio.cpu_nvsw = (data & 0x10);
|
||||
@@ -93,7 +93,7 @@ void SA1::mmio_w2209(uint8_t data) {
|
||||
}
|
||||
|
||||
//(CIE) SA-1 interrupt enable
|
||||
void SA1::mmio_w220a(uint8_t data) {
|
||||
void SA1::mmio_w220a(uint8 data) {
|
||||
if(!mmio.sa1_irqen && (data & 0x80) && mmio.sa1_irqfl ) mmio.sa1_irqcl = 0;
|
||||
if(!mmio.timer_irqen && (data & 0x40) && mmio.timer_irqfl) mmio.timer_irqcl = 0;
|
||||
if(!mmio.dma_irqen && (data & 0x20) && mmio.dma_irqfl ) mmio.dma_irqcl = 0;
|
||||
@@ -106,7 +106,7 @@ void SA1::mmio_w220a(uint8_t data) {
|
||||
}
|
||||
|
||||
//(CIC) SA-1 interrupt clear
|
||||
void SA1::mmio_w220b(uint8_t data) {
|
||||
void SA1::mmio_w220b(uint8 data) {
|
||||
mmio.sa1_irqcl = (data & 0x80);
|
||||
mmio.timer_irqcl = (data & 0x40);
|
||||
mmio.dma_irqcl = (data & 0x20);
|
||||
@@ -119,36 +119,36 @@ void SA1::mmio_w220b(uint8_t data) {
|
||||
}
|
||||
|
||||
//(SNV) S-CPU NMI vector
|
||||
void SA1::mmio_w220c(uint8_t data) { mmio.snv = (mmio.snv & 0xff00) | data; }
|
||||
void SA1::mmio_w220d(uint8_t data) { mmio.snv = (data << 8) | (mmio.snv & 0xff); }
|
||||
void SA1::mmio_w220c(uint8 data) { mmio.snv = (mmio.snv & 0xff00) | data; }
|
||||
void SA1::mmio_w220d(uint8 data) { mmio.snv = (data << 8) | (mmio.snv & 0xff); }
|
||||
|
||||
//(SIV) S-CPU IRQ vector
|
||||
void SA1::mmio_w220e(uint8_t data) { mmio.siv = (mmio.siv & 0xff00) | data; }
|
||||
void SA1::mmio_w220f(uint8_t data) { mmio.siv = (data << 8) | (mmio.siv & 0xff); }
|
||||
void SA1::mmio_w220e(uint8 data) { mmio.siv = (mmio.siv & 0xff00) | data; }
|
||||
void SA1::mmio_w220f(uint8 data) { mmio.siv = (data << 8) | (mmio.siv & 0xff); }
|
||||
|
||||
//(TMC) H/V timer control
|
||||
void SA1::mmio_w2210(uint8_t data) {
|
||||
void SA1::mmio_w2210(uint8 data) {
|
||||
mmio.hvselb = (data & 0x80);
|
||||
mmio.ven = (data & 0x02);
|
||||
mmio.hen = (data & 0x01);
|
||||
}
|
||||
|
||||
//(CTR) SA-1 timer restart
|
||||
void SA1::mmio_w2211(uint8_t data) {
|
||||
void SA1::mmio_w2211(uint8 data) {
|
||||
status.vcounter = 0;
|
||||
status.hcounter = 0;
|
||||
}
|
||||
|
||||
//(HCNT) H-count
|
||||
void SA1::mmio_w2212(uint8_t data) { mmio.hcnt = (mmio.hcnt & 0xff00) | (data << 0); }
|
||||
void SA1::mmio_w2213(uint8_t data) { mmio.hcnt = (mmio.hcnt & 0x00ff) | (data << 8); }
|
||||
void SA1::mmio_w2212(uint8 data) { mmio.hcnt = (mmio.hcnt & 0xff00) | (data << 0); }
|
||||
void SA1::mmio_w2213(uint8 data) { mmio.hcnt = (mmio.hcnt & 0x00ff) | (data << 8); }
|
||||
|
||||
//(VCNT) V-count
|
||||
void SA1::mmio_w2214(uint8_t data) { mmio.vcnt = (mmio.vcnt & 0xff00) | (data << 0); }
|
||||
void SA1::mmio_w2215(uint8_t data) { mmio.vcnt = (mmio.vcnt & 0x00ff) | (data << 8); }
|
||||
void SA1::mmio_w2214(uint8 data) { mmio.vcnt = (mmio.vcnt & 0xff00) | (data << 0); }
|
||||
void SA1::mmio_w2215(uint8 data) { mmio.vcnt = (mmio.vcnt & 0x00ff) | (data << 8); }
|
||||
|
||||
//(CXB) Super MMC bank C
|
||||
void SA1::mmio_w2220(uint8_t data) {
|
||||
void SA1::mmio_w2220(uint8 data) {
|
||||
mmio.cbmode = (data & 0x80);
|
||||
mmio.cb = (data & 0x07);
|
||||
|
||||
@@ -170,7 +170,7 @@ void SA1::mmio_w2220(uint8_t data) {
|
||||
}
|
||||
|
||||
//(DXB) Super MMC bank D
|
||||
void SA1::mmio_w2221(uint8_t data) {
|
||||
void SA1::mmio_w2221(uint8 data) {
|
||||
mmio.dbmode = (data & 0x80);
|
||||
mmio.db = (data & 0x07);
|
||||
|
||||
@@ -190,7 +190,7 @@ void SA1::mmio_w2221(uint8_t data) {
|
||||
}
|
||||
|
||||
//(EXB) Super MMC bank E
|
||||
void SA1::mmio_w2222(uint8_t data) {
|
||||
void SA1::mmio_w2222(uint8 data) {
|
||||
mmio.ebmode = (data & 0x80);
|
||||
mmio.eb = (data & 0x07);
|
||||
|
||||
@@ -210,7 +210,7 @@ void SA1::mmio_w2222(uint8_t data) {
|
||||
}
|
||||
|
||||
//(FXB) Super MMC bank F
|
||||
void SA1::mmio_w2223(uint8_t data) {
|
||||
void SA1::mmio_w2223(uint8 data) {
|
||||
mmio.fbmode = (data & 0x80);
|
||||
mmio.fb = (data & 0x07);
|
||||
|
||||
@@ -230,7 +230,7 @@ void SA1::mmio_w2223(uint8_t data) {
|
||||
}
|
||||
|
||||
//(BMAPS) S-CPU BW-RAM address mapping
|
||||
void SA1::mmio_w2224(uint8_t data) {
|
||||
void SA1::mmio_w2224(uint8 data) {
|
||||
mmio.sbm = (data & 0x1f);
|
||||
|
||||
bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::cc1bwram, mmio.sbm * 0x2000, 0x2000);
|
||||
@@ -238,14 +238,14 @@ void SA1::mmio_w2224(uint8_t data) {
|
||||
}
|
||||
|
||||
//(BMAP) SA-1 BW-RAM address mapping
|
||||
void SA1::mmio_w2225(uint8_t data) {
|
||||
void SA1::mmio_w2225(uint8 data) {
|
||||
mmio.sw46 = (data & 0x80);
|
||||
mmio.cbm = (data & 0x7f);
|
||||
|
||||
if(mmio.sw46 == 0) {
|
||||
//$[40-43]:[0000-ffff] x 32 projection
|
||||
sa1bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::bwram, (mmio.cbm & 0x1f) * 0x2000, 0x2000);
|
||||
sa1bus.map(Bus::MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::bwram, (mmio.cbm & 0x1f) * 0x2000, 0x2000);
|
||||
sa1bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::sa1bwram, (mmio.cbm & 0x1f) * 0x2000, 0x2000);
|
||||
sa1bus.map(Bus::MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::sa1bwram, (mmio.cbm & 0x1f) * 0x2000, 0x2000);
|
||||
} else {
|
||||
//$[60-6f]:[0000-ffff] x 128 projection
|
||||
sa1bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::bitmapram, mmio.cbm * 0x2000, 0x2000);
|
||||
@@ -254,32 +254,32 @@ void SA1::mmio_w2225(uint8_t data) {
|
||||
}
|
||||
|
||||
//(SWBE) S-CPU BW-RAM write enable
|
||||
void SA1::mmio_w2226(uint8_t data) {
|
||||
void SA1::mmio_w2226(uint8 data) {
|
||||
mmio.swen = (data & 0x80);
|
||||
}
|
||||
|
||||
//(CWBE) SA-1 BW-RAM write enable
|
||||
void SA1::mmio_w2227(uint8_t data) {
|
||||
void SA1::mmio_w2227(uint8 data) {
|
||||
mmio.cwen = (data & 0x80);
|
||||
}
|
||||
|
||||
//(BWPA) BW-RAM write-protected area
|
||||
void SA1::mmio_w2228(uint8_t data) {
|
||||
void SA1::mmio_w2228(uint8 data) {
|
||||
mmio.bwp = (data & 0x0f);
|
||||
}
|
||||
|
||||
//(SIWP) S-CPU I-RAM write protection
|
||||
void SA1::mmio_w2229(uint8_t data) {
|
||||
void SA1::mmio_w2229(uint8 data) {
|
||||
mmio.siwp = data;
|
||||
}
|
||||
|
||||
//(CIWP) SA-1 I-RAM write protection
|
||||
void SA1::mmio_w222a(uint8_t data) {
|
||||
void SA1::mmio_w222a(uint8 data) {
|
||||
mmio.ciwp = data;
|
||||
}
|
||||
|
||||
//(DCNT) DMA control
|
||||
void SA1::mmio_w2230(uint8_t data) {
|
||||
void SA1::mmio_w2230(uint8 data) {
|
||||
mmio.dmaen = (data & 0x80);
|
||||
mmio.dprio = (data & 0x40);
|
||||
mmio.cden = (data & 0x20);
|
||||
@@ -291,7 +291,7 @@ void SA1::mmio_w2230(uint8_t data) {
|
||||
}
|
||||
|
||||
//(CDMA) character conversion DMA parameters
|
||||
void SA1::mmio_w2231(uint8_t data) {
|
||||
void SA1::mmio_w2231(uint8 data) {
|
||||
mmio.chdend = (data & 0x80);
|
||||
mmio.dmasize = (data >> 2) & 7;
|
||||
mmio.dmacb = (data & 0x03);
|
||||
@@ -302,16 +302,16 @@ void SA1::mmio_w2231(uint8_t data) {
|
||||
}
|
||||
|
||||
//(SDA) DMA source device start address
|
||||
void SA1::mmio_w2232(uint8_t data) { mmio.dsa = (mmio.dsa & 0xffff00) | (data << 0); }
|
||||
void SA1::mmio_w2233(uint8_t data) { mmio.dsa = (mmio.dsa & 0xff00ff) | (data << 8); }
|
||||
void SA1::mmio_w2234(uint8_t data) { mmio.dsa = (mmio.dsa & 0x00ffff) | (data << 16); }
|
||||
void SA1::mmio_w2232(uint8 data) { mmio.dsa = (mmio.dsa & 0xffff00) | (data << 0); }
|
||||
void SA1::mmio_w2233(uint8 data) { mmio.dsa = (mmio.dsa & 0xff00ff) | (data << 8); }
|
||||
void SA1::mmio_w2234(uint8 data) { mmio.dsa = (mmio.dsa & 0x00ffff) | (data << 16); }
|
||||
|
||||
//(DDA) DMA destination start address
|
||||
void SA1::mmio_w2235(uint8_t data) {
|
||||
void SA1::mmio_w2235(uint8 data) {
|
||||
mmio.dda = (mmio.dda & 0xffff00) | (data << 0);
|
||||
}
|
||||
|
||||
void SA1::mmio_w2236(uint8_t data) {
|
||||
void SA1::mmio_w2236(uint8 data) {
|
||||
mmio.dda = (mmio.dda & 0xff00ff) | (data << 8);
|
||||
|
||||
if(mmio.dmaen == true) {
|
||||
@@ -323,7 +323,7 @@ void SA1::mmio_w2236(uint8_t data) {
|
||||
}
|
||||
}
|
||||
|
||||
void SA1::mmio_w2237(uint8_t data) {
|
||||
void SA1::mmio_w2237(uint8 data) {
|
||||
mmio.dda = (mmio.dda & 0x00ffff) | (data << 16);
|
||||
|
||||
if(mmio.dmaen == true) {
|
||||
@@ -334,23 +334,23 @@ void SA1::mmio_w2237(uint8_t data) {
|
||||
}
|
||||
|
||||
//(DTC) DMA terminal counter
|
||||
void SA1::mmio_w2238(uint8_t data) { mmio.dtc = (mmio.dtc & 0xff00) | (data << 0); }
|
||||
void SA1::mmio_w2239(uint8_t data) { mmio.dtc = (mmio.dtc & 0x00ff) | (data << 8); }
|
||||
void SA1::mmio_w2238(uint8 data) { mmio.dtc = (mmio.dtc & 0xff00) | (data << 0); }
|
||||
void SA1::mmio_w2239(uint8 data) { mmio.dtc = (mmio.dtc & 0x00ff) | (data << 8); }
|
||||
|
||||
//(BBF) BW-RAM bitmap format
|
||||
void SA1::mmio_w223f(uint8_t data) {
|
||||
void SA1::mmio_w223f(uint8 data) {
|
||||
mmio.bbf = (data & 0x80);
|
||||
}
|
||||
|
||||
//(BRF) bitmap register files
|
||||
void SA1::mmio_w2240(uint8_t data) { mmio.brf[ 0] = data; }
|
||||
void SA1::mmio_w2241(uint8_t data) { mmio.brf[ 1] = data; }
|
||||
void SA1::mmio_w2242(uint8_t data) { mmio.brf[ 2] = data; }
|
||||
void SA1::mmio_w2243(uint8_t data) { mmio.brf[ 3] = data; }
|
||||
void SA1::mmio_w2244(uint8_t data) { mmio.brf[ 4] = data; }
|
||||
void SA1::mmio_w2245(uint8_t data) { mmio.brf[ 5] = data; }
|
||||
void SA1::mmio_w2246(uint8_t data) { mmio.brf[ 6] = data; }
|
||||
void SA1::mmio_w2247(uint8_t data) { mmio.brf[ 7] = data;
|
||||
void SA1::mmio_w2240(uint8 data) { mmio.brf[ 0] = data; }
|
||||
void SA1::mmio_w2241(uint8 data) { mmio.brf[ 1] = data; }
|
||||
void SA1::mmio_w2242(uint8 data) { mmio.brf[ 2] = data; }
|
||||
void SA1::mmio_w2243(uint8 data) { mmio.brf[ 3] = data; }
|
||||
void SA1::mmio_w2244(uint8 data) { mmio.brf[ 4] = data; }
|
||||
void SA1::mmio_w2245(uint8 data) { mmio.brf[ 5] = data; }
|
||||
void SA1::mmio_w2246(uint8 data) { mmio.brf[ 6] = data; }
|
||||
void SA1::mmio_w2247(uint8 data) { mmio.brf[ 7] = data;
|
||||
if(mmio.dmaen == true) {
|
||||
if(mmio.cden == 1 && mmio.cdsel == 0) {
|
||||
dma_cc2();
|
||||
@@ -358,14 +358,14 @@ void SA1::mmio_w2247(uint8_t data) { mmio.brf[ 7] = data;
|
||||
}
|
||||
}
|
||||
|
||||
void SA1::mmio_w2248(uint8_t data) { mmio.brf[ 8] = data; }
|
||||
void SA1::mmio_w2249(uint8_t data) { mmio.brf[ 9] = data; }
|
||||
void SA1::mmio_w224a(uint8_t data) { mmio.brf[10] = data; }
|
||||
void SA1::mmio_w224b(uint8_t data) { mmio.brf[11] = data; }
|
||||
void SA1::mmio_w224c(uint8_t data) { mmio.brf[12] = data; }
|
||||
void SA1::mmio_w224d(uint8_t data) { mmio.brf[13] = data; }
|
||||
void SA1::mmio_w224e(uint8_t data) { mmio.brf[14] = data; }
|
||||
void SA1::mmio_w224f(uint8_t data) { mmio.brf[15] = data;
|
||||
void SA1::mmio_w2248(uint8 data) { mmio.brf[ 8] = data; }
|
||||
void SA1::mmio_w2249(uint8 data) { mmio.brf[ 9] = data; }
|
||||
void SA1::mmio_w224a(uint8 data) { mmio.brf[10] = data; }
|
||||
void SA1::mmio_w224b(uint8 data) { mmio.brf[11] = data; }
|
||||
void SA1::mmio_w224c(uint8 data) { mmio.brf[12] = data; }
|
||||
void SA1::mmio_w224d(uint8 data) { mmio.brf[13] = data; }
|
||||
void SA1::mmio_w224e(uint8 data) { mmio.brf[14] = data; }
|
||||
void SA1::mmio_w224f(uint8 data) { mmio.brf[15] = data;
|
||||
if(mmio.dmaen == true) {
|
||||
if(mmio.cden == 1 && mmio.cdsel == 0) {
|
||||
dma_cc2();
|
||||
@@ -374,7 +374,7 @@ void SA1::mmio_w224f(uint8_t data) { mmio.brf[15] = data;
|
||||
}
|
||||
|
||||
//(MCNT) arithmetic control
|
||||
void SA1::mmio_w2250(uint8_t data) {
|
||||
void SA1::mmio_w2250(uint8 data) {
|
||||
mmio.acm = (data & 0x02);
|
||||
mmio.md = (data & 0x01);
|
||||
|
||||
@@ -382,38 +382,38 @@ void SA1::mmio_w2250(uint8_t data) {
|
||||
}
|
||||
|
||||
//(MAL) multiplicand / dividend low
|
||||
void SA1::mmio_w2251(uint8_t data) {
|
||||
void SA1::mmio_w2251(uint8 data) {
|
||||
mmio.ma = (mmio.ma & 0xff00) | data;
|
||||
}
|
||||
|
||||
//(MAH) multiplicand / dividend high
|
||||
void SA1::mmio_w2252(uint8_t data) {
|
||||
void SA1::mmio_w2252(uint8 data) {
|
||||
mmio.ma = (data << 8) | (mmio.ma & 0x00ff);
|
||||
}
|
||||
|
||||
//(MBL) multiplier / divisor low
|
||||
void SA1::mmio_w2253(uint8_t data) {
|
||||
void SA1::mmio_w2253(uint8 data) {
|
||||
mmio.mb = (mmio.mb & 0xff00) | data;
|
||||
}
|
||||
|
||||
//(MBH) multiplier / divisor high
|
||||
//multiplication / cumulative sum only resets MB
|
||||
//division resets both MA and MB
|
||||
void SA1::mmio_w2254(uint8_t data) {
|
||||
void SA1::mmio_w2254(uint8 data) {
|
||||
mmio.mb = (data << 8) | (mmio.mb & 0x00ff);
|
||||
|
||||
if(mmio.acm == 0) {
|
||||
if(mmio.md == 0) {
|
||||
//signed multiplication
|
||||
mmio.mr = (int16_t)mmio.ma * (int16_t)mmio.mb;
|
||||
mmio.mr = (int16)mmio.ma * (int16)mmio.mb;
|
||||
mmio.mb = 0;
|
||||
} else {
|
||||
//unsigned division
|
||||
if(mmio.mb == 0) {
|
||||
mmio.mr = 0;
|
||||
} else {
|
||||
int16_t quotient = (int16_t)mmio.ma / (uint16_t)mmio.mb;
|
||||
uint16_t remainder = (int16_t)mmio.ma % (uint16_t)mmio.mb;
|
||||
int16 quotient = (int16)mmio.ma / (uint16)mmio.mb;
|
||||
uint16 remainder = (int16)mmio.ma % (uint16)mmio.mb;
|
||||
mmio.mr = (remainder << 16) | quotient;
|
||||
}
|
||||
mmio.ma = 0;
|
||||
@@ -421,7 +421,7 @@ void SA1::mmio_w2254(uint8_t data) {
|
||||
}
|
||||
} else {
|
||||
//sigma (accumulative multiplication)
|
||||
mmio.mr += (int16_t)mmio.ma * (int16_t)mmio.mb;
|
||||
mmio.mr += (int16)mmio.ma * (int16)mmio.mb;
|
||||
mmio.overflow = (mmio.mr >= (1ULL << 40));
|
||||
mmio.mr &= (1ULL << 40) - 1;
|
||||
mmio.mb = 0;
|
||||
@@ -429,7 +429,7 @@ void SA1::mmio_w2254(uint8_t data) {
|
||||
}
|
||||
|
||||
//(VBD) variable-length bit processing
|
||||
void SA1::mmio_w2258(uint8_t data) {
|
||||
void SA1::mmio_w2258(uint8 data) {
|
||||
mmio.hl = (data & 0x80);
|
||||
mmio.vb = (data & 0x0f);
|
||||
if(mmio.vb == 0) mmio.vb = 16;
|
||||
@@ -443,13 +443,13 @@ void SA1::mmio_w2258(uint8_t data) {
|
||||
}
|
||||
|
||||
//(VDA) variable-length bit game pak ROM start address
|
||||
void SA1::mmio_w2259(uint8_t data) { mmio.va = (mmio.va & 0xffff00) | (data << 0); }
|
||||
void SA1::mmio_w225a(uint8_t data) { mmio.va = (mmio.va & 0xff00ff) | (data << 8); }
|
||||
void SA1::mmio_w225b(uint8_t data) { mmio.va = (mmio.va & 0x00ffff) | (data << 16); mmio.vbit = 0; }
|
||||
void SA1::mmio_w2259(uint8 data) { mmio.va = (mmio.va & 0xffff00) | (data << 0); }
|
||||
void SA1::mmio_w225a(uint8 data) { mmio.va = (mmio.va & 0xff00ff) | (data << 8); }
|
||||
void SA1::mmio_w225b(uint8 data) { mmio.va = (mmio.va & 0x00ffff) | (data << 16); mmio.vbit = 0; }
|
||||
|
||||
//(SFR) S-CPU flag read
|
||||
uint8_t SA1::mmio_r2300() {
|
||||
uint8_t data;
|
||||
uint8 SA1::mmio_r2300() {
|
||||
uint8 data;
|
||||
data = mmio.cpu_irqfl << 7;
|
||||
data |= mmio.cpu_ivsw << 6;
|
||||
data |= mmio.chdma_irqfl << 5;
|
||||
@@ -459,8 +459,8 @@ uint8_t SA1::mmio_r2300() {
|
||||
}
|
||||
|
||||
//(CFR) SA-1 flag read
|
||||
uint8_t SA1::mmio_r2301() {
|
||||
uint8_t data;
|
||||
uint8 SA1::mmio_r2301() {
|
||||
uint8 data;
|
||||
data = mmio.sa1_irqfl << 7;
|
||||
data |= mmio.timer_irqfl << 6;
|
||||
data |= mmio.dma_irqfl << 5;
|
||||
@@ -470,41 +470,41 @@ uint8_t SA1::mmio_r2301() {
|
||||
}
|
||||
|
||||
//(HCR) hcounter read
|
||||
uint8_t SA1::mmio_r2302() {
|
||||
uint8 SA1::mmio_r2302() {
|
||||
//latch counters
|
||||
mmio.hcr = status.hcounter >> 2;
|
||||
mmio.vcr = status.vcounter;
|
||||
return mmio.hcr >> 0; }
|
||||
uint8_t SA1::mmio_r2303() { return mmio.hcr >> 8; }
|
||||
uint8 SA1::mmio_r2303() { return mmio.hcr >> 8; }
|
||||
|
||||
//(VCR) vcounter read
|
||||
uint8_t SA1::mmio_r2304() { return mmio.vcr >> 0; }
|
||||
uint8_t SA1::mmio_r2305() { return mmio.vcr >> 8; }
|
||||
uint8 SA1::mmio_r2304() { return mmio.vcr >> 0; }
|
||||
uint8 SA1::mmio_r2305() { return mmio.vcr >> 8; }
|
||||
|
||||
//(MR) arithmetic result
|
||||
uint8_t SA1::mmio_r2306() { return mmio.mr >> 0; }
|
||||
uint8_t SA1::mmio_r2307() { return mmio.mr >> 8; }
|
||||
uint8_t SA1::mmio_r2308() { return mmio.mr >> 16; }
|
||||
uint8_t SA1::mmio_r2309() { return mmio.mr >> 24; }
|
||||
uint8_t SA1::mmio_r230a() { return mmio.mr >> 32; }
|
||||
uint8 SA1::mmio_r2306() { return mmio.mr >> 0; }
|
||||
uint8 SA1::mmio_r2307() { return mmio.mr >> 8; }
|
||||
uint8 SA1::mmio_r2308() { return mmio.mr >> 16; }
|
||||
uint8 SA1::mmio_r2309() { return mmio.mr >> 24; }
|
||||
uint8 SA1::mmio_r230a() { return mmio.mr >> 32; }
|
||||
|
||||
//(OF) arithmetic overflow flag
|
||||
uint8_t SA1::mmio_r230b() { return mmio.overflow << 7; }
|
||||
uint8 SA1::mmio_r230b() { return mmio.overflow << 7; }
|
||||
|
||||
//(VDPL) variable-length data read port low
|
||||
uint8_t SA1::mmio_r230c() {
|
||||
uint32_t data = (sa1bus.read(mmio.va + 0) << 0)
|
||||
| (sa1bus.read(mmio.va + 1) << 8)
|
||||
| (sa1bus.read(mmio.va + 2) << 16);
|
||||
uint8 SA1::mmio_r230c() {
|
||||
uint32 data = (vbrbus.read(mmio.va + 0) << 0)
|
||||
| (vbrbus.read(mmio.va + 1) << 8)
|
||||
| (vbrbus.read(mmio.va + 2) << 16);
|
||||
data >>= mmio.vbit;
|
||||
return data >> 0;
|
||||
}
|
||||
|
||||
//(VDPH) variable-length data read port high
|
||||
uint8_t SA1::mmio_r230d() {
|
||||
uint32_t data = (sa1bus.read(mmio.va + 0) << 0)
|
||||
| (sa1bus.read(mmio.va + 1) << 8)
|
||||
| (sa1bus.read(mmio.va + 2) << 16);
|
||||
uint8 SA1::mmio_r230d() {
|
||||
uint32 data = (vbrbus.read(mmio.va + 0) << 0)
|
||||
| (vbrbus.read(mmio.va + 1) << 8)
|
||||
| (vbrbus.read(mmio.va + 2) << 16);
|
||||
data >>= mmio.vbit;
|
||||
|
||||
if(mmio.hl == 1) {
|
||||
@@ -518,11 +518,12 @@ uint8_t SA1::mmio_r230d() {
|
||||
}
|
||||
|
||||
//(VC) version code register
|
||||
uint8_t SA1::mmio_r230e() {
|
||||
uint8 SA1::mmio_r230e() {
|
||||
return 0x01; //true value unknown
|
||||
}
|
||||
|
||||
uint8_t SA1::mmio_read(unsigned addr) {
|
||||
uint8 SA1::mmio_read(unsigned addr) {
|
||||
(co_active() == scheduler.thread_cpu ? scheduler.sync_cpucop() : scheduler.sync_copcpu());
|
||||
addr &= 0xffff;
|
||||
|
||||
switch(addr) {
|
||||
@@ -546,7 +547,8 @@ uint8_t SA1::mmio_read(unsigned addr) {
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void SA1::mmio_write(unsigned addr, uint8_t data) {
|
||||
void SA1::mmio_write(unsigned addr, uint8 data) {
|
||||
(co_active() == scheduler.thread_cpu ? scheduler.sync_cpucop() : scheduler.sync_copcpu());
|
||||
addr &= 0xffff;
|
||||
|
||||
switch(addr) {
|
||||
|
||||
+119
-119
@@ -1,5 +1,5 @@
|
||||
uint8_t mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8_t data);
|
||||
uint8 mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
Memory& mmio_access(unsigned &addr);
|
||||
|
||||
struct MMIO {
|
||||
@@ -8,7 +8,7 @@ struct MMIO {
|
||||
bool sa1_rdyb;
|
||||
bool sa1_resb;
|
||||
bool sa1_nmi;
|
||||
uint8_t smeg;
|
||||
uint8 smeg;
|
||||
|
||||
//$2201 SIE
|
||||
bool cpu_irqen;
|
||||
@@ -19,19 +19,19 @@ struct MMIO {
|
||||
bool chdma_irqcl;
|
||||
|
||||
//$2203,$2204 CRV
|
||||
uint16_t crv;
|
||||
uint16 crv;
|
||||
|
||||
//$2205,$2206 CNV
|
||||
uint16_t cnv;
|
||||
uint16 cnv;
|
||||
|
||||
//$2207,$2208 CIV
|
||||
uint16_t civ;
|
||||
uint16 civ;
|
||||
|
||||
//$2209 SCNT
|
||||
bool cpu_irq;
|
||||
bool cpu_ivsw;
|
||||
bool cpu_nvsw;
|
||||
uint8_t cmeg;
|
||||
uint8 cmeg;
|
||||
|
||||
//$220a CIE
|
||||
bool sa1_irqen;
|
||||
@@ -46,10 +46,10 @@ struct MMIO {
|
||||
bool sa1_nmicl;
|
||||
|
||||
//$220c,$220d SNV
|
||||
uint16_t snv;
|
||||
uint16 snv;
|
||||
|
||||
//$220e,$220f SIV
|
||||
uint16_t siv;
|
||||
uint16 siv;
|
||||
|
||||
//$2210 TMC
|
||||
bool hvselb;
|
||||
@@ -57,33 +57,33 @@ struct MMIO {
|
||||
bool hen;
|
||||
|
||||
//$2212,$2213
|
||||
uint16_t hcnt;
|
||||
uint16 hcnt;
|
||||
|
||||
//$2214,$2215
|
||||
uint16_t vcnt;
|
||||
uint16 vcnt;
|
||||
|
||||
//$2220 CXB
|
||||
bool cbmode;
|
||||
uint8_t cb;
|
||||
uint8 cb;
|
||||
|
||||
//$2221 DXB
|
||||
bool dbmode;
|
||||
uint8_t db;
|
||||
uint8 db;
|
||||
|
||||
//$2222 EXB
|
||||
bool ebmode;
|
||||
uint8_t eb;
|
||||
uint8 eb;
|
||||
|
||||
//$2223 FXB
|
||||
bool fbmode;
|
||||
uint8_t fb;
|
||||
uint8 fb;
|
||||
|
||||
//$2224 BMAPS
|
||||
uint8_t sbm;
|
||||
uint8 sbm;
|
||||
|
||||
//$2225 BMAP
|
||||
bool sw46;
|
||||
uint8_t cbm;
|
||||
uint8 cbm;
|
||||
|
||||
//$2226 SBWE
|
||||
bool swen;
|
||||
@@ -92,13 +92,13 @@ struct MMIO {
|
||||
bool cwen;
|
||||
|
||||
//$2228 BWPA
|
||||
uint8_t bwp;
|
||||
uint8 bwp;
|
||||
|
||||
//$2229 SIWP
|
||||
uint8_t siwp;
|
||||
uint8 siwp;
|
||||
|
||||
//$222a CIWP
|
||||
uint8_t ciwp;
|
||||
uint8 ciwp;
|
||||
|
||||
//$2230 DCNT
|
||||
bool dmaen;
|
||||
@@ -106,45 +106,45 @@ struct MMIO {
|
||||
bool cden;
|
||||
bool cdsel;
|
||||
bool dd;
|
||||
uint8_t sd;
|
||||
uint8 sd;
|
||||
|
||||
//$2231 CDMA
|
||||
bool chdend;
|
||||
uint8_t dmasize;
|
||||
uint8_t dmacb;
|
||||
uint8 dmasize;
|
||||
uint8 dmacb;
|
||||
|
||||
//$2232-$2234 SDA
|
||||
uint32_t dsa;
|
||||
uint32 dsa;
|
||||
|
||||
//$2235-$2237 DDA
|
||||
uint32_t dda;
|
||||
uint32 dda;
|
||||
|
||||
//$2238,$2239 DTC
|
||||
uint16_t dtc;
|
||||
uint16 dtc;
|
||||
|
||||
//$223f BBF
|
||||
bool bbf;
|
||||
|
||||
//$2240-224f BRF
|
||||
uint8_t brf[16];
|
||||
uint8 brf[16];
|
||||
|
||||
//$2250 MCNT
|
||||
bool acm;
|
||||
bool md;
|
||||
|
||||
//$2251,$2252 MA
|
||||
uint16_t ma;
|
||||
uint16 ma;
|
||||
|
||||
//$2253,$2254 MB
|
||||
uint16_t mb;
|
||||
uint16 mb;
|
||||
|
||||
//$2258 VBD
|
||||
bool hl;
|
||||
uint8_t vb;
|
||||
uint8 vb;
|
||||
|
||||
//$2259-$225b VDA
|
||||
uint32_t va;
|
||||
uint8_t vbit;
|
||||
uint32 va;
|
||||
uint8 vbit;
|
||||
|
||||
//$2300 SFR
|
||||
bool cpu_irqfl;
|
||||
@@ -157,100 +157,100 @@ struct MMIO {
|
||||
bool sa1_nmifl;
|
||||
|
||||
//$2302,$2303 HCR
|
||||
uint16_t hcr;
|
||||
uint16 hcr;
|
||||
|
||||
//$2304,$2305 VCR
|
||||
uint16_t vcr;
|
||||
uint16 vcr;
|
||||
|
||||
//$2306-230a MR
|
||||
uint64_t mr;
|
||||
uint64 mr;
|
||||
|
||||
//$230b OF
|
||||
bool overflow;
|
||||
} mmio;
|
||||
|
||||
void mmio_w2200(uint8_t); //CCNT
|
||||
void mmio_w2201(uint8_t); //SIE
|
||||
void mmio_w2202(uint8_t); //SIC
|
||||
void mmio_w2203(uint8_t); //CRVL
|
||||
void mmio_w2204(uint8_t); //CRVH
|
||||
void mmio_w2205(uint8_t); //CNVL
|
||||
void mmio_w2206(uint8_t); //CNVH
|
||||
void mmio_w2207(uint8_t); //CIVL
|
||||
void mmio_w2208(uint8_t); //CIVH
|
||||
void mmio_w2209(uint8_t); //SCNT
|
||||
void mmio_w220a(uint8_t); //CIE
|
||||
void mmio_w220b(uint8_t); //CIC
|
||||
void mmio_w220c(uint8_t); //SNVL
|
||||
void mmio_w220d(uint8_t); //SNVH
|
||||
void mmio_w220e(uint8_t); //SIVL
|
||||
void mmio_w220f(uint8_t); //SIVH
|
||||
void mmio_w2210(uint8_t); //TMC
|
||||
void mmio_w2211(uint8_t); //CTR
|
||||
void mmio_w2212(uint8_t); //HCNTL
|
||||
void mmio_w2213(uint8_t); //HCNTH
|
||||
void mmio_w2214(uint8_t); //VCNTL
|
||||
void mmio_w2215(uint8_t); //VCNTH
|
||||
void mmio_w2220(uint8_t); //CXB
|
||||
void mmio_w2221(uint8_t); //DXB
|
||||
void mmio_w2222(uint8_t); //EXB
|
||||
void mmio_w2223(uint8_t); //FXB
|
||||
void mmio_w2224(uint8_t); //BMAPS
|
||||
void mmio_w2225(uint8_t); //BMAP
|
||||
void mmio_w2226(uint8_t); //SBWE
|
||||
void mmio_w2227(uint8_t); //CBWE
|
||||
void mmio_w2228(uint8_t); //BWPA
|
||||
void mmio_w2229(uint8_t); //SIWP
|
||||
void mmio_w222a(uint8_t); //CIWP
|
||||
void mmio_w2230(uint8_t); //DCNT
|
||||
void mmio_w2231(uint8_t); //CDMA
|
||||
void mmio_w2232(uint8_t); //SDAL
|
||||
void mmio_w2233(uint8_t); //SDAH
|
||||
void mmio_w2234(uint8_t); //SDAB
|
||||
void mmio_w2235(uint8_t); //DDAL
|
||||
void mmio_w2236(uint8_t); //DDAH
|
||||
void mmio_w2237(uint8_t); //DDAB
|
||||
void mmio_w2238(uint8_t); //DTCL
|
||||
void mmio_w2239(uint8_t); //DTCH
|
||||
void mmio_w223f(uint8_t); //BBF
|
||||
void mmio_w2240(uint8_t); //BRF0
|
||||
void mmio_w2241(uint8_t); //BRF1
|
||||
void mmio_w2242(uint8_t); //BRF2
|
||||
void mmio_w2243(uint8_t); //BRF3
|
||||
void mmio_w2244(uint8_t); //BRF4
|
||||
void mmio_w2245(uint8_t); //BRF5
|
||||
void mmio_w2246(uint8_t); //BRF6
|
||||
void mmio_w2247(uint8_t); //BRF7
|
||||
void mmio_w2248(uint8_t); //BRF8
|
||||
void mmio_w2249(uint8_t); //BRF9
|
||||
void mmio_w224a(uint8_t); //BRFA
|
||||
void mmio_w224b(uint8_t); //BRFB
|
||||
void mmio_w224c(uint8_t); //BRFC
|
||||
void mmio_w224d(uint8_t); //BRFD
|
||||
void mmio_w224e(uint8_t); //BRFE
|
||||
void mmio_w224f(uint8_t); //BRFF
|
||||
void mmio_w2250(uint8_t); //MCNT
|
||||
void mmio_w2251(uint8_t); //MAL
|
||||
void mmio_w2252(uint8_t); //MAH
|
||||
void mmio_w2253(uint8_t); //MBL
|
||||
void mmio_w2254(uint8_t); //MBH
|
||||
void mmio_w2258(uint8_t); //VBD
|
||||
void mmio_w2259(uint8_t); //VDAL
|
||||
void mmio_w225a(uint8_t); //VDAH
|
||||
void mmio_w225b(uint8_t); //VDAB
|
||||
void mmio_w2200(uint8); //CCNT
|
||||
void mmio_w2201(uint8); //SIE
|
||||
void mmio_w2202(uint8); //SIC
|
||||
void mmio_w2203(uint8); //CRVL
|
||||
void mmio_w2204(uint8); //CRVH
|
||||
void mmio_w2205(uint8); //CNVL
|
||||
void mmio_w2206(uint8); //CNVH
|
||||
void mmio_w2207(uint8); //CIVL
|
||||
void mmio_w2208(uint8); //CIVH
|
||||
void mmio_w2209(uint8); //SCNT
|
||||
void mmio_w220a(uint8); //CIE
|
||||
void mmio_w220b(uint8); //CIC
|
||||
void mmio_w220c(uint8); //SNVL
|
||||
void mmio_w220d(uint8); //SNVH
|
||||
void mmio_w220e(uint8); //SIVL
|
||||
void mmio_w220f(uint8); //SIVH
|
||||
void mmio_w2210(uint8); //TMC
|
||||
void mmio_w2211(uint8); //CTR
|
||||
void mmio_w2212(uint8); //HCNTL
|
||||
void mmio_w2213(uint8); //HCNTH
|
||||
void mmio_w2214(uint8); //VCNTL
|
||||
void mmio_w2215(uint8); //VCNTH
|
||||
void mmio_w2220(uint8); //CXB
|
||||
void mmio_w2221(uint8); //DXB
|
||||
void mmio_w2222(uint8); //EXB
|
||||
void mmio_w2223(uint8); //FXB
|
||||
void mmio_w2224(uint8); //BMAPS
|
||||
void mmio_w2225(uint8); //BMAP
|
||||
void mmio_w2226(uint8); //SBWE
|
||||
void mmio_w2227(uint8); //CBWE
|
||||
void mmio_w2228(uint8); //BWPA
|
||||
void mmio_w2229(uint8); //SIWP
|
||||
void mmio_w222a(uint8); //CIWP
|
||||
void mmio_w2230(uint8); //DCNT
|
||||
void mmio_w2231(uint8); //CDMA
|
||||
void mmio_w2232(uint8); //SDAL
|
||||
void mmio_w2233(uint8); //SDAH
|
||||
void mmio_w2234(uint8); //SDAB
|
||||
void mmio_w2235(uint8); //DDAL
|
||||
void mmio_w2236(uint8); //DDAH
|
||||
void mmio_w2237(uint8); //DDAB
|
||||
void mmio_w2238(uint8); //DTCL
|
||||
void mmio_w2239(uint8); //DTCH
|
||||
void mmio_w223f(uint8); //BBF
|
||||
void mmio_w2240(uint8); //BRF0
|
||||
void mmio_w2241(uint8); //BRF1
|
||||
void mmio_w2242(uint8); //BRF2
|
||||
void mmio_w2243(uint8); //BRF3
|
||||
void mmio_w2244(uint8); //BRF4
|
||||
void mmio_w2245(uint8); //BRF5
|
||||
void mmio_w2246(uint8); //BRF6
|
||||
void mmio_w2247(uint8); //BRF7
|
||||
void mmio_w2248(uint8); //BRF8
|
||||
void mmio_w2249(uint8); //BRF9
|
||||
void mmio_w224a(uint8); //BRFA
|
||||
void mmio_w224b(uint8); //BRFB
|
||||
void mmio_w224c(uint8); //BRFC
|
||||
void mmio_w224d(uint8); //BRFD
|
||||
void mmio_w224e(uint8); //BRFE
|
||||
void mmio_w224f(uint8); //BRFF
|
||||
void mmio_w2250(uint8); //MCNT
|
||||
void mmio_w2251(uint8); //MAL
|
||||
void mmio_w2252(uint8); //MAH
|
||||
void mmio_w2253(uint8); //MBL
|
||||
void mmio_w2254(uint8); //MBH
|
||||
void mmio_w2258(uint8); //VBD
|
||||
void mmio_w2259(uint8); //VDAL
|
||||
void mmio_w225a(uint8); //VDAH
|
||||
void mmio_w225b(uint8); //VDAB
|
||||
|
||||
uint8_t mmio_r2300(); //SFR
|
||||
uint8_t mmio_r2301(); //CFR
|
||||
uint8_t mmio_r2302(); //HCRL
|
||||
uint8_t mmio_r2303(); //HCRH
|
||||
uint8_t mmio_r2304(); //VCRL
|
||||
uint8_t mmio_r2305(); //VCRH
|
||||
uint8_t mmio_r2306(); //MR [00-07]
|
||||
uint8_t mmio_r2307(); //MR [08-15]
|
||||
uint8_t mmio_r2308(); //MR [16-23]
|
||||
uint8_t mmio_r2309(); //MR [24-31]
|
||||
uint8_t mmio_r230a(); //MR [32-40]
|
||||
uint8_t mmio_r230b(); //OF
|
||||
uint8_t mmio_r230c(); //VDPL
|
||||
uint8_t mmio_r230d(); //VDPH
|
||||
uint8_t mmio_r230e(); //VC
|
||||
uint8 mmio_r2300(); //SFR
|
||||
uint8 mmio_r2301(); //CFR
|
||||
uint8 mmio_r2302(); //HCRL
|
||||
uint8 mmio_r2303(); //HCRH
|
||||
uint8 mmio_r2304(); //VCRL
|
||||
uint8 mmio_r2305(); //VCRH
|
||||
uint8 mmio_r2306(); //MR [00-07]
|
||||
uint8 mmio_r2307(); //MR [08-15]
|
||||
uint8 mmio_r2308(); //MR [16-23]
|
||||
uint8 mmio_r2309(); //MR [24-31]
|
||||
uint8 mmio_r230a(); //MR [32-40]
|
||||
uint8 mmio_r230b(); //OF
|
||||
uint8 mmio_r230c(); //VDPL
|
||||
uint8 mmio_r230d(); //VDPH
|
||||
uint8 mmio_r230e(); //VC
|
||||
+13
-3
@@ -5,6 +5,7 @@ namespace SNES {
|
||||
|
||||
SA1 sa1;
|
||||
|
||||
#include "serialization.cpp"
|
||||
#include "bus/bus.cpp"
|
||||
#include "dma/dma.cpp"
|
||||
#include "memory/memory.cpp"
|
||||
@@ -12,10 +13,15 @@ SA1 sa1;
|
||||
|
||||
void SA1::enter() {
|
||||
while(true) {
|
||||
while(mmio.sa1_rdyb || mmio.sa1_resb) {
|
||||
if(scheduler.sync == Scheduler::SyncAll) {
|
||||
scheduler.exit(Scheduler::SynchronizeEvent);
|
||||
}
|
||||
|
||||
if(mmio.sa1_rdyb || mmio.sa1_resb) {
|
||||
//SA-1 co-processor is asleep
|
||||
tick();
|
||||
scheduler.sync_copcpu();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(status.interrupt_pending) {
|
||||
@@ -54,7 +60,7 @@ void SA1::last_cycle() {
|
||||
}
|
||||
}
|
||||
|
||||
void SA1::interrupt(uint16_t vector) {
|
||||
void SA1::interrupt(uint16 vector) {
|
||||
op_read(regs.pc.d);
|
||||
op_io();
|
||||
if(!regs.e) op_writestack(regs.pc.b);
|
||||
@@ -73,6 +79,7 @@ bool SA1::interrupt_pending() {
|
||||
|
||||
void SA1::tick() {
|
||||
scheduler.addclocks_cop(2);
|
||||
if(++status.tick_counter == 0) scheduler.sync_copcpu();
|
||||
|
||||
//adjust counters:
|
||||
//note that internally, status counters are in clocks;
|
||||
@@ -125,6 +132,7 @@ void SA1::reset() {
|
||||
for(unsigned addr = 0; addr < memory::iram.size(); addr++) {
|
||||
memory::iram.write(addr, 0x00);
|
||||
}
|
||||
vbrbus.init();
|
||||
sa1bus.init();
|
||||
|
||||
regs.pc.d = 0x000000;
|
||||
@@ -137,7 +145,9 @@ void SA1::reset() {
|
||||
regs.e = 1;
|
||||
regs.mdr = 0x00;
|
||||
regs.wai = false;
|
||||
update_table();
|
||||
CPUcore::update_table();
|
||||
|
||||
status.tick_counter = 0;
|
||||
|
||||
status.interrupt_pending = false;
|
||||
status.interrupt_vector = 0x0000;
|
||||
|
||||
@@ -7,16 +7,18 @@ public:
|
||||
#include "mmio/mmio.hpp"
|
||||
|
||||
struct Status {
|
||||
bool interrupt_pending;
|
||||
uint16_t interrupt_vector;
|
||||
uint8 tick_counter;
|
||||
|
||||
uint16_t scanlines;
|
||||
uint16_t vcounter;
|
||||
uint16_t hcounter;
|
||||
bool interrupt_pending;
|
||||
uint16 interrupt_vector;
|
||||
|
||||
uint16 scanlines;
|
||||
uint16 vcounter;
|
||||
uint16 hcounter;
|
||||
} status;
|
||||
|
||||
void enter();
|
||||
void interrupt(uint16_t vector);
|
||||
void interrupt(uint16 vector);
|
||||
void tick();
|
||||
|
||||
alwaysinline void trigger_irq();
|
||||
@@ -28,6 +30,7 @@ public:
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
void serialize(serializer&);
|
||||
SA1();
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
#ifdef SA1_CPP
|
||||
|
||||
void SA1::serialize(serializer &s) {
|
||||
CPUcore::core_serialize(s);
|
||||
|
||||
//sa1.hpp
|
||||
s.integer(status.tick_counter);
|
||||
|
||||
s.integer(status.interrupt_pending);
|
||||
s.integer(status.interrupt_vector);
|
||||
|
||||
s.integer(status.scanlines);
|
||||
s.integer(status.vcounter);
|
||||
s.integer(status.hcounter);
|
||||
|
||||
//bus/bus.hpp
|
||||
s.array(memory::iram.data(), memory::iram.size());
|
||||
|
||||
memory::vectorsp.sync();
|
||||
|
||||
s.integer(memory::cc1bwram.dma);
|
||||
|
||||
//dma/dma.hpp
|
||||
s.integer(dma.line);
|
||||
|
||||
//mmio/mmio.hpp
|
||||
s.integer(mmio.sa1_irq);
|
||||
s.integer(mmio.sa1_rdyb);
|
||||
s.integer(mmio.sa1_resb);
|
||||
s.integer(mmio.sa1_nmi);
|
||||
s.integer(mmio.smeg);
|
||||
|
||||
s.integer(mmio.cpu_irqen);
|
||||
s.integer(mmio.chdma_irqen);
|
||||
|
||||
s.integer(mmio.cpu_irqcl);
|
||||
s.integer(mmio.chdma_irqcl);
|
||||
|
||||
s.integer(mmio.crv);
|
||||
|
||||
s.integer(mmio.cnv);
|
||||
|
||||
s.integer(mmio.civ);
|
||||
|
||||
s.integer(mmio.cpu_irq);
|
||||
s.integer(mmio.cpu_ivsw);
|
||||
s.integer(mmio.cpu_nvsw);
|
||||
s.integer(mmio.cmeg);
|
||||
|
||||
s.integer(mmio.sa1_irqen);
|
||||
s.integer(mmio.timer_irqen);
|
||||
s.integer(mmio.dma_irqen);
|
||||
s.integer(mmio.sa1_nmien);
|
||||
|
||||
s.integer(mmio.sa1_irqcl);
|
||||
s.integer(mmio.timer_irqcl);
|
||||
s.integer(mmio.dma_irqcl);
|
||||
s.integer(mmio.sa1_nmicl);
|
||||
|
||||
s.integer(mmio.snv);
|
||||
|
||||
s.integer(mmio.siv);
|
||||
|
||||
s.integer(mmio.hvselb);
|
||||
s.integer(mmio.ven);
|
||||
s.integer(mmio.hen);
|
||||
|
||||
s.integer(mmio.hcnt);
|
||||
|
||||
s.integer(mmio.vcnt);
|
||||
|
||||
s.integer(mmio.cbmode);
|
||||
s.integer(mmio.cb);
|
||||
|
||||
s.integer(mmio.dbmode);
|
||||
s.integer(mmio.db);
|
||||
|
||||
s.integer(mmio.ebmode);
|
||||
s.integer(mmio.eb);
|
||||
|
||||
s.integer(mmio.fbmode);
|
||||
s.integer(mmio.fb);
|
||||
|
||||
s.integer(mmio.sbm);
|
||||
|
||||
s.integer(mmio.sw46);
|
||||
s.integer(mmio.cbm);
|
||||
|
||||
s.integer(mmio.swen);
|
||||
|
||||
s.integer(mmio.cwen);
|
||||
|
||||
s.integer(mmio.bwp);
|
||||
|
||||
s.integer(mmio.siwp);
|
||||
|
||||
s.integer(mmio.ciwp);
|
||||
|
||||
s.integer(mmio.dmaen);
|
||||
s.integer(mmio.dprio);
|
||||
s.integer(mmio.cden);
|
||||
s.integer(mmio.cdsel);
|
||||
s.integer(mmio.dd);
|
||||
s.integer(mmio.sd);
|
||||
|
||||
s.integer(mmio.chdend);
|
||||
s.integer(mmio.dmasize);
|
||||
s.integer(mmio.dmacb);
|
||||
|
||||
s.integer(mmio.dsa);
|
||||
|
||||
s.integer(mmio.dda);
|
||||
|
||||
s.integer(mmio.dtc);
|
||||
|
||||
s.integer(mmio.bbf);
|
||||
|
||||
s.array(mmio.brf);
|
||||
|
||||
s.integer(mmio.acm);
|
||||
s.integer(mmio.md);
|
||||
|
||||
s.integer(mmio.ma);
|
||||
|
||||
s.integer(mmio.mb);
|
||||
|
||||
s.integer(mmio.hl);
|
||||
s.integer(mmio.vb);
|
||||
|
||||
s.integer(mmio.va);
|
||||
s.integer(mmio.vbit);
|
||||
|
||||
s.integer(mmio.cpu_irqfl);
|
||||
s.integer(mmio.chdma_irqfl);
|
||||
|
||||
s.integer(mmio.sa1_irqfl);
|
||||
s.integer(mmio.timer_irqfl);
|
||||
s.integer(mmio.dma_irqfl);
|
||||
s.integer(mmio.sa1_nmifl);
|
||||
|
||||
s.integer(mmio.hcr);
|
||||
|
||||
s.integer(mmio.vcr);
|
||||
|
||||
s.integer(mmio.mr);
|
||||
|
||||
s.integer(mmio.overflow);
|
||||
}
|
||||
|
||||
#endif
|
||||
+9
-10
@@ -5,6 +5,7 @@ namespace SNES {
|
||||
|
||||
SDD1 sdd1;
|
||||
|
||||
#include "serialization.cpp"
|
||||
#include "sdd1emu.cpp"
|
||||
|
||||
void SDD1::init() {}
|
||||
@@ -54,10 +55,10 @@ uint8 SDD1::mmio_read(unsigned addr) {
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
case 0x4804: return (mmc[0] >> 20) & 7;
|
||||
case 0x4805: return (mmc[1] >> 20) & 7;
|
||||
case 0x4806: return (mmc[2] >> 20) & 7;
|
||||
case 0x4807: return (mmc[3] >> 20) & 7;
|
||||
case 0x4804: return mmc[0] >> 20;
|
||||
case 0x4805: return mmc[1] >> 20;
|
||||
case 0x4806: return mmc[2] >> 20;
|
||||
case 0x4807: return mmc[3] >> 20;
|
||||
}
|
||||
|
||||
return cpu.regs.mdr;
|
||||
@@ -83,10 +84,10 @@ void SDD1::mmio_write(unsigned addr, uint8 data) {
|
||||
case 0x4800: sdd1_enable = data; break;
|
||||
case 0x4801: xfer_enable = data; break;
|
||||
|
||||
case 0x4804: mmc[0] = (data & 7) << 20; break;
|
||||
case 0x4805: mmc[1] = (data & 7) << 20; break;
|
||||
case 0x4806: mmc[2] = (data & 7) << 20; break;
|
||||
case 0x4807: mmc[3] = (data & 7) << 20; break;
|
||||
case 0x4804: mmc[0] = data << 20; break;
|
||||
case 0x4805: mmc[1] = data << 20; break;
|
||||
case 0x4806: mmc[2] = data << 20; break;
|
||||
case 0x4807: mmc[3] = data << 20; break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,11 +153,9 @@ void SDD1::write(unsigned addr, uint8 data) {
|
||||
}
|
||||
|
||||
SDD1::SDD1() {
|
||||
buffer.data = new uint8[65536];
|
||||
}
|
||||
|
||||
SDD1::~SDD1() {
|
||||
delete[] buffer.data;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -13,6 +13,7 @@ public:
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
void serialize(serializer&);
|
||||
SDD1();
|
||||
~SDD1();
|
||||
|
||||
@@ -30,7 +31,7 @@ private:
|
||||
|
||||
SDD1emu sdd1emu;
|
||||
struct {
|
||||
uint8 *data; //pointer to decompressed S-DD1 data (65536 bytes)
|
||||
uint8 data[65536]; //pointer to decompressed S-DD1 data
|
||||
uint16 offset; //read index into S-DD1 decompression buffer
|
||||
unsigned size; //length of data buffer; reads decrement counter, set ready to false at 0
|
||||
bool ready; //true when data[] is valid; false to invoke sdd1emu.decompress()
|
||||
|
||||
@@ -30,6 +30,7 @@ understood.
|
||||
|
||||
************************************************************************/
|
||||
|
||||
typedef uint8 bool8;
|
||||
#define SDD1_read(__addr) (sdd1.read(__addr))
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
@@ -28,7 +28,7 @@ understood.
|
||||
|
||||
************************************************************************/
|
||||
|
||||
typedef uint8_t bool8;
|
||||
#define bool8 uint8
|
||||
|
||||
class SDD1_IM { //Input Manager
|
||||
|
||||
@@ -160,3 +160,5 @@ class SDD1emu {
|
||||
SDD1_OL OL;
|
||||
|
||||
};
|
||||
|
||||
#undef bool8
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifdef SDD1_CPP
|
||||
|
||||
void SDD1::serialize(serializer &s) {
|
||||
s.integer(sdd1_enable);
|
||||
s.integer(xfer_enable);
|
||||
s.array(mmc);
|
||||
|
||||
for(unsigned n = 0; n < 8; n++) {
|
||||
s.integer(dma[n].addr);
|
||||
s.integer(dma[n].size);
|
||||
}
|
||||
|
||||
s.array(buffer.data);
|
||||
s.integer(buffer.offset);
|
||||
s.integer(buffer.size);
|
||||
s.integer(buffer.ready);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,65 +0,0 @@
|
||||
#include <../base.hpp>
|
||||
|
||||
#define SGB_CPP
|
||||
namespace SNES {
|
||||
|
||||
SuperGameBoy sgb;
|
||||
|
||||
void SuperGameBoy::enter() {
|
||||
while(true) {
|
||||
if(sgb_run) {
|
||||
unsigned samples = sgb_run(samplebuffer, 16);
|
||||
scheduler.addclocks_cop(samples * 10);
|
||||
scheduler.sync_copcpu();
|
||||
} else {
|
||||
scheduler.addclocks_cop(64 * 1024 * 1024);
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t SuperGameBoy::read(unsigned addr) {
|
||||
addr &= 0xffff;
|
||||
if(sgb_read) return sgb_read(addr);
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void SuperGameBoy::write(unsigned addr, uint8_t data) {
|
||||
addr &= 0xffff;
|
||||
if(sgb_write) return sgb_write(addr, data);
|
||||
}
|
||||
|
||||
void SuperGameBoy::init() {
|
||||
if(libsgb.open("SuperGameBoy")) {
|
||||
sgb_init = libsgb.sym("sgb_init");
|
||||
sgb_term = libsgb.sym("sgb_term");
|
||||
sgb_power = libsgb.sym("sgb_power");
|
||||
sgb_reset = libsgb.sym("sgb_reset");
|
||||
sgb_read = libsgb.sym("sgb_read");
|
||||
sgb_write = libsgb.sym("sgb_write");
|
||||
sgb_run = libsgb.sym("sgb_run");
|
||||
}
|
||||
}
|
||||
|
||||
void SuperGameBoy::enable() {
|
||||
}
|
||||
|
||||
void SuperGameBoy::power() {
|
||||
bus.map(Bus::MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, *this);
|
||||
bus.map(Bus::MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, *this);
|
||||
|
||||
if(sgb_init) {
|
||||
sgb_init(SGB2,
|
||||
memory::gbrom.data(), memory::gbrom.size(),
|
||||
memory::gbram.data(), memory::gbram.size()
|
||||
);
|
||||
}
|
||||
|
||||
if(sgb_power) sgb_power();
|
||||
}
|
||||
|
||||
void SuperGameBoy::reset() {
|
||||
if(sgb_reset) sgb_reset();
|
||||
}
|
||||
|
||||
};
|
||||
@@ -1,27 +0,0 @@
|
||||
class SuperGameBoy : public Memory {
|
||||
public:
|
||||
void enter();
|
||||
|
||||
uint8_t read(unsigned addr);
|
||||
void write(unsigned addr, uint8_t data);
|
||||
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
private:
|
||||
library libsgb;
|
||||
uint32_t samplebuffer[4096];
|
||||
|
||||
enum { SGB1 = 0, SGB2 = 1 };
|
||||
function<bool (bool, uint8_t*, unsigned, uint8_t*, unsigned)> sgb_init;
|
||||
function<void ()> sgb_term;
|
||||
function<void ()> sgb_power;
|
||||
function<void ()> sgb_reset;
|
||||
function<uint8_t (unsigned)> sgb_read;
|
||||
function<void (unsigned, uint8_t)> sgb_write;
|
||||
function<unsigned (uint32_t*, unsigned)> sgb_run;
|
||||
};
|
||||
|
||||
extern SuperGameBoy sgb;
|
||||
@@ -4,6 +4,7 @@ public:
|
||||
void init(unsigned mode, unsigned offset, unsigned index);
|
||||
void reset();
|
||||
|
||||
void serialize(serializer&);
|
||||
SPC7110Decomp();
|
||||
~SPC7110Decomp();
|
||||
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
#ifdef SPC7110_CPP
|
||||
|
||||
void SPC7110Decomp::serialize(serializer &s) {
|
||||
s.integer(decomp_mode);
|
||||
s.integer(decomp_offset);
|
||||
|
||||
s.array(decomp_buffer, decomp_buffer_size);
|
||||
s.integer(decomp_buffer_rdoffset);
|
||||
s.integer(decomp_buffer_wroffset);
|
||||
s.integer(decomp_buffer_length);
|
||||
|
||||
for(unsigned n = 0; n < 32; n++) {
|
||||
s.integer(context[n].index);
|
||||
s.integer(context[n].invert);
|
||||
}
|
||||
}
|
||||
|
||||
void SPC7110::serialize(serializer &s) {
|
||||
s.integer(r4801);
|
||||
s.integer(r4802);
|
||||
s.integer(r4803);
|
||||
s.integer(r4804);
|
||||
s.integer(r4805);
|
||||
s.integer(r4806);
|
||||
s.integer(r4807);
|
||||
s.integer(r4808);
|
||||
s.integer(r4809);
|
||||
s.integer(r480a);
|
||||
s.integer(r480b);
|
||||
s.integer(r480c);
|
||||
decomp.serialize(s);
|
||||
|
||||
s.integer(r4811);
|
||||
s.integer(r4812);
|
||||
s.integer(r4813);
|
||||
s.integer(r4814);
|
||||
s.integer(r4815);
|
||||
s.integer(r4816);
|
||||
s.integer(r4817);
|
||||
s.integer(r4818);
|
||||
s.integer(r481x);
|
||||
s.integer(r4814_latch);
|
||||
s.integer(r4815_latch);
|
||||
|
||||
s.integer(r4820);
|
||||
s.integer(r4821);
|
||||
s.integer(r4822);
|
||||
s.integer(r4823);
|
||||
s.integer(r4824);
|
||||
s.integer(r4825);
|
||||
s.integer(r4826);
|
||||
s.integer(r4827);
|
||||
s.integer(r4828);
|
||||
s.integer(r4829);
|
||||
s.integer(r482a);
|
||||
s.integer(r482b);
|
||||
s.integer(r482c);
|
||||
s.integer(r482d);
|
||||
s.integer(r482e);
|
||||
s.integer(r482f);
|
||||
|
||||
s.integer(r4830);
|
||||
s.integer(r4831);
|
||||
s.integer(r4832);
|
||||
s.integer(r4833);
|
||||
s.integer(r4834);
|
||||
|
||||
s.integer(dx_offset);
|
||||
s.integer(ex_offset);
|
||||
s.integer(fx_offset);
|
||||
|
||||
s.integer(r4840);
|
||||
s.integer(r4841);
|
||||
s.integer(r4842);
|
||||
|
||||
s.integer(rtc_state);
|
||||
s.integer(rtc_mode);
|
||||
s.integer(rtc_index);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -5,6 +5,7 @@ namespace SNES {
|
||||
|
||||
SPC7110 spc7110;
|
||||
|
||||
#include "serialization.cpp"
|
||||
#include "decomp.cpp"
|
||||
|
||||
const unsigned SPC7110::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
@@ -534,17 +535,17 @@ void SPC7110::mmio_write(unsigned addr, uint8 data) {
|
||||
|
||||
case 0x4831: {
|
||||
r4831 = data;
|
||||
dx_offset = datarom_addr((data & 7) * 0x100000);
|
||||
dx_offset = datarom_addr(data * 0x100000);
|
||||
} break;
|
||||
|
||||
case 0x4832: {
|
||||
r4832 = data;
|
||||
ex_offset = datarom_addr((data & 7) * 0x100000);
|
||||
ex_offset = datarom_addr(data * 0x100000);
|
||||
} break;
|
||||
|
||||
case 0x4833: {
|
||||
r4833 = data;
|
||||
fx_offset = datarom_addr((data & 7) * 0x100000);
|
||||
fx_offset = datarom_addr(data * 0x100000);
|
||||
} break;
|
||||
|
||||
case 0x4834: r4834 = data; break;
|
||||
|
||||
@@ -35,48 +35,49 @@ public:
|
||||
void update_time(int offset = 0);
|
||||
time_t create_time();
|
||||
|
||||
uint8 mmio_read (unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
uint8 mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
|
||||
uint8 read (unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
//spc7110decomp
|
||||
void decomp_init();
|
||||
uint8 decomp_read();
|
||||
|
||||
void serialize(serializer&);
|
||||
SPC7110();
|
||||
|
||||
private:
|
||||
//==================
|
||||
//decompression unit
|
||||
//==================
|
||||
uint8 r4801; //compression table low
|
||||
uint8 r4802; //compression table high
|
||||
uint8 r4803; //compression table bank
|
||||
uint8 r4804; //compression table index
|
||||
uint8 r4805; //decompression buffer index low
|
||||
uint8 r4806; //decompression buffer index high
|
||||
uint8 r4807; //???
|
||||
uint8 r4808; //???
|
||||
uint8 r4809; //compression length low
|
||||
uint8 r480a; //compression length high
|
||||
uint8 r480b; //decompression control register
|
||||
uint8 r480c; //decompression status
|
||||
uint8 r4801; //compression table low
|
||||
uint8 r4802; //compression table high
|
||||
uint8 r4803; //compression table bank
|
||||
uint8 r4804; //compression table index
|
||||
uint8 r4805; //decompression buffer index low
|
||||
uint8 r4806; //decompression buffer index high
|
||||
uint8 r4807; //???
|
||||
uint8 r4808; //???
|
||||
uint8 r4809; //compression length low
|
||||
uint8 r480a; //compression length high
|
||||
uint8 r480b; //decompression control register
|
||||
uint8 r480c; //decompression status
|
||||
|
||||
SPC7110Decomp decomp;
|
||||
|
||||
//==============
|
||||
//data port unit
|
||||
//==============
|
||||
uint8 r4811; //data pointer low
|
||||
uint8 r4812; //data pointer high
|
||||
uint8 r4813; //data pointer bank
|
||||
uint8 r4814; //data adjust low
|
||||
uint8 r4815; //data adjust high
|
||||
uint8 r4816; //data increment low
|
||||
uint8 r4817; //data increment high
|
||||
uint8 r4818; //data port control register
|
||||
uint8 r4811; //data pointer low
|
||||
uint8 r4812; //data pointer high
|
||||
uint8 r4813; //data pointer bank
|
||||
uint8 r4814; //data adjust low
|
||||
uint8 r4815; //data adjust high
|
||||
uint8 r4816; //data increment low
|
||||
uint8 r4817; //data increment high
|
||||
uint8 r4818; //data port control register
|
||||
|
||||
uint8 r481x;
|
||||
|
||||
@@ -86,31 +87,31 @@ private:
|
||||
//=========
|
||||
//math unit
|
||||
//=========
|
||||
uint8 r4820; //16-bit multiplicand B0, 32-bit dividend B0
|
||||
uint8 r4821; //16-bit multiplicand B1, 32-bit dividend B1
|
||||
uint8 r4822; //32-bit dividend B2
|
||||
uint8 r4823; //32-bit dividend B3
|
||||
uint8 r4824; //16-bit multiplier B0
|
||||
uint8 r4825; //16-bit multiplier B1
|
||||
uint8 r4826; //16-bit divisor B0
|
||||
uint8 r4827; //16-bit divisor B1
|
||||
uint8 r4828; //32-bit product B0, 32-bit quotient B0
|
||||
uint8 r4829; //32-bit product B1, 32-bit quotient B1
|
||||
uint8 r482a; //32-bit product B2, 32-bit quotient B2
|
||||
uint8 r482b; //32-bit product B3, 32-bit quotient B3
|
||||
uint8 r482c; //16-bit remainder B0
|
||||
uint8 r482d; //16-bit remainder B1
|
||||
uint8 r482e; //math control register
|
||||
uint8 r482f; //math status
|
||||
uint8 r4820; //16-bit multiplicand B0, 32-bit dividend B0
|
||||
uint8 r4821; //16-bit multiplicand B1, 32-bit dividend B1
|
||||
uint8 r4822; //32-bit dividend B2
|
||||
uint8 r4823; //32-bit dividend B3
|
||||
uint8 r4824; //16-bit multiplier B0
|
||||
uint8 r4825; //16-bit multiplier B1
|
||||
uint8 r4826; //16-bit divisor B0
|
||||
uint8 r4827; //16-bit divisor B1
|
||||
uint8 r4828; //32-bit product B0, 32-bit quotient B0
|
||||
uint8 r4829; //32-bit product B1, 32-bit quotient B1
|
||||
uint8 r482a; //32-bit product B2, 32-bit quotient B2
|
||||
uint8 r482b; //32-bit product B3, 32-bit quotient B3
|
||||
uint8 r482c; //16-bit remainder B0
|
||||
uint8 r482d; //16-bit remainder B1
|
||||
uint8 r482e; //math control register
|
||||
uint8 r482f; //math status
|
||||
|
||||
//===================
|
||||
//memory mapping unit
|
||||
//===================
|
||||
uint8 r4830; //SRAM write enable
|
||||
uint8 r4831; //$[d0-df]:[0000-ffff] mapping
|
||||
uint8 r4832; //$[e0-ef]:[0000-ffff] mapping
|
||||
uint8 r4833; //$[f0-ff]:[0000-ffff] mapping
|
||||
uint8 r4834; //???
|
||||
uint8 r4830; //SRAM write enable
|
||||
uint8 r4831; //$[d0-df]:[0000-ffff] mapping
|
||||
uint8 r4832; //$[e0-ef]:[0000-ffff] mapping
|
||||
uint8 r4833; //$[f0-ff]:[0000-ffff] mapping
|
||||
uint8 r4834; //???
|
||||
|
||||
unsigned dx_offset;
|
||||
unsigned ex_offset;
|
||||
@@ -119,12 +120,14 @@ private:
|
||||
//====================
|
||||
//real-time clock unit
|
||||
//====================
|
||||
uint8 r4840; //RTC latch
|
||||
uint8 r4841; //RTC index/data port
|
||||
uint8 r4842; //RTC status
|
||||
uint8 r4840; //RTC latch
|
||||
uint8 r4841; //RTC index/data port
|
||||
uint8 r4842; //RTC status
|
||||
|
||||
enum RTC_State { RTCS_Inactive, RTCS_ModeSelect, RTCS_IndexSelect, RTCS_Write } rtc_state;
|
||||
enum RTC_Mode { RTCM_Linear = 0x03, RTCM_Indexed = 0x0c } rtc_mode;
|
||||
enum RTC_State { RTCS_Inactive, RTCS_ModeSelect, RTCS_IndexSelect, RTCS_Write };
|
||||
enum RTC_Mode { RTCM_Linear = 0x03, RTCM_Indexed = 0x0c };
|
||||
unsigned rtc_state;
|
||||
unsigned rtc_mode;
|
||||
unsigned rtc_index;
|
||||
|
||||
static const unsigned months[12];
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifdef SRTC_CPP
|
||||
|
||||
void SRTC::serialize(serializer &s) {
|
||||
s.integer(rtc_mode);
|
||||
s.integer(rtc_index);
|
||||
}
|
||||
|
||||
#endif
|
||||
+11
-9
@@ -5,6 +5,8 @@ namespace SNES {
|
||||
|
||||
SRTC srtc;
|
||||
|
||||
#include "serialization.cpp"
|
||||
|
||||
const unsigned SRTC::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
void SRTC::init() {
|
||||
@@ -20,7 +22,7 @@ void SRTC::power() {
|
||||
}
|
||||
|
||||
void SRTC::reset() {
|
||||
rtc_mode = RTCM_Read;
|
||||
rtc_mode = RtcRead;
|
||||
rtc_index = -1;
|
||||
update_time();
|
||||
}
|
||||
@@ -159,7 +161,7 @@ uint8 SRTC::mmio_read(unsigned addr) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr == 0x2800) {
|
||||
if(rtc_mode != RTCM_Read) return 0x00;
|
||||
if(rtc_mode != RtcRead) return 0x00;
|
||||
|
||||
if(rtc_index < 0) {
|
||||
update_time();
|
||||
@@ -183,19 +185,19 @@ void SRTC::mmio_write(unsigned addr, uint8 data) {
|
||||
data &= 0x0f; //only the low four bits are used
|
||||
|
||||
if(data == 0x0d) {
|
||||
rtc_mode = RTCM_Read;
|
||||
rtc_mode = RtcRead;
|
||||
rtc_index = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
if(data == 0x0e) {
|
||||
rtc_mode = RTCM_Command;
|
||||
rtc_mode = RtcCommand;
|
||||
return;
|
||||
}
|
||||
|
||||
if(data == 0x0f) return; //unknown behavior
|
||||
|
||||
if(rtc_mode == RTCM_Write) {
|
||||
if(rtc_mode == RtcWrite) {
|
||||
if(rtc_index >= 0 && rtc_index < 12) {
|
||||
memory::cartrtc.write(rtc_index++, data);
|
||||
|
||||
@@ -209,17 +211,17 @@ void SRTC::mmio_write(unsigned addr, uint8 data) {
|
||||
memory::cartrtc.write(rtc_index++, weekday(year, month, day));
|
||||
}
|
||||
}
|
||||
} else if(rtc_mode == RTCM_Command) {
|
||||
} else if(rtc_mode == RtcCommand) {
|
||||
if(data == 0) {
|
||||
rtc_mode = RTCM_Write;
|
||||
rtc_mode = RtcWrite;
|
||||
rtc_index = 0;
|
||||
} else if(data == 4) {
|
||||
rtc_mode = RTCM_Ready;
|
||||
rtc_mode = RtcReady;
|
||||
rtc_index = -1;
|
||||
for(unsigned i = 0; i < 13; i++) memory::cartrtc.write(i, 0);
|
||||
} else {
|
||||
//unknown behavior
|
||||
rtc_mode = RTCM_Ready;
|
||||
rtc_mode = RtcReady;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
class SRTC : public MMIO {
|
||||
public:
|
||||
void update_time();
|
||||
unsigned weekday(unsigned year, unsigned month, unsigned day);
|
||||
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 mmio_read (unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
uint8 mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
|
||||
void serialize(serializer&);
|
||||
SRTC();
|
||||
|
||||
private:
|
||||
static const unsigned months[12];
|
||||
enum RTC_Mode { RTCM_Ready, RTCM_Command, RTCM_Read, RTCM_Write } rtc_mode;
|
||||
enum RtcMode { RtcReady, RtcCommand, RtcRead, RtcWrite };
|
||||
unsigned rtc_mode;
|
||||
signed rtc_index;
|
||||
|
||||
void update_time();
|
||||
unsigned weekday(unsigned year, unsigned month, unsigned day);
|
||||
};
|
||||
|
||||
extern SRTC srtc;
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifdef ST010_CPP
|
||||
|
||||
void ST010::serialize(serializer &s) {
|
||||
s.array(ram);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -6,8 +6,17 @@ namespace SNES {
|
||||
ST010 st010;
|
||||
|
||||
#include "st010_data.hpp"
|
||||
#include "serialization.cpp"
|
||||
#include "st010_op.cpp"
|
||||
|
||||
void ST010::init() {
|
||||
}
|
||||
|
||||
void ST010::enable() {
|
||||
bus.map(Bus::MapDirect, 0x68, 0x6f, 0x0000, 0x0fff, *this);
|
||||
bus.map(Bus::MapDirect, 0xe8, 0xef, 0x0000, 0x0fff, *this);
|
||||
}
|
||||
|
||||
int16 ST010::sin(int16 theta) {
|
||||
return sin_table[(theta >> 8) & 0xff];
|
||||
}
|
||||
@@ -37,25 +46,19 @@ void ST010::writeb(uint16 addr, uint8 data) {
|
||||
}
|
||||
|
||||
void ST010::writew(uint16 addr, uint16 data) {
|
||||
writeb(addr + 0, data);
|
||||
writeb(addr + 0, data >> 0);
|
||||
writeb(addr + 1, data >> 8);
|
||||
}
|
||||
|
||||
void ST010::writed(uint16 addr, uint32 data) {
|
||||
writeb(addr + 0, data);
|
||||
writeb(addr + 1, data >> 8);
|
||||
writeb(addr + 0, data >> 0);
|
||||
writeb(addr + 1, data >> 8);
|
||||
writeb(addr + 2, data >> 16);
|
||||
writeb(addr + 3, data >> 24);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void ST010::init() {
|
||||
}
|
||||
|
||||
void ST010::enable() {
|
||||
}
|
||||
|
||||
void ST010::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
@@ -5,8 +5,10 @@ public:
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 read (unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
void serialize(serializer&);
|
||||
|
||||
private:
|
||||
uint8 ram[0x1000];
|
||||
@@ -14,11 +16,11 @@ private:
|
||||
static const int16 mode7_scale[176];
|
||||
static const uint8 arctan[32][32];
|
||||
|
||||
//interfaces to sin table
|
||||
//interfaces to sin table
|
||||
int16 sin(int16 theta);
|
||||
int16 cos(int16 theta);
|
||||
|
||||
//interfaces to ram buffer
|
||||
//interfaces to ram buffer
|
||||
uint8 readb (uint16 addr);
|
||||
uint16 readw (uint16 addr);
|
||||
uint32 readd (uint16 addr);
|
||||
@@ -26,7 +28,7 @@ private:
|
||||
void writew(uint16 addr, uint16 data);
|
||||
void writed(uint16 addr, uint32 data);
|
||||
|
||||
//opcodes
|
||||
//opcodes
|
||||
void op_01();
|
||||
void op_02();
|
||||
void op_03();
|
||||
|
||||
+67
-67
@@ -35,26 +35,26 @@ void ST010::op_01(int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &quadrant, int
|
||||
//
|
||||
|
||||
void ST010::op_01() {
|
||||
int16 x0 = readw(0x0000);
|
||||
int16 y0 = readw(0x0002);
|
||||
int16 x1, y1, quadrant, theta;
|
||||
int16 x0 = readw(0x0000);
|
||||
int16 y0 = readw(0x0002);
|
||||
int16 x1, y1, quadrant, theta;
|
||||
|
||||
op_01(x0, y0, x1, y1, quadrant, theta);
|
||||
|
||||
writew(0x0000, x1);
|
||||
writew(0x0002, y1);
|
||||
writew(0x0004, quadrant);
|
||||
//writew(0x0006, y0); //Overload's docs note this write occurs, SNES9x disagrees
|
||||
//writew(0x0006, y0); //Overload's docs note this write occurs, SNES9x disagrees
|
||||
writew(0x0010, theta);
|
||||
}
|
||||
|
||||
void ST010::op_02() {
|
||||
int16 positions = readw(0x0024);
|
||||
uint16 *places = (uint16*)(ram + 0x0040);
|
||||
uint16 *drivers = (uint16*)(ram + 0x0080);
|
||||
int16 positions = readw(0x0024);
|
||||
uint16 *places = (uint16*)(ram + 0x0040);
|
||||
uint16 *drivers = (uint16*)(ram + 0x0080);
|
||||
|
||||
bool sorted;
|
||||
uint16 temp;
|
||||
bool sorted;
|
||||
uint16 temp;
|
||||
if(positions > 1) {
|
||||
do {
|
||||
sorted = true;
|
||||
@@ -77,10 +77,10 @@ uint16 temp;
|
||||
}
|
||||
|
||||
void ST010::op_03() {
|
||||
int16 x0 = readw(0x0000);
|
||||
int16 y0 = readw(0x0002);
|
||||
int16 multiplier = readw(0x0004);
|
||||
int32 x1, y1;
|
||||
int16 x0 = readw(0x0000);
|
||||
int16 y0 = readw(0x0002);
|
||||
int16 multiplier = readw(0x0004);
|
||||
int32 x1, y1;
|
||||
|
||||
x1 = x0 * multiplier << 1;
|
||||
y1 = y0 * multiplier << 1;
|
||||
@@ -90,121 +90,121 @@ int32 x1, y1;
|
||||
}
|
||||
|
||||
void ST010::op_04() {
|
||||
int16 x = readw(0x0000);
|
||||
int16 y = readw(0x0002);
|
||||
int16 square;
|
||||
//calculate the vector length of (x,y)
|
||||
int16 x = readw(0x0000);
|
||||
int16 y = readw(0x0002);
|
||||
int16 square;
|
||||
//calculate the vector length of (x,y)
|
||||
square = (int16)sqrt((double)(y * y + x * x));
|
||||
|
||||
writew(0x0010, square);
|
||||
}
|
||||
|
||||
void ST010::op_05() {
|
||||
int32 dx, dy;
|
||||
int16 a1, b1, c1;
|
||||
uint16 o1;
|
||||
bool wrap = false;
|
||||
int32 dx, dy;
|
||||
int16 a1, b1, c1;
|
||||
uint16 o1;
|
||||
bool wrap = false;
|
||||
|
||||
//target (x,y) coordinates
|
||||
int16 ypos_max = readw(0x00c0);
|
||||
int16 xpos_max = readw(0x00c2);
|
||||
//target (x,y) coordinates
|
||||
int16 ypos_max = readw(0x00c0);
|
||||
int16 xpos_max = readw(0x00c2);
|
||||
|
||||
//current coordinates and direction
|
||||
int32 ypos = readd(0x00c4);
|
||||
int32 xpos = readd(0x00c8);
|
||||
uint16 rot = readw(0x00cc);
|
||||
//current coordinates and direction
|
||||
int32 ypos = readd(0x00c4);
|
||||
int32 xpos = readd(0x00c8);
|
||||
uint16 rot = readw(0x00cc);
|
||||
|
||||
//physics
|
||||
uint16 speed = readw(0x00d4);
|
||||
uint16 accel = readw(0x00d6);
|
||||
uint16 speed_max = readw(0x00d8);
|
||||
//physics
|
||||
uint16 speed = readw(0x00d4);
|
||||
uint16 accel = readw(0x00d6);
|
||||
uint16 speed_max = readw(0x00d8);
|
||||
|
||||
//special condition acknowledgement
|
||||
int16 system = readw(0x00da);
|
||||
int16 flags = readw(0x00dc);
|
||||
//special condition acknowledgement
|
||||
int16 system = readw(0x00da);
|
||||
int16 flags = readw(0x00dc);
|
||||
|
||||
//new target coordinates
|
||||
int16 ypos_new = readw(0x00de);
|
||||
int16 xpos_new = readw(0x00e0);
|
||||
//new target coordinates
|
||||
int16 ypos_new = readw(0x00de);
|
||||
int16 xpos_new = readw(0x00e0);
|
||||
|
||||
//mask upper bit
|
||||
//mask upper bit
|
||||
xpos_new &= 0x7fff;
|
||||
|
||||
//get the current distance
|
||||
//get the current distance
|
||||
dx = xpos_max - (xpos >> 16);
|
||||
dy = ypos_max - (ypos >> 16);
|
||||
|
||||
//quirk: clear and move in9
|
||||
//quirk: clear and move in9
|
||||
writew(0x00d2, 0xffff);
|
||||
writew(0x00da, 0x0000);
|
||||
|
||||
//grab the target angle
|
||||
//grab the target angle
|
||||
op_01(dy, dx, a1, b1, c1, (int16&)o1);
|
||||
|
||||
//check for wrapping
|
||||
//check for wrapping
|
||||
if(abs(o1 - rot) > 0x8000) {
|
||||
o1 += 0x8000;
|
||||
rot += 0x8000;
|
||||
wrap = true;
|
||||
}
|
||||
|
||||
uint16 old_speed = speed;
|
||||
uint16 old_speed = speed;
|
||||
|
||||
//special case
|
||||
//special case
|
||||
if(abs(o1 - rot) == 0x8000) {
|
||||
speed = 0x100;
|
||||
}
|
||||
|
||||
//slow down for sharp curves
|
||||
//slow down for sharp curves
|
||||
else if(abs(o1 - rot) >= 0x1000) {
|
||||
uint32 slow = abs(o1 - rot);
|
||||
slow >>= 4; //scaling
|
||||
slow >>= 4; //scaling
|
||||
speed -= slow;
|
||||
}
|
||||
|
||||
//otherwise accelerate
|
||||
//otherwise accelerate
|
||||
else {
|
||||
speed += accel;
|
||||
if(speed > speed_max) {
|
||||
speed = speed_max; //clip speed
|
||||
speed = speed_max; //clip speed
|
||||
}
|
||||
}
|
||||
|
||||
//prevent negative/positive overflow
|
||||
//prevent negative/positive overflow
|
||||
if(abs(old_speed - speed) > 0x8000) {
|
||||
if(old_speed < speed) { speed = 0; }
|
||||
else speed = 0xff00;
|
||||
}
|
||||
|
||||
//adjust direction by so many degrees
|
||||
//be careful of negative adjustments
|
||||
//adjust direction by so many degrees
|
||||
//be careful of negative adjustments
|
||||
if((o1 > rot && (o1 - rot) > 0x80) || (o1 < rot && (rot - o1) >= 0x80)) {
|
||||
if(o1 < rot) { rot -= 0x280; }
|
||||
else if(o1 > rot) { rot += 0x280; }
|
||||
}
|
||||
|
||||
//turn of wrapping
|
||||
//turn off wrapping
|
||||
if(wrap) { rot -= 0x8000; }
|
||||
|
||||
//now check the distances (store for later)
|
||||
//now check the distances (store for later)
|
||||
dx = (xpos_max << 16) - xpos;
|
||||
dy = (ypos_max << 16) - ypos;
|
||||
dx >>= 16;
|
||||
dy >>= 16;
|
||||
|
||||
//if we're in so many units of the target, signal it
|
||||
//if we're in so many units of the target, signal it
|
||||
if((system && (dy <= 6 && dy >= -8) && (dx <= 126 && dx >= -128)) || (!system && (dx <= 6 && dx >= -8) && (dy <= 126 && dy >= -128))) {
|
||||
//announce our new destination and flag it
|
||||
//announce our new destination and flag it
|
||||
xpos_max = xpos_new & 0x7fff;
|
||||
ypos_max = ypos_new;
|
||||
flags |= 0x08;
|
||||
}
|
||||
|
||||
//update position
|
||||
//update position
|
||||
xpos -= (cos(rot) * 0x400 >> 15) * (speed >> 8) << 1;
|
||||
ypos -= (sin(rot) * 0x400 >> 15) * (speed >> 8) << 1;
|
||||
|
||||
//quirk: mask upper byte
|
||||
//quirk: mask upper byte
|
||||
xpos &= 0x1fffffff;
|
||||
ypos &= 0x1fffffff;
|
||||
|
||||
@@ -218,9 +218,9 @@ uint16 old_speed = speed;
|
||||
}
|
||||
|
||||
void ST010::op_06() {
|
||||
int16 multiplicand = readw(0x0000);
|
||||
int16 multiplier = readw(0x0002);
|
||||
int32 product;
|
||||
int16 multiplicand = readw(0x0000);
|
||||
int16 multiplier = readw(0x0002);
|
||||
int32 product;
|
||||
|
||||
product = multiplicand * multiplier << 1;
|
||||
|
||||
@@ -228,9 +228,9 @@ int32 product;
|
||||
}
|
||||
|
||||
void ST010::op_07() {
|
||||
int16 theta = readw(0x0000);
|
||||
int16 theta = readw(0x0000);
|
||||
|
||||
int16 data;
|
||||
int16 data;
|
||||
for(int i = 0, offset = 0; i < 176; i++) {
|
||||
data = mode7_scale[i] * cos(theta) >> 15;
|
||||
writew(0x00f0 + offset, data);
|
||||
@@ -246,10 +246,10 @@ int16 data;
|
||||
}
|
||||
|
||||
void ST010::op_08() {
|
||||
int16 x0 = readw(0x0000);
|
||||
int16 y0 = readw(0x0002);
|
||||
int16 theta = readw(0x0004);
|
||||
int16 x1, y1;
|
||||
int16 x0 = readw(0x0000);
|
||||
int16 y0 = readw(0x0002);
|
||||
int16 theta = readw(0x0004);
|
||||
int16 x1, y1;
|
||||
|
||||
x1 = (y0 * sin(theta) >> 15) + (x0 * cos(theta) >> 15);
|
||||
y1 = (y0 * cos(theta) >> 15) - (x0 * sin(theta) >> 15);
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#include <../base.hpp>
|
||||
|
||||
#define ST011_CPP
|
||||
namespace SNES {
|
||||
|
||||
ST011 st011;
|
||||
|
||||
void ST011::init() {
|
||||
}
|
||||
|
||||
void ST011::enable() {
|
||||
}
|
||||
|
||||
void ST011::power() {
|
||||
}
|
||||
|
||||
void ST011::reset() {
|
||||
}
|
||||
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
class ST011 {
|
||||
public:
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
};
|
||||
|
||||
extern ST011 st011;
|
||||
@@ -0,0 +1,124 @@
|
||||
#include <../base.hpp>
|
||||
|
||||
#define ST018_CPP
|
||||
namespace SNES {
|
||||
|
||||
ST018 st018;
|
||||
|
||||
uint8 ST018::mmio_read(unsigned addr) {
|
||||
addr &= 0xffff;
|
||||
if(addr == 0x3800) return regs.r3800;
|
||||
if(addr == 0x3804) return regs.r3804;
|
||||
return cpu.regs.mdr;
|
||||
}
|
||||
|
||||
void ST018::mmio_write(unsigned addr, uint8 data) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr == 0x3802) {
|
||||
switch(regs.mode) {
|
||||
case Waiting: {
|
||||
switch(data) {
|
||||
case 0x01: regs.r3800 = regs.r3800_01; break;
|
||||
case 0xaa: op_board_upload(); break;
|
||||
case 0xb2: op_b2(); break;
|
||||
case 0xb3: op_b3(); break;
|
||||
case 0xb4: op_b4(); break;
|
||||
case 0xb5: op_b5(); break;
|
||||
case 0xf1: op_query_chip(); break;
|
||||
case 0xf2: op_query_chip(); break;
|
||||
default: fprintf(stdout, "* ST018 w3802::%.2x\n", data); break;
|
||||
}
|
||||
} return;
|
||||
|
||||
case BoardUpload: {
|
||||
op_board_upload(data);
|
||||
} return;
|
||||
}
|
||||
}
|
||||
|
||||
if(addr == 0x3804) {
|
||||
regs.w3804 <<= 8;
|
||||
regs.w3804 |= data;
|
||||
regs.w3804 &= 0xffffff;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ST018::init() {
|
||||
}
|
||||
|
||||
void ST018::enable() {
|
||||
for(unsigned i = 0x3800; i <= 0x38ff; i++) memory::mmio.map(i, *this);
|
||||
}
|
||||
|
||||
void ST018::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void ST018::reset() {
|
||||
regs.mode = Waiting;
|
||||
regs.r3800 = 0x00;
|
||||
regs.r3804 = 0x85;
|
||||
regs.w3804 = 0;
|
||||
for(unsigned i = 0; i < 97; i++) board[i] = 0;
|
||||
}
|
||||
|
||||
//=============
|
||||
//ST018 opcodes
|
||||
//=============
|
||||
|
||||
void ST018::op_board_upload() {
|
||||
regs.mode = BoardUpload;
|
||||
regs.counter = 0;
|
||||
regs.r3800 = 0xe0;
|
||||
}
|
||||
|
||||
void ST018::op_board_upload(uint8 data) {
|
||||
board[regs.counter] = data;
|
||||
regs.r3800 = 96 - regs.counter;
|
||||
regs.counter++;
|
||||
if(regs.counter >= 97) {
|
||||
regs.mode = Waiting;
|
||||
#if 0
|
||||
for(unsigned y = 0; y < 9; y++) {
|
||||
for(unsigned x = 0; x < 9; x++) {
|
||||
fprintf(stdout, "%.2x ", board[y * 9 + x]);
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
for(unsigned n = 0; n < 16; n++) fprintf(stdout, "%.2x ", board[81 + n]);
|
||||
fprintf(stdout, "\n\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void ST018::op_b2() {
|
||||
fprintf(stdout, "* ST018 w3802::b2\n");
|
||||
regs.r3800 = 0xe0;
|
||||
regs.r3800_01 = 0; //unknown
|
||||
}
|
||||
|
||||
void ST018::op_b3() {
|
||||
fprintf(stdout, "* ST018 w3802::b3\n");
|
||||
regs.r3800 = 0xe0;
|
||||
regs.r3800_01 = 1; //0 = player lost?
|
||||
}
|
||||
|
||||
void ST018::op_b4() {
|
||||
fprintf(stdout, "* ST018 w3802::b4\n");
|
||||
regs.r3800 = 0xe0;
|
||||
regs.r3800_01 = 1; //0 = player won?
|
||||
}
|
||||
|
||||
void ST018::op_b5() {
|
||||
fprintf(stdout, "* ST018 w3802::b5\n");
|
||||
regs.r3800 = 0xe0;
|
||||
regs.r3800_01 = 0; //1 = move will result in checkmate?
|
||||
}
|
||||
|
||||
void ST018::op_query_chip() {
|
||||
regs.r3800 = 0x00;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
class ST018 : public MMIO {
|
||||
public:
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
|
||||
enum mode_t { Waiting, BoardUpload };
|
||||
struct regs_t {
|
||||
mode_t mode;
|
||||
|
||||
uint8 r3800;
|
||||
uint8 r3800_01;
|
||||
uint8 r3804;
|
||||
|
||||
unsigned w3804;
|
||||
unsigned counter;
|
||||
} regs;
|
||||
|
||||
enum PieceID {
|
||||
Pawn = 0x00, //foot soldier
|
||||
Lance = 0x04, //incense chariot
|
||||
Knight = 0x08, //cassia horse
|
||||
Silver = 0x0c, //silver general
|
||||
Gold = 0x10, //gold general
|
||||
Rook = 0x14, //flying chariot
|
||||
Bishop = 0x18, //angle mover
|
||||
King = 0x1c, //king
|
||||
};
|
||||
|
||||
enum PieceFlag {
|
||||
PlayerA = 0x20,
|
||||
PlayerB = 0x40,
|
||||
};
|
||||
|
||||
uint8 board[9 * 9 + 16];
|
||||
|
||||
private:
|
||||
void op_board_upload();
|
||||
void op_board_upload(uint8 data);
|
||||
void op_b2();
|
||||
void op_b3();
|
||||
void op_b4();
|
||||
void op_b5();
|
||||
void op_query_chip();
|
||||
};
|
||||
|
||||
extern ST018 st018;
|
||||
@@ -3,11 +3,11 @@
|
||||
SuperFXBus superfxbus;
|
||||
|
||||
namespace memory {
|
||||
static SuperFXGSUROM gsurom;
|
||||
static SuperFXGSURAM gsuram;
|
||||
static SuperFXCPUROM fxrom;
|
||||
static SuperFXCPURAM fxram;
|
||||
};
|
||||
SuperFXGSUROM gsurom;
|
||||
SuperFXGSURAM gsuram;
|
||||
SuperFXCPUROM fxrom;
|
||||
SuperFXCPURAM fxram;
|
||||
}
|
||||
|
||||
void SuperFXBus::init() {
|
||||
map(MapDirect, 0x00, 0xff, 0x0000, 0xffff, memory::memory_unmapped);
|
||||
@@ -33,25 +33,39 @@ unsigned SuperFXGSUROM::size() const {
|
||||
return memory::cartrom.size();
|
||||
}
|
||||
|
||||
uint8_t SuperFXGSUROM::read(unsigned addr) {
|
||||
while(!superfx.regs.scmr.ron) superfx.add_clocks(2);
|
||||
uint8 SuperFXGSUROM::read(unsigned addr) {
|
||||
while(!superfx.regs.scmr.ron && scheduler.sync != Scheduler::SyncAll) {
|
||||
superfx.add_clocks(6);
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
return memory::cartrom.read(addr);
|
||||
}
|
||||
|
||||
void SuperFXGSUROM::write(unsigned addr, uint8_t data) {
|
||||
void SuperFXGSUROM::write(unsigned addr, uint8 data) {
|
||||
while(!superfx.regs.scmr.ron && scheduler.sync != Scheduler::SyncAll) {
|
||||
superfx.add_clocks(6);
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
memory::cartrom.write(addr, data);
|
||||
}
|
||||
|
||||
unsigned SuperFXGSURAM::size() const {
|
||||
return memory::cartram.size();
|
||||
}
|
||||
|
||||
uint8_t SuperFXGSURAM::read(unsigned addr) {
|
||||
while(!superfx.regs.scmr.ran) superfx.add_clocks(2);
|
||||
uint8 SuperFXGSURAM::read(unsigned addr) {
|
||||
while(!superfx.regs.scmr.ran && scheduler.sync != Scheduler::SyncAll) {
|
||||
superfx.add_clocks(6);
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
return memory::cartram.read(addr);
|
||||
}
|
||||
|
||||
void SuperFXGSURAM::write(unsigned addr, uint8_t data) {
|
||||
while(!superfx.regs.scmr.ran) superfx.add_clocks(2);
|
||||
void SuperFXGSURAM::write(unsigned addr, uint8 data) {
|
||||
while(!superfx.regs.scmr.ran && scheduler.sync != Scheduler::SyncAll) {
|
||||
superfx.add_clocks(6);
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
memory::cartram.write(addr, data);
|
||||
}
|
||||
|
||||
@@ -61,7 +75,7 @@ unsigned SuperFXCPUROM::size() const {
|
||||
return memory::cartrom.size();
|
||||
}
|
||||
|
||||
uint8_t SuperFXCPUROM::read(unsigned addr) {
|
||||
uint8 SuperFXCPUROM::read(unsigned addr) {
|
||||
if(superfx.regs.sfr.g && superfx.regs.scmr.ron) {
|
||||
static const uint8_t data[16] = {
|
||||
0x00, 0x01, 0x00, 0x01, 0x04, 0x01, 0x00, 0x01,
|
||||
@@ -72,7 +86,7 @@ uint8_t SuperFXCPUROM::read(unsigned addr) {
|
||||
return memory::cartrom.read(addr);
|
||||
}
|
||||
|
||||
void SuperFXCPUROM::write(unsigned addr, uint8_t data) {
|
||||
void SuperFXCPUROM::write(unsigned addr, uint8 data) {
|
||||
memory::cartrom.write(addr, data);
|
||||
}
|
||||
|
||||
@@ -80,12 +94,12 @@ unsigned SuperFXCPURAM::size() const {
|
||||
return memory::cartram.size();
|
||||
}
|
||||
|
||||
uint8_t SuperFXCPURAM::read(unsigned addr) {
|
||||
uint8 SuperFXCPURAM::read(unsigned addr) {
|
||||
if(superfx.regs.sfr.g && superfx.regs.scmr.ran) return cpu.regs.mdr;
|
||||
return memory::cartram.read(addr);
|
||||
}
|
||||
|
||||
void SuperFXCPURAM::write(unsigned addr, uint8_t data) {
|
||||
void SuperFXCPURAM::write(unsigned addr, uint8 data) {
|
||||
memory::cartram.write(addr, data);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,24 +4,31 @@ struct SuperFXBus : Bus {
|
||||
|
||||
struct SuperFXGSUROM : Memory {
|
||||
unsigned size() const;
|
||||
uint8_t read(unsigned);
|
||||
void write(unsigned, uint8_t);
|
||||
uint8 read(unsigned);
|
||||
void write(unsigned, uint8);
|
||||
};
|
||||
|
||||
struct SuperFXGSURAM : Memory {
|
||||
unsigned size() const;
|
||||
uint8_t read(unsigned);
|
||||
void write(unsigned, uint8_t);
|
||||
uint8 read(unsigned);
|
||||
void write(unsigned, uint8);
|
||||
};
|
||||
|
||||
struct SuperFXCPUROM : Memory {
|
||||
unsigned size() const;
|
||||
uint8_t read(unsigned);
|
||||
void write(unsigned, uint8_t);
|
||||
uint8 read(unsigned);
|
||||
void write(unsigned, uint8);
|
||||
};
|
||||
|
||||
struct SuperFXCPURAM : Memory {
|
||||
unsigned size() const;
|
||||
uint8_t read(unsigned);
|
||||
void write(unsigned, uint8_t);
|
||||
uint8 read(unsigned);
|
||||
void write(unsigned, uint8);
|
||||
};
|
||||
|
||||
namespace memory {
|
||||
extern SuperFXGSUROM gsurom;
|
||||
extern SuperFXGSURAM gsuram;
|
||||
extern SuperFXCPUROM fxrom;
|
||||
extern SuperFXCPURAM fxram;
|
||||
}
|
||||
@@ -3,28 +3,14 @@
|
||||
#include "opcodes.cpp"
|
||||
#include "opcode_table.cpp"
|
||||
|
||||
void SuperFX::exec_opcode() {
|
||||
#if 0
|
||||
if(!fp) fp = fopen("sfxtrace.log", "wb");
|
||||
char t[4096];
|
||||
disassemble_opcode(t);
|
||||
fprintf(fp, "%s ", t);
|
||||
for(unsigned i = 0; i < 16; i++) fprintf(fp, "r%u:%.4x ", i, (uint16_t)regs.r[i]);
|
||||
fprintf(fp, "\n");
|
||||
#endif
|
||||
|
||||
(this->*opcode_table[(regs.sfr & 0x0300) + peekpipe()])();
|
||||
if(r15_modified == false) regs.r[15]++;
|
||||
}
|
||||
|
||||
uint8_t SuperFX::color(uint8_t source) {
|
||||
uint8 SuperFX::color(uint8 source) {
|
||||
if(regs.por.highnibble) return (regs.colr & 0xf0) | (source >> 4);
|
||||
if(regs.por.freezehigh) return (regs.colr & 0xf0) | (source & 0x0f);
|
||||
return source;
|
||||
}
|
||||
|
||||
void SuperFX::plot(uint8_t x, uint8_t y) {
|
||||
uint8_t color = regs.colr;
|
||||
void SuperFX::plot(uint8 x, uint8 y) {
|
||||
uint8 color = regs.colr;
|
||||
|
||||
if(regs.por.dither && regs.scmr.md != 3) {
|
||||
if((x ^ y) & 1) color >>= 4;
|
||||
@@ -43,7 +29,7 @@ void SuperFX::plot(uint8_t x, uint8_t y) {
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t offset = (y << 5) + (x >> 3);
|
||||
uint16 offset = (y << 5) + (x >> 3);
|
||||
if(offset != pixelcache[0].offset) {
|
||||
pixelcache_flush(pixelcache[1]);
|
||||
pixelcache[1] = pixelcache[0];
|
||||
@@ -61,7 +47,7 @@ void SuperFX::plot(uint8_t x, uint8_t y) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t SuperFX::rpix(uint8_t x, uint8_t y) {
|
||||
uint8 SuperFX::rpix(uint8 x, uint8 y) {
|
||||
pixelcache_flush(pixelcache[1]);
|
||||
pixelcache_flush(pixelcache[0]);
|
||||
|
||||
@@ -74,7 +60,7 @@ uint8_t SuperFX::rpix(uint8_t x, uint8_t y) {
|
||||
}
|
||||
unsigned bpp = 2 << (regs.scmr.md - (regs.scmr.md >> 1)); // = [regs.scmr.md]{ 2, 4, 4, 8 };
|
||||
unsigned addr = 0x700000 + (cn * (bpp << 3)) + (regs.scbr << 10) + ((y & 0x07) * 2);
|
||||
uint8_t data = 0x00;
|
||||
uint8 data = 0x00;
|
||||
x = (x & 7) ^ 7;
|
||||
|
||||
for(unsigned n = 0; n < bpp; n++) {
|
||||
@@ -89,8 +75,8 @@ uint8_t SuperFX::rpix(uint8_t x, uint8_t y) {
|
||||
void SuperFX::pixelcache_flush(pixelcache_t &cache) {
|
||||
if(cache.bitpend == 0x00) return;
|
||||
|
||||
uint8_t x = cache.offset << 3;
|
||||
uint8_t y = cache.offset >> 5;
|
||||
uint8 x = cache.offset << 3;
|
||||
uint8 y = cache.offset >> 5;
|
||||
|
||||
unsigned cn; //character number
|
||||
switch(regs.por.obj ? 3 : regs.scmr.ht) {
|
||||
@@ -104,7 +90,7 @@ void SuperFX::pixelcache_flush(pixelcache_t &cache) {
|
||||
|
||||
for(unsigned n = 0; n < bpp; n++) {
|
||||
unsigned byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 };
|
||||
uint8_t data = 0x00;
|
||||
uint8 data = 0x00;
|
||||
for(unsigned x = 0; x < 8; x++) data |= ((cache.data[x] >> n) & 1) << x;
|
||||
if(cache.bitpend != 0xff) {
|
||||
add_clocks(memory_access_speed);
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
#include "registers.hpp"
|
||||
|
||||
void exec_opcode();
|
||||
uint8_t color(uint8_t source);
|
||||
void plot(uint8_t x, uint8_t y);
|
||||
uint8_t rpix(uint8_t x, uint8_t y);
|
||||
uint8 color(uint8 source);
|
||||
void plot(uint8 x, uint8 y);
|
||||
uint8 rpix(uint8 x, uint8 y);
|
||||
void pixelcache_flush(pixelcache_t &cache);
|
||||
|
||||
void (SuperFX::*opcode_table[1024])();
|
||||
|
||||
@@ -47,66 +47,66 @@ void SuperFX::op_rol() {
|
||||
|
||||
//$05 bra e
|
||||
void SuperFX::op_bra() {
|
||||
regs.r[15] += (int8_t)pipe();
|
||||
regs.r[15] += (int8)pipe();
|
||||
}
|
||||
|
||||
//$06 blt e
|
||||
void SuperFX::op_blt() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if((regs.sfr.s ^ regs.sfr.ov) == 0) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$07 bge e
|
||||
void SuperFX::op_bge() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if((regs.sfr.s ^ regs.sfr.ov) == 1) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$08 bne e
|
||||
void SuperFX::op_bne() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if(regs.sfr.z == 0) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$09 beq e
|
||||
void SuperFX::op_beq() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if(regs.sfr.z == 1) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$0a bpl e
|
||||
void SuperFX::op_bpl() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if(regs.sfr.s == 0) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$0b bmi e
|
||||
void SuperFX::op_bmi() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if(regs.sfr.s == 1) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$0c bcc e
|
||||
void SuperFX::op_bcc() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if(regs.sfr.cy == 0) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$0d bcs e
|
||||
void SuperFX::op_bcs() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if(regs.sfr.cy == 1) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$0e bvc e
|
||||
void SuperFX::op_bvc() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if(regs.sfr.ov == 0) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$0f bvs e
|
||||
void SuperFX::op_bvs() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if(regs.sfr.ov == 1) regs.r[15] += e;
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ void SuperFX::op_bvs() {
|
||||
//$10-1f(b1): move rN
|
||||
template<int n> void SuperFX::op_to_r() {
|
||||
if(regs.sfr.b == 0) {
|
||||
regs.dreg = ®s.r[n];
|
||||
regs.dreg = n;
|
||||
} else {
|
||||
regs.r[n] = regs.sr();
|
||||
regs.reset();
|
||||
@@ -123,8 +123,8 @@ template<int n> void SuperFX::op_to_r() {
|
||||
|
||||
//$20-2f: with rN
|
||||
template<int n> void SuperFX::op_with_r() {
|
||||
regs.sreg = ®s.r[n];
|
||||
regs.dreg = ®s.r[n];
|
||||
regs.sreg = n;
|
||||
regs.dreg = n;
|
||||
regs.sfr.b = 1;
|
||||
}
|
||||
|
||||
@@ -362,7 +362,7 @@ template<int n> void SuperFX::op_bic_i() {
|
||||
|
||||
//$80-8f(alt0): mult rN
|
||||
template<int n> void SuperFX::op_mult_r() {
|
||||
regs.dr() = (int8_t)regs.sr() * (int8_t)regs.r[n];
|
||||
regs.dr() = (int8)regs.sr() * (int8)regs.r[n];
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
@@ -371,7 +371,7 @@ template<int n> void SuperFX::op_mult_r() {
|
||||
|
||||
//$80-8f(alt1): umult rN
|
||||
template<int n> void SuperFX::op_umult_r() {
|
||||
regs.dr() = (uint8_t)regs.sr() * (uint8_t)regs.r[n];
|
||||
regs.dr() = (uint8)regs.sr() * (uint8)regs.r[n];
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
@@ -380,7 +380,7 @@ template<int n> void SuperFX::op_umult_r() {
|
||||
|
||||
//$80-8f(alt2): mult #N
|
||||
template<int n> void SuperFX::op_mult_i() {
|
||||
regs.dr() = (int8_t)regs.sr() * (int8_t)n;
|
||||
regs.dr() = (int8)regs.sr() * (int8)n;
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
@@ -389,7 +389,7 @@ template<int n> void SuperFX::op_mult_i() {
|
||||
|
||||
//$80-8f(alt3): umult #N
|
||||
template<int n> void SuperFX::op_umult_i() {
|
||||
regs.dr() = (uint8_t)regs.sr() * (uint8_t)n;
|
||||
regs.dr() = (uint8)regs.sr() * (uint8)n;
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
@@ -411,7 +411,7 @@ template<int n> void SuperFX::op_link() {
|
||||
|
||||
//$95: sex
|
||||
void SuperFX::op_sex() {
|
||||
regs.dr() = (int8_t)regs.sr();
|
||||
regs.dr() = (int8)regs.sr();
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
@@ -453,7 +453,7 @@ template<int n> void SuperFX::op_jmp_r() {
|
||||
|
||||
//$98-9d(alt1): ljmp rN
|
||||
template<int n> void SuperFX::op_ljmp_r() {
|
||||
regs.pbr = regs.r[n];
|
||||
regs.pbr = regs.r[n] & 0x7f;
|
||||
regs.r[15] = regs.sr();
|
||||
regs.cbr = regs.r[15] & 0xfff0;
|
||||
cache_flush();
|
||||
@@ -493,7 +493,7 @@ void SuperFX::op_lmult() {
|
||||
|
||||
//$a0-af(alt0): ibt rN,#pp
|
||||
template<int n> void SuperFX::op_ibt_r() {
|
||||
regs.r[n] = (int8_t)pipe();
|
||||
regs.r[n] = (int8)pipe();
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
@@ -519,7 +519,7 @@ template<int n> void SuperFX::op_sms_r() {
|
||||
//$b0-bf(b1): moves rN
|
||||
template<int n> void SuperFX::op_from_r() {
|
||||
if(regs.sfr.b == 0) {
|
||||
regs.sreg = ®s.r[n];
|
||||
regs.sreg = n;
|
||||
} else {
|
||||
regs.dr() = regs.r[n];
|
||||
regs.sfr.ov = (regs.dr() & 0x80);
|
||||
@@ -593,7 +593,7 @@ void SuperFX::op_ramb() {
|
||||
//$df(alt3): romb
|
||||
void SuperFX::op_romb() {
|
||||
rombuffer_sync();
|
||||
regs.rombr = regs.sr();
|
||||
regs.rombr = regs.sr() & 0x7f;
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
@@ -625,7 +625,7 @@ void SuperFX::op_getbl() {
|
||||
|
||||
//$ef(alt3): getbs
|
||||
void SuperFX::op_getbs() {
|
||||
regs.dr() = (int8_t)rombuffer_read();
|
||||
regs.dr() = (int8)rombuffer_read();
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
|
||||
|
||||
//accepts a callback binding so r14 writes can trigger ROM buffering transparently
|
||||
struct reg16_t : noncopyable {
|
||||
uint16_t data;
|
||||
function<void (uint16_t)> on_modify;
|
||||
uint16 data;
|
||||
function<void (uint16)> on_modify;
|
||||
|
||||
inline operator unsigned() const { return data; }
|
||||
inline uint16_t assign(uint16_t i) {
|
||||
inline uint16 assign(uint16 i) {
|
||||
if(on_modify) on_modify(i);
|
||||
else data = i;
|
||||
return data;
|
||||
@@ -47,7 +45,7 @@ struct sfr_t {
|
||||
bool cy; //carry flag
|
||||
bool z; //zero flag
|
||||
|
||||
operator uint16_t() const {
|
||||
operator unsigned() const {
|
||||
return (irq << 15) | (b << 12) | (ih << 11) | (il << 10) | (alt2 << 9) | (alt1 << 8)
|
||||
| (r << 6) | (g << 5) | (ov << 4) | (s << 3) | (cy << 2) | (z << 1);
|
||||
}
|
||||
@@ -75,11 +73,11 @@ struct scmr_t {
|
||||
bool ran;
|
||||
unsigned md;
|
||||
|
||||
operator uint8_t() const {
|
||||
operator unsigned() const {
|
||||
return ((ht >> 1) << 5) | (ron << 4) | (ran << 3) | ((ht & 1) << 2) | (md);
|
||||
}
|
||||
|
||||
scmr_t& operator=(uint8_t data) {
|
||||
scmr_t& operator=(uint8 data) {
|
||||
ht = (bool)(data & 0x20) << 1;
|
||||
ht |= (bool)(data & 0x04) << 0;
|
||||
ron = data & 0x10;
|
||||
@@ -96,11 +94,11 @@ struct por_t {
|
||||
bool dither;
|
||||
bool transparent;
|
||||
|
||||
operator uint8_t() const {
|
||||
operator unsigned() const {
|
||||
return (obj << 4) | (freezehigh << 3) | (highnibble << 2) | (dither << 1) | (transparent);
|
||||
}
|
||||
|
||||
por_t& operator=(uint8_t data) {
|
||||
por_t& operator=(uint8 data) {
|
||||
obj = data & 0x10;
|
||||
freezehigh = data & 0x08;
|
||||
highnibble = data & 0x04;
|
||||
@@ -114,11 +112,11 @@ struct cfgr_t {
|
||||
bool irq;
|
||||
bool ms0;
|
||||
|
||||
operator uint8_t() const {
|
||||
operator unsigned() const {
|
||||
return (irq << 7) | (ms0 << 5);
|
||||
}
|
||||
|
||||
cfgr_t& operator=(uint8_t data) {
|
||||
cfgr_t& operator=(uint8 data) {
|
||||
irq = data & 0x80;
|
||||
ms0 = data & 0x20;
|
||||
return *this;
|
||||
@@ -126,52 +124,52 @@ struct cfgr_t {
|
||||
};
|
||||
|
||||
struct regs_t {
|
||||
uint8_t pipeline;
|
||||
uint16_t ramaddr;
|
||||
uint8 pipeline;
|
||||
uint16 ramaddr;
|
||||
|
||||
reg16_t r[16]; //general purpose registers
|
||||
sfr_t sfr; //status flag register
|
||||
uint8_t pbr; //program bank register
|
||||
uint8_t rombr; //game pack ROM bank register
|
||||
uint8 pbr; //program bank register
|
||||
uint8 rombr; //game pack ROM bank register
|
||||
bool rambr; //game pack RAM bank register
|
||||
uint16_t cbr; //cache base register
|
||||
uint8_t scbr; //screen base register
|
||||
uint16 cbr; //cache base register
|
||||
uint8 scbr; //screen base register
|
||||
scmr_t scmr; //screen mode register
|
||||
uint8_t colr; //color register
|
||||
uint8 colr; //color register
|
||||
por_t por; //plot option register
|
||||
bool bramr; //back-up RAM register
|
||||
uint8_t vcr; //version code register
|
||||
uint8 vcr; //version code register
|
||||
cfgr_t cfgr; //config register
|
||||
bool clsr; //clock select register
|
||||
|
||||
unsigned romcl; //clock ticks until romdr is valid
|
||||
uint8_t romdr; //ROM buffer data register
|
||||
uint8 romdr; //ROM buffer data register
|
||||
|
||||
unsigned ramcl; //clock ticks until ramdr is valid
|
||||
uint16_t ramar; //RAM buffer address register
|
||||
uint8_t ramdr; //RAM buffer data register
|
||||
uint16 ramar; //RAM buffer address register
|
||||
uint8 ramdr; //RAM buffer data register
|
||||
|
||||
reg16_t *sreg, *dreg;
|
||||
reg16_t& sr() { return *sreg; } //source register (from)
|
||||
reg16_t& dr() { return *dreg; } //destination register (to)
|
||||
unsigned sreg, dreg;
|
||||
reg16_t& sr() { return r[sreg]; } //source register (from)
|
||||
reg16_t& dr() { return r[dreg]; } //destination register (to)
|
||||
|
||||
void reset() {
|
||||
sfr.b = 0;
|
||||
sfr.alt1 = 0;
|
||||
sfr.alt2 = 0;
|
||||
|
||||
sreg = &r[0];
|
||||
dreg = &r[0];
|
||||
sreg = 0;
|
||||
dreg = 0;
|
||||
}
|
||||
} regs;
|
||||
|
||||
struct cache_t {
|
||||
uint8_t buffer[512];
|
||||
uint8 buffer[512];
|
||||
bool valid[32];
|
||||
} cache;
|
||||
|
||||
struct pixelcache_t {
|
||||
uint16_t offset;
|
||||
uint8_t bitpend;
|
||||
uint8_t data[8];
|
||||
uint16 offset;
|
||||
uint8 bitpend;
|
||||
uint8 data[8];
|
||||
} pixelcache[2];
|
||||
@@ -1,3 +1,5 @@
|
||||
#ifdef SUPERFX_CPP
|
||||
|
||||
void SuperFX::disassemble_opcode(char *output) {
|
||||
*output = 0;
|
||||
|
||||
@@ -273,3 +275,5 @@ void SuperFX::disassemble_alt3(char *output) {
|
||||
#undef op0
|
||||
#undef op1
|
||||
#undef op2
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,7 @@
|
||||
uint8_t SuperFX::op_read(uint16_t addr) {
|
||||
uint16_t offset = addr - regs.cbr;
|
||||
#ifdef SUPERFX_CPP
|
||||
|
||||
uint8 SuperFX::op_read(uint16 addr) {
|
||||
uint16 offset = addr - regs.cbr;
|
||||
if(offset < 512) {
|
||||
if(cache.valid[offset >> 4] == false) {
|
||||
unsigned dp = offset & 0xfff0;
|
||||
@@ -28,15 +30,15 @@ uint8_t SuperFX::op_read(uint16_t addr) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t SuperFX::peekpipe() {
|
||||
uint8_t result = regs.pipeline;
|
||||
uint8 SuperFX::peekpipe() {
|
||||
uint8 result = regs.pipeline;
|
||||
regs.pipeline = op_read(regs.r[15]);
|
||||
r15_modified = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t SuperFX::pipe() {
|
||||
uint8_t result = regs.pipeline;
|
||||
uint8 SuperFX::pipe() {
|
||||
uint8 result = regs.pipeline;
|
||||
regs.pipeline = op_read(++regs.r[15]);
|
||||
r15_modified = false;
|
||||
return result;
|
||||
@@ -46,12 +48,12 @@ void SuperFX::cache_flush() {
|
||||
for(unsigned n = 0; n < 32; n++) cache.valid[n] = false;
|
||||
}
|
||||
|
||||
uint8_t SuperFX::cache_mmio_read(uint16_t addr) {
|
||||
uint8 SuperFX::cache_mmio_read(uint16 addr) {
|
||||
addr = (addr + regs.cbr) & 511;
|
||||
return cache.buffer[addr];
|
||||
}
|
||||
|
||||
void SuperFX::cache_mmio_write(uint16_t addr, uint8_t data) {
|
||||
void SuperFX::cache_mmio_write(uint16 addr, uint8 data) {
|
||||
addr = (addr + regs.cbr) & 511;
|
||||
cache.buffer[addr] = data;
|
||||
if((addr & 15) == 15) cache.valid[addr >> 4] = true;
|
||||
@@ -65,3 +67,5 @@ void SuperFX::memory_reset() {
|
||||
pixelcache[n].bitpend = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,9 +1,9 @@
|
||||
uint8_t op_read(uint16_t addr);
|
||||
alwaysinline uint8_t peekpipe();
|
||||
alwaysinline uint8_t pipe();
|
||||
uint8 op_read(uint16 addr);
|
||||
alwaysinline uint8 peekpipe();
|
||||
alwaysinline uint8 pipe();
|
||||
|
||||
void cache_flush();
|
||||
uint8_t cache_mmio_read(uint16_t addr);
|
||||
void cache_mmio_write(uint16_t addr, uint8_t data);
|
||||
uint8 cache_mmio_read(uint16 addr);
|
||||
void cache_mmio_write(uint16 addr, uint8 data);
|
||||
|
||||
void memory_reset();
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifdef SUPERFX_CPP
|
||||
|
||||
uint8_t SuperFX::mmio_read(unsigned addr) {
|
||||
uint8 SuperFX::mmio_read(unsigned addr) {
|
||||
scheduler.sync_cpucop();
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr >= 0x3100 && addr <= 0x32ff) {
|
||||
@@ -17,7 +18,7 @@ uint8_t SuperFX::mmio_read(unsigned addr) {
|
||||
}
|
||||
|
||||
case 0x3031: {
|
||||
uint8_t r = regs.sfr >> 8;
|
||||
uint8 r = regs.sfr >> 8;
|
||||
regs.sfr.irq = 0;
|
||||
cpu.regs.irq = 0;
|
||||
return r;
|
||||
@@ -51,7 +52,8 @@ uint8_t SuperFX::mmio_read(unsigned addr) {
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void SuperFX::mmio_write(unsigned addr, uint8_t data) {
|
||||
void SuperFX::mmio_write(unsigned addr, uint8 data) {
|
||||
scheduler.sync_cpucop();
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr >= 0x3100 && addr <= 0x32ff) {
|
||||
@@ -89,13 +91,13 @@ void SuperFX::mmio_write(unsigned addr, uint8_t data) {
|
||||
} break;
|
||||
|
||||
case 0x3034: {
|
||||
regs.pbr = data;
|
||||
regs.pbr = data & 0x7f;
|
||||
cache_flush();
|
||||
} break;
|
||||
|
||||
case 0x3037: {
|
||||
regs.cfgr = data;
|
||||
if(regs.clsr) regs.cfgr.ms0 = 0; //cannot use high-speed multiplication in 21MHz mode
|
||||
update_speed();
|
||||
} break;
|
||||
|
||||
case 0x3038: {
|
||||
@@ -104,9 +106,7 @@ void SuperFX::mmio_write(unsigned addr, uint8_t data) {
|
||||
|
||||
case 0x3039: {
|
||||
regs.clsr = data;
|
||||
if(regs.clsr) regs.cfgr.ms0 = 0; //cannot use high-speed multiplication in 21MHz mode
|
||||
cache_access_speed = (regs.clsr ? config.superfx.fast_cache_speed : config.superfx.slow_cache_speed );
|
||||
memory_access_speed = (regs.clsr ? config.superfx.fast_memory_speed : config.superfx.slow_memory_speed);
|
||||
update_speed();
|
||||
} break;
|
||||
|
||||
case 0x303a: {
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
uint8_t mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8_t data);
|
||||
uint8 mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
@@ -0,0 +1,94 @@
|
||||
#ifdef SUPERFX_CPP
|
||||
|
||||
void SuperFX::serialize(serializer &s) {
|
||||
//superfx.hpp
|
||||
s.integer(clockmode);
|
||||
s.integer(instruction_counter);
|
||||
|
||||
//core/registers.hpp
|
||||
s.integer(regs.pipeline);
|
||||
s.integer(regs.ramaddr);
|
||||
|
||||
s.integer(regs.r[ 0].data);
|
||||
s.integer(regs.r[ 1].data);
|
||||
s.integer(regs.r[ 2].data);
|
||||
s.integer(regs.r[ 3].data);
|
||||
s.integer(regs.r[ 4].data);
|
||||
s.integer(regs.r[ 5].data);
|
||||
s.integer(regs.r[ 6].data);
|
||||
s.integer(regs.r[ 7].data);
|
||||
s.integer(regs.r[ 8].data);
|
||||
s.integer(regs.r[ 9].data);
|
||||
s.integer(regs.r[10].data);
|
||||
s.integer(regs.r[11].data);
|
||||
s.integer(regs.r[12].data);
|
||||
s.integer(regs.r[13].data);
|
||||
s.integer(regs.r[14].data);
|
||||
s.integer(regs.r[15].data);
|
||||
|
||||
s.integer(regs.sfr.irq);
|
||||
s.integer(regs.sfr.b);
|
||||
s.integer(regs.sfr.ih);
|
||||
s.integer(regs.sfr.il);
|
||||
s.integer(regs.sfr.alt2);
|
||||
s.integer(regs.sfr.alt1);
|
||||
s.integer(regs.sfr.r);
|
||||
s.integer(regs.sfr.g);
|
||||
s.integer(regs.sfr.ov);
|
||||
s.integer(regs.sfr.s);
|
||||
s.integer(regs.sfr.cy);
|
||||
s.integer(regs.sfr.z);
|
||||
|
||||
s.integer(regs.pbr);
|
||||
s.integer(regs.rombr);
|
||||
s.integer(regs.rambr);
|
||||
s.integer(regs.cbr);
|
||||
s.integer(regs.scbr);
|
||||
|
||||
s.integer(regs.scmr.ht);
|
||||
s.integer(regs.scmr.ron);
|
||||
s.integer(regs.scmr.ran);
|
||||
s.integer(regs.scmr.md);
|
||||
|
||||
s.integer(regs.colr);
|
||||
|
||||
s.integer(regs.por.obj);
|
||||
s.integer(regs.por.freezehigh);
|
||||
s.integer(regs.por.highnibble);
|
||||
s.integer(regs.por.dither);
|
||||
s.integer(regs.por.transparent);
|
||||
|
||||
s.integer(regs.bramr);
|
||||
s.integer(regs.vcr);
|
||||
|
||||
s.integer(regs.cfgr.irq);
|
||||
s.integer(regs.cfgr.ms0);
|
||||
|
||||
s.integer(regs.clsr);
|
||||
|
||||
s.integer(regs.romcl);
|
||||
s.integer(regs.romdr);
|
||||
|
||||
s.integer(regs.ramcl);
|
||||
s.integer(regs.ramar);
|
||||
s.integer(regs.ramdr);
|
||||
|
||||
s.integer(regs.sreg);
|
||||
s.integer(regs.dreg);
|
||||
|
||||
s.array(cache.buffer);
|
||||
s.array(cache.valid);
|
||||
|
||||
for(unsigned i = 0; i < 2; i++) {
|
||||
s.integer(pixelcache[i].offset);
|
||||
s.integer(pixelcache[i].bitpend);
|
||||
s.array(pixelcache[i].data);
|
||||
}
|
||||
|
||||
//timing/timing.hpp
|
||||
s.integer(cache_access_speed);
|
||||
s.integer(memory_access_speed);
|
||||
s.integer(r15_modified);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -3,6 +3,7 @@
|
||||
#define SUPERFX_CPP
|
||||
namespace SNES {
|
||||
|
||||
#include "serialization.cpp"
|
||||
#include "bus/bus.cpp"
|
||||
#include "core/core.cpp"
|
||||
#include "memory/memory.cpp"
|
||||
@@ -14,8 +15,23 @@ SuperFX superfx;
|
||||
|
||||
void SuperFX::enter() {
|
||||
while(true) {
|
||||
while(regs.sfr.g == 0) add_clocks(2);
|
||||
exec_opcode();
|
||||
if(scheduler.sync == Scheduler::SyncAll) {
|
||||
scheduler.exit(Scheduler::SynchronizeEvent);
|
||||
}
|
||||
|
||||
if(regs.sfr.g == 0) {
|
||||
add_clocks(6);
|
||||
scheduler.sync_copcpu();
|
||||
continue;
|
||||
}
|
||||
|
||||
(this->*opcode_table[(regs.sfr & 0x0300) + peekpipe()])();
|
||||
if(r15_modified == false) regs.r[15]++;
|
||||
|
||||
if(++instruction_counter >= 128) {
|
||||
instruction_counter = 0;
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,15 +42,17 @@ void SuperFX::init() {
|
||||
}
|
||||
|
||||
void SuperFX::enable() {
|
||||
for(uint16_t i = 0x3000; i <= 0x32ff; i++) memory::mmio.map(i, *this);
|
||||
for(unsigned i = 0x3000; i <= 0x32ff; i++) memory::mmio.map(i, *this);
|
||||
}
|
||||
|
||||
void SuperFX::power() {
|
||||
clockmode = config.superfx.speed;
|
||||
reset();
|
||||
}
|
||||
|
||||
void SuperFX::reset() {
|
||||
superfxbus.init();
|
||||
instruction_counter = 0;
|
||||
|
||||
for(unsigned n = 0; n < 16; n++) regs.r[n] = 0x0000;
|
||||
regs.sfr = 0x0000;
|
||||
@@ -58,4 +76,4 @@ void SuperFX::reset() {
|
||||
timing_reset();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
@@ -14,6 +14,12 @@ public:
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
void serialize(serializer&);
|
||||
|
||||
private:
|
||||
unsigned clockmode;
|
||||
unsigned instruction_counter;
|
||||
};
|
||||
|
||||
extern SuperFX superfx;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#ifdef SUPERFX_CPP
|
||||
|
||||
void SuperFX::add_clocks(unsigned clocks) {
|
||||
if(regs.romcl) {
|
||||
regs.romcl -= min(clocks, regs.romcl);
|
||||
@@ -27,7 +29,7 @@ void SuperFX::rombuffer_update() {
|
||||
regs.romcl = memory_access_speed;
|
||||
}
|
||||
|
||||
uint8_t SuperFX::rombuffer_read() {
|
||||
uint8 SuperFX::rombuffer_read() {
|
||||
rombuffer_sync();
|
||||
return regs.romdr;
|
||||
}
|
||||
@@ -36,31 +38,52 @@ void SuperFX::rambuffer_sync() {
|
||||
if(regs.ramcl) add_clocks(regs.ramcl);
|
||||
}
|
||||
|
||||
uint8_t SuperFX::rambuffer_read(uint16_t addr) {
|
||||
uint8 SuperFX::rambuffer_read(uint16 addr) {
|
||||
rambuffer_sync();
|
||||
return superfxbus.read(0x700000 + (regs.rambr << 16) + addr);
|
||||
}
|
||||
|
||||
void SuperFX::rambuffer_write(uint16_t addr, uint8_t data) {
|
||||
void SuperFX::rambuffer_write(uint16 addr, uint8 data) {
|
||||
rambuffer_sync();
|
||||
regs.ramcl = memory_access_speed;
|
||||
regs.ramar = addr;
|
||||
regs.ramdr = data;
|
||||
}
|
||||
|
||||
void SuperFX::r14_modify(uint16_t data) {
|
||||
void SuperFX::r14_modify(uint16 data) {
|
||||
regs.r[14].data = data;
|
||||
rombuffer_update();
|
||||
}
|
||||
|
||||
void SuperFX::r15_modify(uint16_t data) {
|
||||
void SuperFX::r15_modify(uint16 data) {
|
||||
regs.r[15].data = data;
|
||||
r15_modified = true;
|
||||
}
|
||||
|
||||
void SuperFX::update_speed() {
|
||||
//force SuperFX1 mode?
|
||||
if(clockmode == 1) {
|
||||
cache_access_speed = 2;
|
||||
memory_access_speed = 6;
|
||||
return;
|
||||
}
|
||||
|
||||
//force SuperFX2 mode?
|
||||
if(clockmode == 2) {
|
||||
cache_access_speed = 1;
|
||||
memory_access_speed = 5;
|
||||
regs.cfgr.ms0 = 0; //cannot use high-speed multiplication in 21MHz mode
|
||||
return;
|
||||
}
|
||||
|
||||
//default: allow S-CPU to select mode
|
||||
cache_access_speed = (regs.clsr ? 1 : 2);
|
||||
memory_access_speed = (regs.clsr ? 5 : 6);
|
||||
if(regs.clsr) regs.cfgr.ms0 = 0; //cannot use high-speed multiplication in 21MHz mode
|
||||
}
|
||||
|
||||
void SuperFX::timing_reset() {
|
||||
cache_access_speed = config.superfx.slow_cache_speed;
|
||||
memory_access_speed = config.superfx.slow_memory_speed;
|
||||
update_speed();
|
||||
r15_modified = false;
|
||||
|
||||
regs.romcl = 0;
|
||||
@@ -70,3 +93,5 @@ void SuperFX::timing_reset() {
|
||||
regs.ramar = 0;
|
||||
regs.ramdr = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -6,13 +6,14 @@ void add_clocks(unsigned clocks);
|
||||
|
||||
void rombuffer_sync();
|
||||
void rombuffer_update();
|
||||
uint8_t rombuffer_read();
|
||||
uint8 rombuffer_read();
|
||||
|
||||
void rambuffer_sync();
|
||||
uint8_t rambuffer_read(uint16_t addr);
|
||||
void rambuffer_write(uint16_t addr, uint8_t data);
|
||||
uint8 rambuffer_read(uint16 addr);
|
||||
void rambuffer_write(uint16 addr, uint8 data);
|
||||
|
||||
void r14_modify(uint16_t);
|
||||
void r15_modify(uint16_t);
|
||||
void r14_modify(uint16);
|
||||
void r15_modify(uint16);
|
||||
|
||||
void update_speed();
|
||||
void timing_reset();
|
||||
@@ -0,0 +1,140 @@
|
||||
#include <../base.hpp>
|
||||
|
||||
#define SUPERGAMEBOY_CPP
|
||||
namespace SNES {
|
||||
|
||||
SuperGameBoy supergameboy;
|
||||
|
||||
void SuperGameBoy::enter() {
|
||||
scheduler.clock.cop_freq = (version == SuperGameBoy1 ? 2147727 : 2097152);
|
||||
|
||||
if(!sgb_run) while(true) {
|
||||
if(scheduler.sync == Scheduler::SyncAll) {
|
||||
scheduler.exit(Scheduler::SynchronizeEvent);
|
||||
}
|
||||
|
||||
audio.coprocessor_sample(0, 0);
|
||||
scheduler.addclocks_cop(1);
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
|
||||
while(true) {
|
||||
if(scheduler.sync == Scheduler::SyncAll) {
|
||||
scheduler.exit(Scheduler::SynchronizeEvent);
|
||||
}
|
||||
|
||||
unsigned samples = sgb_run(samplebuffer, 16);
|
||||
for(unsigned i = 0; i < samples; i++) {
|
||||
int16 left = samplebuffer[i] >> 0;
|
||||
int16 right = samplebuffer[i] >> 16;
|
||||
|
||||
//SNES audio is notoriously quiet; lower Game Boy samples to match SGB sound effects
|
||||
audio.coprocessor_sample(left / 3, right / 3);
|
||||
}
|
||||
|
||||
scheduler.addclocks_cop(samples);
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
}
|
||||
|
||||
uint8 SuperGameBoy::mmio_read(unsigned addr) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr == 0x2181) return mmio[0]->mmio_read(addr);
|
||||
if(addr == 0x2182) return mmio[1]->mmio_read(addr);
|
||||
if(addr == 0x420b) return mmio[2]->mmio_read(addr);
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void SuperGameBoy::mmio_write(unsigned addr, uint8 data) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr == 0x2181) {
|
||||
row = (row & 0xff00) | (data << 0);
|
||||
mmio[0]->mmio_write(addr, data);
|
||||
}
|
||||
|
||||
if(addr == 0x2182) {
|
||||
row = (row & 0x00ff) | (data << 8);
|
||||
mmio[1]->mmio_write(addr, data);
|
||||
}
|
||||
|
||||
if(addr == 0x420b) {
|
||||
if(data == 0x10 && sgb_row) {
|
||||
if(row >= 0x5000 && row <= 0x6540) sgb_row((row - 0x5000) / 320);
|
||||
if(row >= 0x6800 && row <= 0x7d40) sgb_row((row - 0x6800) / 320);
|
||||
}
|
||||
mmio[2]->mmio_write(addr, data);
|
||||
}
|
||||
}
|
||||
|
||||
uint8 SuperGameBoy::read(unsigned addr) {
|
||||
if(sgb_read) return sgb_read(addr);
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void SuperGameBoy::write(unsigned addr, uint8 data) {
|
||||
if(sgb_write) sgb_write(addr, data);
|
||||
}
|
||||
|
||||
void SuperGameBoy::init() {
|
||||
if(open("supergameboy")) {
|
||||
sgb_rom = sym("sgb_rom");
|
||||
sgb_ram = sym("sgb_ram");
|
||||
sgb_rtc = sym("sgb_rtc");
|
||||
sgb_init = sym("sgb_init");
|
||||
sgb_term = sym("sgb_term");
|
||||
sgb_power = sym("sgb_power");
|
||||
sgb_reset = sym("sgb_reset");
|
||||
sgb_row = sym("sgb_row");
|
||||
sgb_read = sym("sgb_read");
|
||||
sgb_write = sym("sgb_write");
|
||||
sgb_run = sym("sgb_run");
|
||||
sgb_save = sym("sgb_save");
|
||||
sgb_serialize = sym("sgb_serialize");
|
||||
}
|
||||
}
|
||||
|
||||
void SuperGameBoy::enable() {
|
||||
mmio[0] = memory::mmio.mmio[0x2181 - 0x2000];
|
||||
mmio[1] = memory::mmio.mmio[0x2182 - 0x2000];
|
||||
mmio[2] = memory::mmio.mmio[0x420b - 0x2000];
|
||||
|
||||
memory::mmio.map(0x2181, *this);
|
||||
memory::mmio.map(0x2182, *this);
|
||||
memory::mmio.map(0x420b, *this);
|
||||
}
|
||||
|
||||
void SuperGameBoy::power() {
|
||||
version = (cartridge.type() == Cartridge::TypeSuperGameBoy1Bios ? SuperGameBoy1 : SuperGameBoy2);
|
||||
|
||||
audio.coprocessor_enable(true);
|
||||
audio.coprocessor_frequency(version == SuperGameBoy1 ? 2147727.0 : 2097152.0);
|
||||
|
||||
bus.map(Bus::MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, *this);
|
||||
bus.map(Bus::MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, *this);
|
||||
|
||||
sgb_rom(memory::gbrom.data(), memory::gbrom.size() == -1U ? 0 : memory::gbrom.size());
|
||||
sgb_ram(memory::gbram.data(), memory::gbram.size() == -1U ? 0 : memory::gbram.size());
|
||||
sgb_rtc(memory::gbrtc.data(), memory::gbrtc.size() == -1U ? 0 : memory::gbrtc.size());
|
||||
|
||||
if(sgb_init) sgb_init(version);
|
||||
if(sgb_power) sgb_power();
|
||||
}
|
||||
|
||||
void SuperGameBoy::reset() {
|
||||
if(sgb_reset) sgb_reset();
|
||||
}
|
||||
|
||||
void SuperGameBoy::unload() {
|
||||
if(sgb_term) sgb_term();
|
||||
}
|
||||
|
||||
void SuperGameBoy::serialize(serializer &s) {
|
||||
s.integer(row);
|
||||
s.integer(version);
|
||||
if(sgb_serialize) sgb_serialize(s);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
class SuperGameBoy : public MMIO, public Memory, public library {
|
||||
public:
|
||||
void enter();
|
||||
|
||||
MMIO *mmio[3];
|
||||
uint8 mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
void unload();
|
||||
|
||||
void serialize(serializer&);
|
||||
|
||||
private:
|
||||
uint32_t samplebuffer[4096];
|
||||
unsigned row;
|
||||
bool version;
|
||||
|
||||
enum { SuperGameBoy1 = 0, SuperGameBoy2 = 1 };
|
||||
function<void (uint8_t*, unsigned)> sgb_rom;
|
||||
function<void (uint8_t*, unsigned)> sgb_ram;
|
||||
function<void (uint8_t*, unsigned)> sgb_rtc;
|
||||
function<bool (bool)> sgb_init;
|
||||
function<void ()> sgb_term;
|
||||
function<void ()> sgb_power;
|
||||
function<void ()> sgb_reset;
|
||||
function<void (unsigned)> sgb_row;
|
||||
function<uint8 (uint16)> sgb_read;
|
||||
function<void (uint16, uint8)> sgb_write;
|
||||
function<unsigned (uint32_t*, unsigned)> sgb_run;
|
||||
function<void ()> sgb_save;
|
||||
function<void (serializer&)> sgb_serialize;
|
||||
};
|
||||
|
||||
extern SuperGameBoy supergameboy;
|
||||
File renamed without changes.
@@ -1,3 +0,0 @@
|
||||
clear
|
||||
bpp opcode_functions.cpp opcode_functions.bpp
|
||||
bpp opcode_headers.hpp opcode_headers.bpp
|
||||
+28
-4
@@ -3,10 +3,34 @@
|
||||
#define CPUCORE_CPP
|
||||
namespace SNES {
|
||||
|
||||
#include "opcode_algorithms.cpp"
|
||||
#include "opcode_functions.cpp"
|
||||
#include "opcode_tables.cpp"
|
||||
#include "disasm/disasm.cpp"
|
||||
#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.
|
||||
|
||||
+142
-2
@@ -2,8 +2,7 @@ class CPUcore {
|
||||
public:
|
||||
#include "registers.hpp"
|
||||
#include "memory.hpp"
|
||||
#include "opcode_headers.hpp"
|
||||
#include "disasm/disasm.hpp"
|
||||
#include "disassembler/disassembler.hpp"
|
||||
|
||||
regs_t regs;
|
||||
reg24_t aa, rd;
|
||||
@@ -62,6 +61,146 @@ public:
|
||||
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_tsc_e();
|
||||
void op_tsc_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();
|
||||
@@ -75,5 +214,6 @@ public:
|
||||
table_mx = 1024, //16-bit accumulator, 16-bit index
|
||||
};
|
||||
|
||||
void core_serialize(serializer&);
|
||||
CPUcore();
|
||||
};
|
||||
@@ -1,479 +0,0 @@
|
||||
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) {
|
||||
static reg24_t pc;
|
||||
char t[256];
|
||||
char *s = output;
|
||||
|
||||
if(false /* in_opcode() == true */) {
|
||||
strcpy(s, "?????? <CPU within opcode>");
|
||||
return;
|
||||
}
|
||||
|
||||
pc.d = regs.pc.d;
|
||||
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", ppu.vcounter(), ppu.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;
|
||||
}
|
||||
@@ -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);
|
||||
uint8 dreadb(uint32 addr);
|
||||
uint16 dreadw(uint32 addr);
|
||||
uint32 dreadl(uint32 addr);
|
||||
uint32 decode(uint8 offset_type, uint32 addr);
|
||||
uint8 opcode_length();
|
||||
@@ -0,0 +1,483 @@
|
||||
#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
|
||||
@@ -0,0 +1,30 @@
|
||||
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();
|
||||
@@ -1,13 +0,0 @@
|
||||
//opcode_functions.cpp was generated via bpp -> opcode_functions.bpp
|
||||
|
||||
@global class CPUcore
|
||||
@global lc last_cycle();
|
||||
@global wai regs.wai
|
||||
|
||||
@include "opcode_read.bpp"
|
||||
@include "opcode_write.bpp"
|
||||
@include "opcode_rmw.bpp"
|
||||
@include "opcode_pc.bpp"
|
||||
@include "opcode_misc.bpp"
|
||||
|
||||
@include "opcode_list.bpp"
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,386 +0,0 @@
|
||||
//===============
|
||||
//opcode_read.bpp
|
||||
//===============
|
||||
|
||||
@macro op_read_const(name)
|
||||
void op_{name}_const_b();
|
||||
void op_{name}_const_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_bit_const()
|
||||
void op_bit_const_b();
|
||||
void op_bit_const_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_addr(name)
|
||||
void op_{name}_addr_b();
|
||||
void op_{name}_addr_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_addrx(name)
|
||||
void op_{name}_addrx_b();
|
||||
void op_{name}_addrx_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_addry(name)
|
||||
void op_{name}_addry_b();
|
||||
void op_{name}_addry_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_long(name)
|
||||
void op_{name}_long_b();
|
||||
void op_{name}_long_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_longx(name)
|
||||
void op_{name}_longx_b();
|
||||
void op_{name}_longx_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_dp(name)
|
||||
void op_{name}_dp_b();
|
||||
void op_{name}_dp_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_dpr(name, r)
|
||||
void op_{name}_dpr_b();
|
||||
void op_{name}_dpr_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_idp(name)
|
||||
void op_{name}_idp_b();
|
||||
void op_{name}_idp_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_idpx(name)
|
||||
void op_{name}_idpx_b();
|
||||
void op_{name}_idpx_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_idpy(name)
|
||||
void op_{name}_idpy_b();
|
||||
void op_{name}_idpy_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_ildp(name)
|
||||
void op_{name}_ildp_b();
|
||||
void op_{name}_ildp_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_ildpy(name)
|
||||
void op_{name}_ildpy_b();
|
||||
void op_{name}_ildpy_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_sr(name)
|
||||
void op_{name}_sr_b();
|
||||
void op_{name}_sr_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_isry(name)
|
||||
void op_{name}_isry_b();
|
||||
void op_{name}_isry_w();
|
||||
@endmacro
|
||||
|
||||
//================
|
||||
//opcode_write.bpp
|
||||
//================
|
||||
|
||||
@macro op_store_addr(name, r)
|
||||
void op_{name}_addr_b();
|
||||
void op_{name}_addr_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_store_addrr(name, suffix, r, index)
|
||||
void op_{name}_addr{suffix}_b();
|
||||
void op_{name}_addr{suffix}_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_store_longr(name, suffix, index)
|
||||
void op_{name}_long{suffix}_b();
|
||||
void op_{name}_long{suffix}_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_store_dp(name, r)
|
||||
void op_{name}_dp_b();
|
||||
void op_{name}_dp_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_store_dpr(name, r, index)
|
||||
void op_{name}_dpr_b();
|
||||
void op_{name}_dpr_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_idp()
|
||||
void op_sta_idp_b();
|
||||
void op_sta_idp_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_ildp()
|
||||
void op_sta_ildp_b();
|
||||
void op_sta_ildp_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_idpx()
|
||||
void op_sta_idpx_b();
|
||||
void op_sta_idpx_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_idpy()
|
||||
void op_sta_idpy_b();
|
||||
void op_sta_idpy_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_ildpy()
|
||||
void op_sta_ildpy_b();
|
||||
void op_sta_ildpy_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_sr()
|
||||
void op_sta_sr_b();
|
||||
void op_sta_sr_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_isry()
|
||||
void op_sta_isry_b();
|
||||
void op_sta_isry_w();
|
||||
@endmacro
|
||||
|
||||
//==============
|
||||
//opcode_rmw.bpp
|
||||
//==============
|
||||
|
||||
@macro op_adjust(name, r, op)
|
||||
void op_{name}_imm_b();
|
||||
void op_{name}_imm_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_asl()
|
||||
void op_asl_imm_b();
|
||||
void op_asl_imm_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_lsr()
|
||||
void op_lsr_imm_b();
|
||||
void op_lsr_imm_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_rol()
|
||||
void op_rol_imm_b();
|
||||
void op_rol_imm_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_ror()
|
||||
void op_ror_imm_b();
|
||||
void op_ror_imm_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_adjust_addr(name)
|
||||
void op_{name}_addr_b();
|
||||
void op_{name}_addr_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_adjust_addrx(name)
|
||||
void op_{name}_addrx_b();
|
||||
void op_{name}_addrx_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_adjust_dp(name)
|
||||
void op_{name}_dp_b();
|
||||
void op_{name}_dp_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_adjust_dpx(name)
|
||||
void op_{name}_dpx_b();
|
||||
void op_{name}_dpx_w();
|
||||
@endmacro
|
||||
|
||||
//=============
|
||||
//opcode_pc.bpp
|
||||
//=============
|
||||
|
||||
@macro op_branch(name, condition)
|
||||
void op_{name}();
|
||||
@endmacro
|
||||
|
||||
@macro op_bra()
|
||||
void op_bra();
|
||||
@endmacro
|
||||
|
||||
@macro op_brl()
|
||||
void op_brl();
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_addr()
|
||||
void op_jmp_addr();
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_long()
|
||||
void op_jmp_long();
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_iaddr()
|
||||
void op_jmp_iaddr();
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_iaddrx()
|
||||
void op_jmp_iaddrx();
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_iladdr()
|
||||
void op_jmp_iladdr();
|
||||
@endmacro
|
||||
|
||||
@macro op_jsr_addr()
|
||||
void op_jsr_addr();
|
||||
@endmacro
|
||||
|
||||
@macro op_jsr_long()
|
||||
void op_jsr_long_e();
|
||||
void op_jsr_long_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_jsr_iaddrx()
|
||||
void op_jsr_iaddrx_e();
|
||||
void op_jsr_iaddrx_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_rti()
|
||||
void op_rti_e();
|
||||
void op_rti_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_rts()
|
||||
void op_rts();
|
||||
@endmacro
|
||||
|
||||
@macro op_rtl()
|
||||
void op_rtl_e();
|
||||
void op_rtl_n();
|
||||
@endmacro
|
||||
|
||||
//===============
|
||||
//opcode_misc.bpp
|
||||
//===============
|
||||
|
||||
@macro op_nop()
|
||||
void op_nop();
|
||||
@endmacro
|
||||
|
||||
@macro op_wdm()
|
||||
void op_wdm();
|
||||
@endmacro
|
||||
|
||||
@macro op_xba()
|
||||
void op_xba();
|
||||
@endmacro
|
||||
|
||||
@macro op_move(name, op)
|
||||
void op_{name}_b();
|
||||
void op_{name}_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_interrupt(name, vectorE, vectorN)
|
||||
void op_{name}_e();
|
||||
void op_{name}_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_stp()
|
||||
void op_stp();
|
||||
@endmacro
|
||||
|
||||
@macro op_wai()
|
||||
void op_wai();
|
||||
@endmacro
|
||||
|
||||
@macro op_xce()
|
||||
void op_xce();
|
||||
@endmacro
|
||||
|
||||
@macro op_flag(name, rule)
|
||||
void op_{name}();
|
||||
@endmacro
|
||||
|
||||
@macro op_pflag(name, op)
|
||||
void op_{name}_e();
|
||||
void op_{name}_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_transfer(name, from, to)
|
||||
void op_{name}_b();
|
||||
void op_{name}_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_transfer_word(name, from, to)
|
||||
void op_{name}();
|
||||
@endmacro
|
||||
|
||||
@macro op_tcs()
|
||||
void op_tcs_e();
|
||||
void op_tcs_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_tsc()
|
||||
void op_tsc_e();
|
||||
void op_tsc_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_tsx()
|
||||
void op_tsx_b();
|
||||
void op_tsx_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_txs()
|
||||
void op_txs_e();
|
||||
void op_txs_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_push(name, r)
|
||||
void op_{name}_b();
|
||||
void op_{name}_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_phd()
|
||||
void op_phd_e();
|
||||
void op_phd_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_push_byte(name, r)
|
||||
void op_{name}();
|
||||
@endmacro
|
||||
|
||||
@macro op_pull(name, r)
|
||||
void op_{name}_b();
|
||||
void op_{name}_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_pld()
|
||||
void op_pld_e();
|
||||
void op_pld_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_plb()
|
||||
void op_plb();
|
||||
@endmacro
|
||||
|
||||
@macro op_plp()
|
||||
void op_plp_e();
|
||||
void op_plp_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_pea()
|
||||
void op_pea_e();
|
||||
void op_pea_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_pei()
|
||||
void op_pei_e();
|
||||
void op_pei_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_per()
|
||||
void op_per_e();
|
||||
void op_per_n();
|
||||
@endmacro
|
||||
|
||||
@include "opcode_list.bpp"
|
||||
@@ -1,892 +0,0 @@
|
||||
//===============
|
||||
//opcode_read.bpp
|
||||
//===============
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//================
|
||||
//opcode_write.bpp
|
||||
//================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//==============
|
||||
//opcode_rmw.bpp
|
||||
//==============
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=============
|
||||
//opcode_pc.bpp
|
||||
//=============
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===============
|
||||
//opcode_misc.bpp
|
||||
//===============
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===============
|
||||
//opcode_read.bpp
|
||||
//===============
|
||||
|
||||
void op_adc_const_b();
|
||||
void op_adc_const_w();
|
||||
|
||||
void op_and_const_b();
|
||||
void op_and_const_w();
|
||||
|
||||
void op_cmp_const_b();
|
||||
void op_cmp_const_w();
|
||||
|
||||
void op_cpx_const_b();
|
||||
void op_cpx_const_w();
|
||||
|
||||
void op_cpy_const_b();
|
||||
void op_cpy_const_w();
|
||||
|
||||
void op_eor_const_b();
|
||||
void op_eor_const_w();
|
||||
|
||||
void op_lda_const_b();
|
||||
void op_lda_const_w();
|
||||
|
||||
void op_ldx_const_b();
|
||||
void op_ldx_const_w();
|
||||
|
||||
void op_ldy_const_b();
|
||||
void op_ldy_const_w();
|
||||
|
||||
void op_ora_const_b();
|
||||
void op_ora_const_w();
|
||||
|
||||
void op_sbc_const_b();
|
||||
void op_sbc_const_w();
|
||||
|
||||
|
||||
void op_bit_const_b();
|
||||
void op_bit_const_w();
|
||||
|
||||
|
||||
void op_adc_addr_b();
|
||||
void op_adc_addr_w();
|
||||
|
||||
void op_and_addr_b();
|
||||
void op_and_addr_w();
|
||||
|
||||
void op_bit_addr_b();
|
||||
void op_bit_addr_w();
|
||||
|
||||
void op_cmp_addr_b();
|
||||
void op_cmp_addr_w();
|
||||
|
||||
void op_cpx_addr_b();
|
||||
void op_cpx_addr_w();
|
||||
|
||||
void op_cpy_addr_b();
|
||||
void op_cpy_addr_w();
|
||||
|
||||
void op_eor_addr_b();
|
||||
void op_eor_addr_w();
|
||||
|
||||
void op_lda_addr_b();
|
||||
void op_lda_addr_w();
|
||||
|
||||
void op_ldx_addr_b();
|
||||
void op_ldx_addr_w();
|
||||
|
||||
void op_ldy_addr_b();
|
||||
void op_ldy_addr_w();
|
||||
|
||||
void op_ora_addr_b();
|
||||
void op_ora_addr_w();
|
||||
|
||||
void op_sbc_addr_b();
|
||||
void op_sbc_addr_w();
|
||||
|
||||
|
||||
void op_adc_addrx_b();
|
||||
void op_adc_addrx_w();
|
||||
|
||||
void op_and_addrx_b();
|
||||
void op_and_addrx_w();
|
||||
|
||||
void op_bit_addrx_b();
|
||||
void op_bit_addrx_w();
|
||||
|
||||
void op_cmp_addrx_b();
|
||||
void op_cmp_addrx_w();
|
||||
|
||||
void op_eor_addrx_b();
|
||||
void op_eor_addrx_w();
|
||||
|
||||
void op_lda_addrx_b();
|
||||
void op_lda_addrx_w();
|
||||
|
||||
void op_ldy_addrx_b();
|
||||
void op_ldy_addrx_w();
|
||||
|
||||
void op_ora_addrx_b();
|
||||
void op_ora_addrx_w();
|
||||
|
||||
void op_sbc_addrx_b();
|
||||
void op_sbc_addrx_w();
|
||||
|
||||
|
||||
void op_adc_addry_b();
|
||||
void op_adc_addry_w();
|
||||
|
||||
void op_and_addry_b();
|
||||
void op_and_addry_w();
|
||||
|
||||
void op_cmp_addry_b();
|
||||
void op_cmp_addry_w();
|
||||
|
||||
void op_eor_addry_b();
|
||||
void op_eor_addry_w();
|
||||
|
||||
void op_lda_addry_b();
|
||||
void op_lda_addry_w();
|
||||
|
||||
void op_ldx_addry_b();
|
||||
void op_ldx_addry_w();
|
||||
|
||||
void op_ora_addry_b();
|
||||
void op_ora_addry_w();
|
||||
|
||||
void op_sbc_addry_b();
|
||||
void op_sbc_addry_w();
|
||||
|
||||
|
||||
void op_adc_long_b();
|
||||
void op_adc_long_w();
|
||||
|
||||
void op_and_long_b();
|
||||
void op_and_long_w();
|
||||
|
||||
void op_cmp_long_b();
|
||||
void op_cmp_long_w();
|
||||
|
||||
void op_eor_long_b();
|
||||
void op_eor_long_w();
|
||||
|
||||
void op_lda_long_b();
|
||||
void op_lda_long_w();
|
||||
|
||||
void op_ora_long_b();
|
||||
void op_ora_long_w();
|
||||
|
||||
void op_sbc_long_b();
|
||||
void op_sbc_long_w();
|
||||
|
||||
|
||||
void op_adc_longx_b();
|
||||
void op_adc_longx_w();
|
||||
|
||||
void op_and_longx_b();
|
||||
void op_and_longx_w();
|
||||
|
||||
void op_cmp_longx_b();
|
||||
void op_cmp_longx_w();
|
||||
|
||||
void op_eor_longx_b();
|
||||
void op_eor_longx_w();
|
||||
|
||||
void op_lda_longx_b();
|
||||
void op_lda_longx_w();
|
||||
|
||||
void op_ora_longx_b();
|
||||
void op_ora_longx_w();
|
||||
|
||||
void op_sbc_longx_b();
|
||||
void op_sbc_longx_w();
|
||||
|
||||
|
||||
void op_adc_dp_b();
|
||||
void op_adc_dp_w();
|
||||
|
||||
void op_and_dp_b();
|
||||
void op_and_dp_w();
|
||||
|
||||
void op_bit_dp_b();
|
||||
void op_bit_dp_w();
|
||||
|
||||
void op_cmp_dp_b();
|
||||
void op_cmp_dp_w();
|
||||
|
||||
void op_cpx_dp_b();
|
||||
void op_cpx_dp_w();
|
||||
|
||||
void op_cpy_dp_b();
|
||||
void op_cpy_dp_w();
|
||||
|
||||
void op_eor_dp_b();
|
||||
void op_eor_dp_w();
|
||||
|
||||
void op_lda_dp_b();
|
||||
void op_lda_dp_w();
|
||||
|
||||
void op_ldx_dp_b();
|
||||
void op_ldx_dp_w();
|
||||
|
||||
void op_ldy_dp_b();
|
||||
void op_ldy_dp_w();
|
||||
|
||||
void op_ora_dp_b();
|
||||
void op_ora_dp_w();
|
||||
|
||||
void op_sbc_dp_b();
|
||||
void op_sbc_dp_w();
|
||||
|
||||
|
||||
void op_adc_dpr_b();
|
||||
void op_adc_dpr_w();
|
||||
|
||||
void op_and_dpr_b();
|
||||
void op_and_dpr_w();
|
||||
|
||||
void op_bit_dpr_b();
|
||||
void op_bit_dpr_w();
|
||||
|
||||
void op_cmp_dpr_b();
|
||||
void op_cmp_dpr_w();
|
||||
|
||||
void op_eor_dpr_b();
|
||||
void op_eor_dpr_w();
|
||||
|
||||
void op_lda_dpr_b();
|
||||
void op_lda_dpr_w();
|
||||
|
||||
void op_ldx_dpr_b();
|
||||
void op_ldx_dpr_w();
|
||||
|
||||
void op_ldy_dpr_b();
|
||||
void op_ldy_dpr_w();
|
||||
|
||||
void op_ora_dpr_b();
|
||||
void op_ora_dpr_w();
|
||||
|
||||
void op_sbc_dpr_b();
|
||||
void op_sbc_dpr_w();
|
||||
|
||||
|
||||
void op_adc_idp_b();
|
||||
void op_adc_idp_w();
|
||||
|
||||
void op_and_idp_b();
|
||||
void op_and_idp_w();
|
||||
|
||||
void op_cmp_idp_b();
|
||||
void op_cmp_idp_w();
|
||||
|
||||
void op_eor_idp_b();
|
||||
void op_eor_idp_w();
|
||||
|
||||
void op_lda_idp_b();
|
||||
void op_lda_idp_w();
|
||||
|
||||
void op_ora_idp_b();
|
||||
void op_ora_idp_w();
|
||||
|
||||
void op_sbc_idp_b();
|
||||
void op_sbc_idp_w();
|
||||
|
||||
|
||||
void op_adc_idpx_b();
|
||||
void op_adc_idpx_w();
|
||||
|
||||
void op_and_idpx_b();
|
||||
void op_and_idpx_w();
|
||||
|
||||
void op_cmp_idpx_b();
|
||||
void op_cmp_idpx_w();
|
||||
|
||||
void op_eor_idpx_b();
|
||||
void op_eor_idpx_w();
|
||||
|
||||
void op_lda_idpx_b();
|
||||
void op_lda_idpx_w();
|
||||
|
||||
void op_ora_idpx_b();
|
||||
void op_ora_idpx_w();
|
||||
|
||||
void op_sbc_idpx_b();
|
||||
void op_sbc_idpx_w();
|
||||
|
||||
|
||||
void op_adc_idpy_b();
|
||||
void op_adc_idpy_w();
|
||||
|
||||
void op_and_idpy_b();
|
||||
void op_and_idpy_w();
|
||||
|
||||
void op_cmp_idpy_b();
|
||||
void op_cmp_idpy_w();
|
||||
|
||||
void op_eor_idpy_b();
|
||||
void op_eor_idpy_w();
|
||||
|
||||
void op_lda_idpy_b();
|
||||
void op_lda_idpy_w();
|
||||
|
||||
void op_ora_idpy_b();
|
||||
void op_ora_idpy_w();
|
||||
|
||||
void op_sbc_idpy_b();
|
||||
void op_sbc_idpy_w();
|
||||
|
||||
|
||||
void op_adc_ildp_b();
|
||||
void op_adc_ildp_w();
|
||||
|
||||
void op_and_ildp_b();
|
||||
void op_and_ildp_w();
|
||||
|
||||
void op_cmp_ildp_b();
|
||||
void op_cmp_ildp_w();
|
||||
|
||||
void op_eor_ildp_b();
|
||||
void op_eor_ildp_w();
|
||||
|
||||
void op_lda_ildp_b();
|
||||
void op_lda_ildp_w();
|
||||
|
||||
void op_ora_ildp_b();
|
||||
void op_ora_ildp_w();
|
||||
|
||||
void op_sbc_ildp_b();
|
||||
void op_sbc_ildp_w();
|
||||
|
||||
|
||||
void op_adc_ildpy_b();
|
||||
void op_adc_ildpy_w();
|
||||
|
||||
void op_and_ildpy_b();
|
||||
void op_and_ildpy_w();
|
||||
|
||||
void op_cmp_ildpy_b();
|
||||
void op_cmp_ildpy_w();
|
||||
|
||||
void op_eor_ildpy_b();
|
||||
void op_eor_ildpy_w();
|
||||
|
||||
void op_lda_ildpy_b();
|
||||
void op_lda_ildpy_w();
|
||||
|
||||
void op_ora_ildpy_b();
|
||||
void op_ora_ildpy_w();
|
||||
|
||||
void op_sbc_ildpy_b();
|
||||
void op_sbc_ildpy_w();
|
||||
|
||||
|
||||
void op_adc_sr_b();
|
||||
void op_adc_sr_w();
|
||||
|
||||
void op_and_sr_b();
|
||||
void op_and_sr_w();
|
||||
|
||||
void op_cmp_sr_b();
|
||||
void op_cmp_sr_w();
|
||||
|
||||
void op_eor_sr_b();
|
||||
void op_eor_sr_w();
|
||||
|
||||
void op_lda_sr_b();
|
||||
void op_lda_sr_w();
|
||||
|
||||
void op_ora_sr_b();
|
||||
void op_ora_sr_w();
|
||||
|
||||
void op_sbc_sr_b();
|
||||
void op_sbc_sr_w();
|
||||
|
||||
|
||||
void op_adc_isry_b();
|
||||
void op_adc_isry_w();
|
||||
|
||||
void op_and_isry_b();
|
||||
void op_and_isry_w();
|
||||
|
||||
void op_cmp_isry_b();
|
||||
void op_cmp_isry_w();
|
||||
|
||||
void op_eor_isry_b();
|
||||
void op_eor_isry_w();
|
||||
|
||||
void op_lda_isry_b();
|
||||
void op_lda_isry_w();
|
||||
|
||||
void op_ora_isry_b();
|
||||
void op_ora_isry_w();
|
||||
|
||||
void op_sbc_isry_b();
|
||||
void op_sbc_isry_w();
|
||||
|
||||
|
||||
//================
|
||||
//opcode_write.bpp
|
||||
//================
|
||||
|
||||
void op_sta_addr_b();
|
||||
void op_sta_addr_w();
|
||||
|
||||
void op_stx_addr_b();
|
||||
void op_stx_addr_w();
|
||||
|
||||
void op_sty_addr_b();
|
||||
void op_sty_addr_w();
|
||||
|
||||
void op_stz_addr_b();
|
||||
void op_stz_addr_w();
|
||||
|
||||
|
||||
void op_sta_addrx_b();
|
||||
void op_sta_addrx_w();
|
||||
|
||||
void op_sta_addry_b();
|
||||
void op_sta_addry_w();
|
||||
|
||||
void op_stz_addrx_b();
|
||||
void op_stz_addrx_w();
|
||||
|
||||
|
||||
void op_sta_long_b();
|
||||
void op_sta_long_w();
|
||||
|
||||
void op_sta_longx_b();
|
||||
void op_sta_longx_w();
|
||||
|
||||
|
||||
void op_sta_dp_b();
|
||||
void op_sta_dp_w();
|
||||
|
||||
void op_stx_dp_b();
|
||||
void op_stx_dp_w();
|
||||
|
||||
void op_sty_dp_b();
|
||||
void op_sty_dp_w();
|
||||
|
||||
void op_stz_dp_b();
|
||||
void op_stz_dp_w();
|
||||
|
||||
|
||||
void op_sta_dpr_b();
|
||||
void op_sta_dpr_w();
|
||||
|
||||
void op_stx_dpr_b();
|
||||
void op_stx_dpr_w();
|
||||
|
||||
void op_sty_dpr_b();
|
||||
void op_sty_dpr_w();
|
||||
|
||||
void op_stz_dpr_b();
|
||||
void op_stz_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();
|
||||
|
||||
|
||||
//==============
|
||||
//opcode_rmw.bpp
|
||||
//==============
|
||||
|
||||
void op_inc_imm_b();
|
||||
void op_inc_imm_w();
|
||||
|
||||
void op_inx_imm_b();
|
||||
void op_inx_imm_w();
|
||||
|
||||
void op_iny_imm_b();
|
||||
void op_iny_imm_w();
|
||||
|
||||
void op_dec_imm_b();
|
||||
void op_dec_imm_w();
|
||||
|
||||
void op_dex_imm_b();
|
||||
void op_dex_imm_w();
|
||||
|
||||
void op_dey_imm_b();
|
||||
void op_dey_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();
|
||||
|
||||
|
||||
void op_inc_addr_b();
|
||||
void op_inc_addr_w();
|
||||
|
||||
void op_dec_addr_b();
|
||||
void op_dec_addr_w();
|
||||
|
||||
void op_asl_addr_b();
|
||||
void op_asl_addr_w();
|
||||
|
||||
void op_lsr_addr_b();
|
||||
void op_lsr_addr_w();
|
||||
|
||||
void op_rol_addr_b();
|
||||
void op_rol_addr_w();
|
||||
|
||||
void op_ror_addr_b();
|
||||
void op_ror_addr_w();
|
||||
|
||||
void op_trb_addr_b();
|
||||
void op_trb_addr_w();
|
||||
|
||||
void op_tsb_addr_b();
|
||||
void op_tsb_addr_w();
|
||||
|
||||
|
||||
void op_inc_addrx_b();
|
||||
void op_inc_addrx_w();
|
||||
|
||||
void op_dec_addrx_b();
|
||||
void op_dec_addrx_w();
|
||||
|
||||
void op_asl_addrx_b();
|
||||
void op_asl_addrx_w();
|
||||
|
||||
void op_lsr_addrx_b();
|
||||
void op_lsr_addrx_w();
|
||||
|
||||
void op_rol_addrx_b();
|
||||
void op_rol_addrx_w();
|
||||
|
||||
void op_ror_addrx_b();
|
||||
void op_ror_addrx_w();
|
||||
|
||||
|
||||
void op_inc_dp_b();
|
||||
void op_inc_dp_w();
|
||||
|
||||
void op_dec_dp_b();
|
||||
void op_dec_dp_w();
|
||||
|
||||
void op_asl_dp_b();
|
||||
void op_asl_dp_w();
|
||||
|
||||
void op_lsr_dp_b();
|
||||
void op_lsr_dp_w();
|
||||
|
||||
void op_rol_dp_b();
|
||||
void op_rol_dp_w();
|
||||
|
||||
void op_ror_dp_b();
|
||||
void op_ror_dp_w();
|
||||
|
||||
void op_trb_dp_b();
|
||||
void op_trb_dp_w();
|
||||
|
||||
void op_tsb_dp_b();
|
||||
void op_tsb_dp_w();
|
||||
|
||||
|
||||
void op_inc_dpx_b();
|
||||
void op_inc_dpx_w();
|
||||
|
||||
void op_dec_dpx_b();
|
||||
void op_dec_dpx_w();
|
||||
|
||||
void op_asl_dpx_b();
|
||||
void op_asl_dpx_w();
|
||||
|
||||
void op_lsr_dpx_b();
|
||||
void op_lsr_dpx_w();
|
||||
|
||||
void op_rol_dpx_b();
|
||||
void op_rol_dpx_w();
|
||||
|
||||
void op_ror_dpx_b();
|
||||
void op_ror_dpx_w();
|
||||
|
||||
|
||||
//=============
|
||||
//opcode_pc.bpp
|
||||
//=============
|
||||
|
||||
void op_bcc();
|
||||
|
||||
void op_bcs();
|
||||
|
||||
void op_bne();
|
||||
|
||||
void op_beq();
|
||||
|
||||
void op_bpl();
|
||||
|
||||
void op_bmi();
|
||||
|
||||
void op_bvc();
|
||||
|
||||
void op_bvs();
|
||||
|
||||
|
||||
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();
|
||||
|
||||
|
||||
//===============
|
||||
//opcode_misc.bpp
|
||||
//===============
|
||||
|
||||
void op_nop();
|
||||
|
||||
void op_wdm();
|
||||
|
||||
void op_xba();
|
||||
|
||||
|
||||
void op_mvn_b();
|
||||
void op_mvn_w();
|
||||
|
||||
void op_mvp_b();
|
||||
void op_mvp_w();
|
||||
|
||||
|
||||
void op_brk_e();
|
||||
void op_brk_n();
|
||||
|
||||
void op_cop_e();
|
||||
void op_cop_n();
|
||||
|
||||
|
||||
void op_stp();
|
||||
|
||||
void op_wai();
|
||||
|
||||
void op_xce();
|
||||
|
||||
|
||||
void op_clc();
|
||||
|
||||
void op_cld();
|
||||
|
||||
void op_cli();
|
||||
|
||||
void op_clv();
|
||||
|
||||
void op_sec();
|
||||
|
||||
void op_sed();
|
||||
|
||||
void op_sei();
|
||||
|
||||
|
||||
void op_rep_e();
|
||||
void op_rep_n();
|
||||
|
||||
void op_sep_e();
|
||||
void op_sep_n();
|
||||
|
||||
|
||||
void op_tax_b();
|
||||
void op_tax_w();
|
||||
|
||||
void op_tay_b();
|
||||
void op_tay_w();
|
||||
|
||||
void op_txa_b();
|
||||
void op_txa_w();
|
||||
|
||||
void op_txy_b();
|
||||
void op_txy_w();
|
||||
|
||||
void op_tya_b();
|
||||
void op_tya_w();
|
||||
|
||||
void op_tyx_b();
|
||||
void op_tyx_w();
|
||||
|
||||
|
||||
void op_tcd();
|
||||
|
||||
void op_tdc();
|
||||
|
||||
|
||||
void op_tcs_e();
|
||||
void op_tcs_n();
|
||||
|
||||
void op_tsc_e();
|
||||
void op_tsc_n();
|
||||
|
||||
void op_tsx_b();
|
||||
void op_tsx_w();
|
||||
|
||||
void op_txs_e();
|
||||
void op_txs_n();
|
||||
|
||||
|
||||
void op_pha_b();
|
||||
void op_pha_w();
|
||||
|
||||
void op_phx_b();
|
||||
void op_phx_w();
|
||||
|
||||
void op_phy_b();
|
||||
void op_phy_w();
|
||||
|
||||
void op_phd_e();
|
||||
void op_phd_n();
|
||||
|
||||
void op_phb();
|
||||
|
||||
void op_phk();
|
||||
|
||||
void op_php();
|
||||
|
||||
|
||||
void op_pla_b();
|
||||
void op_pla_w();
|
||||
|
||||
void op_plx_b();
|
||||
void op_plx_w();
|
||||
|
||||
void op_ply_b();
|
||||
void op_ply_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();
|
||||
|
||||
|
||||
|
||||
Loaded 100 of 505 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user