mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-18 18:21:28 +02:00
Compare commits
39 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f8e425ff49 | ||
|
2a6a66f478 | ||
|
3c42e6caa0 | ||
|
5f96547beb | ||
|
44b5f1bf27 | ||
|
b0a8de0208 | ||
|
11e0a2ac18 | ||
|
3a6eb56cef | ||
|
4c92d11d80 | ||
|
f3d1d10d3e | ||
|
90aa780d57 | ||
|
b5b21a4ec2 | ||
|
2b587de04b | ||
|
1e133eeb5e | ||
|
9de4b1dea2 | ||
|
2b84d1ef37 | ||
|
e2a44195cd | ||
|
9ac912d100 | ||
|
d15092dada | ||
|
91270e504a | ||
|
f976998222 | ||
|
def86470f4 | ||
|
3e7578761a | ||
|
45feae8f75 | ||
|
4d10c36870 | ||
|
cca8164005 | ||
|
0f83e39d5c | ||
|
ebbcc998d0 | ||
|
78da6946c6 | ||
|
4d31452bca | ||
|
eb1eca4a6d | ||
|
07c9df31a6 | ||
|
c64232a479 | ||
|
85b08fd24b | ||
|
3b3214d1be | ||
|
b5a38d2a07 | ||
|
94004f86ec | ||
|
148bbddb1a | ||
|
e5b2e87ff8 |
283
src/Makefile
283
src/Makefile
@@ -1,55 +1,40 @@
|
||||
include lib/nall/Makefile.string
|
||||
prefix = /usr/local
|
||||
include lib/nall/Makefile
|
||||
ui = ui_qt
|
||||
|
||||
################
|
||||
### compiler ###
|
||||
################
|
||||
|
||||
ifneq ($(findstring gcc,$(compiler)),) # GCC family
|
||||
flags = -O3 -fomit-frame-pointer -Ilib
|
||||
c = $(compiler) $(flags)
|
||||
cpp = $(subst cc,++,$(compiler)) $(flags)
|
||||
obj = o
|
||||
rule = -c $< -o $@
|
||||
link = -s
|
||||
mkbin = -o$1
|
||||
mkdef = -D$1
|
||||
mklib = -l$1
|
||||
else ifeq ($(compiler),cl) # Visual C++
|
||||
flags = /nologo /wd4355 /wd4805 /wd4996 /Ox /GL /EHsc /Ilib
|
||||
c = cl $(flags)
|
||||
cpp = cl $(flags)
|
||||
obj = obj
|
||||
rule = /c $< /Fo$@
|
||||
link = /link
|
||||
mkbin = /Fe$1
|
||||
mkdef = /D$1
|
||||
mklib = $1.lib
|
||||
else
|
||||
unknown_compiler: help;
|
||||
endif
|
||||
c := $(compiler)
|
||||
cpp := $(subst cc,++,$(compiler))
|
||||
flags := -O3 -fomit-frame-pointer -Ilib
|
||||
link := -s
|
||||
|
||||
##########
|
||||
### os ###
|
||||
##########
|
||||
# profile-guided instrumentation:
|
||||
# flags += -fprofile-generate
|
||||
# link += -lgcov
|
||||
|
||||
ifeq ($(platform),x) # X11
|
||||
ruby = video.glx video.xv video.sdl audio.alsa audio.openal audio.oss audio.pulseaudio audio.ao input.sdl input.x
|
||||
link += `pkg-config --libs gtk+-2.0`
|
||||
link += $(call mklib,Xtst)
|
||||
delete = rm -f $1
|
||||
else ifeq ($(platform),win) # Windows
|
||||
ruby = video.direct3d video.wgl video.directdraw video.gdi audio.directsound input.directinput
|
||||
link += $(if $(findstring mingw,$(compiler)),-mwindows)
|
||||
link += $(call mklib,uuid)
|
||||
link += $(call mklib,kernel32)
|
||||
link += $(call mklib,user32)
|
||||
link += $(call mklib,gdi32)
|
||||
link += $(call mklib,shell32)
|
||||
link += $(call mklib,winmm)
|
||||
link += $(call mklib,comdlg32)
|
||||
link += $(call mklib,comctl32)
|
||||
delete = $(if $(findstring i586-mingw-gcc,$(compiler)),rm -f $1,del $(subst /,\,$1))
|
||||
# profile-guided optimization:
|
||||
# flags += -fprofile-use
|
||||
|
||||
################
|
||||
### platform ###
|
||||
################
|
||||
|
||||
ifeq ($(platform),x)
|
||||
ruby := video.glx video.xv video.sdl
|
||||
ruby += audio.alsa audio.openal audio.oss audio.pulseaudio audio.ao
|
||||
ruby += input.sdl input.x
|
||||
else ifeq ($(platform),win)
|
||||
ruby := video.direct3d video.wgl video.directdraw video.gdi
|
||||
ruby += audio.directsound
|
||||
ruby += input.rawinput input.directinput
|
||||
|
||||
link += -mwindows
|
||||
# link += -mconsole
|
||||
link += -luuid -lkernel32 -luser32 -lgdi32 -lshell32
|
||||
# statically link Qt for Windows build
|
||||
link += -enable-stdcall-fixup -Wl,-s -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
|
||||
else
|
||||
unknown_platform: help;
|
||||
endif
|
||||
@@ -58,196 +43,188 @@ endif
|
||||
### ruby ###
|
||||
############
|
||||
|
||||
rubyflags =
|
||||
rubyflags += $(if $(findstring .sdl,$(ruby)),`sdl-config --cflags`)
|
||||
rubyflags = $(call ifhas,.sdl,$(ruby),`sdl-config --cflags`)
|
||||
|
||||
link += $(if $(findstring video.direct3d,$(ruby)),$(call mklib,d3d9))
|
||||
link += $(if $(findstring video.directdraw,$(ruby)),$(call mklib,ddraw))
|
||||
link += $(if $(findstring video.glx,$(ruby)),$(call mklib,GL))
|
||||
link += $(if $(findstring video.wgl,$(ruby)),$(call mklib,opengl32))
|
||||
link += $(if $(findstring video.xv,$(ruby)),$(call mklib,Xv))
|
||||
link += $(if $(findstring audio.alsa,$(ruby)),$(call mklib,asound))
|
||||
link += $(if $(findstring audio.ao,$(ruby)),$(call mklib,ao))
|
||||
link += $(if $(findstring audio.directsound,$(ruby)),$(call mklib,dsound))
|
||||
link += $(if $(findstring audio.openal,$(ruby)),$(if $(call streq,$(platform),x),$(call mklib,openal),$(call mklib,openal32)))
|
||||
link += $(if $(findstring audio.pulseaudio,$(ruby)),$(call mklib,pulse-simple))
|
||||
link += $(if $(findstring input.directinput,$(ruby)),$(call mklib,dinput8) $(call mklib,dxguid))
|
||||
link += $(if $(findstring input.sdl,$(ruby)),`sdl-config --libs`)
|
||||
link += $(call ifhas,.sdl,$(ruby),`sdl-config --libs`)
|
||||
link += $(call ifhas,video.direct3d,$(ruby),-ld3d9)
|
||||
link += $(call ifhas,video.directdraw,$(ruby),-lddraw)
|
||||
link += $(call ifhas,video.glx,$(ruby),-lGL)
|
||||
link += $(call ifhas,video.wgl,$(ruby),-lopengl32)
|
||||
link += $(call ifhas,video.xv,$(ruby),-lXv)
|
||||
link += $(call ifhas,audio.alsa,$(ruby),-lasound)
|
||||
link += $(call ifhas,audio.ao,$(ruby),-lao)
|
||||
link += $(call ifhas,audio.directsound,$(ruby),-ldsound)
|
||||
link += $(call ifhas,audio.openal,$(ruby),$(if $(call streq,$(platform),x),-lopenal,-lopenal32))
|
||||
link += $(call ifhas,audio.pulseaudio,$(ruby),-lpulse-simple)
|
||||
link += $(call ifhas,input.directinput,$(ruby),-ldinput8 -ldxguid)
|
||||
link += $(call ifhas,input.rawinput,$(ruby),-lxinput -ldinput8 -ldxguid)
|
||||
|
||||
####################################
|
||||
### main target and dependencies ###
|
||||
####################################
|
||||
####################
|
||||
### core objects ###
|
||||
####################
|
||||
|
||||
objects = main libco hiro ruby libfilter string \
|
||||
reader cart cheat \
|
||||
memory smemory cpu scpu smp ssmp sdsp ppu bppu snes \
|
||||
bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010
|
||||
objects = libco ruby libreader libfilter string \
|
||||
system cartridge cheat \
|
||||
memory smemory cpu cpucore scpu smp smpcore ssmp sdsp ppu bppu \
|
||||
sgb 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 += $(call mkdef,GZIP_SUPPORT)
|
||||
flags += -DGZIP_SUPPORT
|
||||
endif
|
||||
|
||||
ifeq ($(enable_jma),true)
|
||||
objects += jma jcrc32 lzmadec 7zlzma iiostrm inbyte lzma winout
|
||||
flags += $(call mkdef,JMA_SUPPORT)
|
||||
flags += -DJMA_SUPPORT
|
||||
endif
|
||||
|
||||
objects := $(patsubst %,obj/%.$(obj),$(objects))
|
||||
rubydef := $(foreach c,$(subst .,_,$(call strupper,$(ruby))),$(call mkdef,$c))
|
||||
|
||||
# Windows resource file
|
||||
ifeq ($(platform),win)
|
||||
objects += obj/resource.$(obj)
|
||||
endif
|
||||
|
||||
################
|
||||
### implicit ###
|
||||
################
|
||||
######################
|
||||
### implicit rules ###
|
||||
######################
|
||||
|
||||
compile = \
|
||||
$(strip \
|
||||
$(if $(filter %.c,$<), \
|
||||
$(c) $1 $(rule), \
|
||||
$(c) $(flags) $1 -c $< -o $@, \
|
||||
$(if $(filter %.cpp,$<), \
|
||||
$(cpp) $1 $(rule) \
|
||||
$(cpp) $(flags) $1 -c $< -o $@ \
|
||||
) \
|
||||
) \
|
||||
)
|
||||
|
||||
%.$(obj): $<; $(call compile)
|
||||
%.o: $<; $(call compile)
|
||||
|
||||
all: build;
|
||||
|
||||
############
|
||||
### main ###
|
||||
############
|
||||
|
||||
obj/main.$(obj) : ui/main.cpp ui/* ui/base/* ui/event/* ui/loader/* ui/settings/*
|
||||
obj/resource.$(obj): ui/bsnes.rc; windres ui/bsnes.rc obj/resource.$(obj)
|
||||
include $(ui)/Makefile
|
||||
objects := $(patsubst %,obj/%.o,$(objects))
|
||||
rubydef := $(foreach c,$(subst .,_,$(call strupper,$(ruby))),-D$c)
|
||||
|
||||
#################
|
||||
### libraries ###
|
||||
#################
|
||||
|
||||
obj/ruby.$(obj): lib/ruby/ruby.cpp lib/ruby/* lib/ruby/video/* lib/ruby/audio/* lib/ruby/input/*
|
||||
obj/ruby.o: lib/ruby/ruby.cpp $(call rwildcard,lib/ruby/*)
|
||||
$(call compile,$(rubydef) $(rubyflags))
|
||||
obj/hiro.$(obj): lib/hiro/hiro.cpp lib/hiro/* lib/hiro/gtk/* lib/hiro/win/*
|
||||
$(call compile,$(if $(call streq,$(platform),x),`pkg-config --cflags gtk+-2.0`))
|
||||
obj/libco.$(obj): lib/libco/libco.c lib/libco/*
|
||||
$(call compile,$(if $(call strne,$(compiler),cl),-static))
|
||||
obj/libfilter.$(obj): lib/libfilter/libfilter.cpp lib/libfilter/*
|
||||
obj/string.$(obj): lib/nall/string.cpp lib/nall/*
|
||||
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/*
|
||||
obj/string.o: lib/nall/string.cpp lib/nall/*
|
||||
|
||||
#################
|
||||
### utilities ###
|
||||
#################
|
||||
|
||||
obj/reader.$(obj): reader/reader.cpp reader/*
|
||||
obj/cart.$(obj) : cart/cart.cpp cart/*
|
||||
obj/cheat.$(obj) : cheat/cheat.cpp cheat/*
|
||||
obj/cartridge.o: cartridge/cartridge.cpp cartridge/*
|
||||
obj/cheat.o : cheat/cheat.cpp cheat/*
|
||||
|
||||
##############
|
||||
### memory ###
|
||||
##############
|
||||
|
||||
obj/memory.$(obj) : memory/memory.cpp memory/*
|
||||
obj/smemory.$(obj): memory/smemory/smemory.cpp memory/smemory/* memory/smemory/mapper/*
|
||||
obj/memory.o : memory/memory.cpp memory/*
|
||||
obj/smemory.o: memory/smemory/smemory.cpp $(call rwildcard,memory/smemory/)
|
||||
|
||||
###########
|
||||
### cpu ###
|
||||
###########
|
||||
|
||||
obj/cpu.$(obj) : cpu/cpu.cpp cpu/*
|
||||
obj/scpu.$(obj): cpu/scpu/scpu.cpp cpu/scpu/* cpu/scpu/core/* cpu/scpu/dma/* cpu/scpu/memory/* cpu/scpu/mmio/* cpu/scpu/timing/*
|
||||
obj/cpu.o : cpu/cpu.cpp cpu/*
|
||||
obj/cpucore.o: cpu/core/core.cpp $(call rwildcard,cpu/core/)
|
||||
obj/scpu.o : cpu/scpu/scpu.cpp $(call rwildcard,cpu/scpu/)
|
||||
|
||||
###########
|
||||
### smp ###
|
||||
###########
|
||||
|
||||
obj/smp.$(obj) : smp/smp.cpp smp/*
|
||||
obj/ssmp.$(obj): smp/ssmp/ssmp.cpp smp/ssmp/* smp/ssmp/core/* smp/ssmp/memory/* smp/ssmp/timing/*
|
||||
obj/smp.o : smp/smp.cpp smp/*
|
||||
obj/smpcore.o: smp/core/core.cpp $(call rwildcard,smp/core/)
|
||||
obj/ssmp.o : smp/ssmp/ssmp.cpp $(call rwildcard,smp/ssmp/)
|
||||
|
||||
###########
|
||||
### dsp ###
|
||||
###########
|
||||
|
||||
obj/adsp.$(obj): dsp/adsp/adsp.cpp dsp/adsp/*
|
||||
obj/sdsp.$(obj): dsp/sdsp/sdsp.cpp dsp/sdsp/*
|
||||
obj/adsp.o: dsp/adsp/adsp.cpp dsp/adsp/*
|
||||
obj/sdsp.o: dsp/sdsp/sdsp.cpp dsp/sdsp/*
|
||||
|
||||
###########
|
||||
### ppu ###
|
||||
###########
|
||||
|
||||
obj/ppu.$(obj) : ppu/ppu.cpp ppu/*
|
||||
obj/bppu.$(obj): ppu/bppu/bppu.cpp ppu/bppu/*
|
||||
obj/ppu.o : ppu/ppu.cpp ppu/*
|
||||
obj/bppu.o: ppu/bppu/bppu.cpp ppu/bppu/*
|
||||
|
||||
############
|
||||
### snes ###
|
||||
############
|
||||
##############
|
||||
### system ###
|
||||
##############
|
||||
|
||||
obj/snes.$(obj): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* snes/input/*
|
||||
obj/system.o: system/system.cpp $(call rwildcard,system/)
|
||||
|
||||
#####################
|
||||
### special chips ###
|
||||
#####################
|
||||
|
||||
obj/bsx.$(obj) : chip/bsx/bsx.cpp chip/bsx/*
|
||||
obj/srtc.$(obj) : chip/srtc/srtc.cpp chip/srtc/*
|
||||
obj/sdd1.$(obj) : chip/sdd1/sdd1.cpp chip/sdd1/*
|
||||
obj/spc7110.$(obj): chip/spc7110/spc7110.cpp chip/spc7110/*
|
||||
obj/cx4.$(obj) : chip/cx4/cx4.cpp chip/cx4/*
|
||||
obj/dsp1.$(obj) : chip/dsp1/dsp1.cpp chip/dsp1/*
|
||||
obj/dsp2.$(obj) : chip/dsp2/dsp2.cpp chip/dsp2/*
|
||||
obj/dsp3.$(obj) : chip/dsp3/dsp3.cpp chip/dsp3/*
|
||||
obj/dsp4.$(obj) : chip/dsp4/dsp4.cpp chip/dsp4/*
|
||||
obj/obc1.$(obj) : chip/obc1/obc1.cpp chip/obc1/*
|
||||
obj/st010.$(obj) : chip/st010/st010.cpp chip/st010/*
|
||||
obj/sgb.o : chip/sgb/sgb.cpp $(call rwildcard,chip/sgb/)
|
||||
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.$(obj) : reader/zlib/adler32.c reader/zlib/*
|
||||
obj/compress.$(obj): reader/zlib/compress.c reader/zlib/*
|
||||
obj/crc32.$(obj) : reader/zlib/crc32.c reader/zlib/*
|
||||
obj/deflate.$(obj) : reader/zlib/deflate.c reader/zlib/*
|
||||
obj/gzio.$(obj) : reader/zlib/gzio.c reader/zlib/*
|
||||
obj/inffast.$(obj) : reader/zlib/inffast.c reader/zlib/*
|
||||
obj/inflate.$(obj) : reader/zlib/inflate.c reader/zlib/*
|
||||
obj/inftrees.$(obj): reader/zlib/inftrees.c reader/zlib/*
|
||||
obj/ioapi.$(obj) : reader/zlib/ioapi.c reader/zlib/*
|
||||
obj/trees.$(obj) : reader/zlib/trees.c reader/zlib/*
|
||||
obj/unzip.$(obj) : reader/zlib/unzip.c reader/zlib/*
|
||||
obj/zip.$(obj) : reader/zlib/zip.c reader/zlib/*
|
||||
obj/zutil.$(obj) : reader/zlib/zutil.c reader/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/*
|
||||
|
||||
###########
|
||||
### jma ###
|
||||
###########
|
||||
##############
|
||||
### libjma ###
|
||||
##############
|
||||
|
||||
obj/jma.$(obj) : reader/jma/jma.cpp reader/jma/*
|
||||
obj/jcrc32.$(obj) : reader/jma/jcrc32.cpp reader/jma/*
|
||||
obj/lzmadec.$(obj): reader/jma/lzmadec.cpp reader/jma/*
|
||||
obj/7zlzma.$(obj) : reader/jma/7zlzma.cpp reader/jma/*
|
||||
obj/iiostrm.$(obj): reader/jma/iiostrm.cpp reader/jma/*
|
||||
obj/inbyte.$(obj) : reader/jma/inbyte.cpp reader/jma/*
|
||||
obj/lzma.$(obj) : reader/jma/lzma.cpp reader/jma/*
|
||||
obj/winout.$(obj) : reader/jma/winout.cpp reader/jma/*
|
||||
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/*
|
||||
|
||||
###############
|
||||
### targets ###
|
||||
###############
|
||||
|
||||
build: $(objects)
|
||||
$(strip $(cpp) $(call mkbin,../bsnes) $(objects) $(link))
|
||||
build: ui_build $(objects)
|
||||
$(strip $(cpp) -o../bsnes $(objects) $(link))
|
||||
|
||||
install:
|
||||
install -D -m 755 ../bsnes $(DESTDIR)$(prefix)/bin/bsnes
|
||||
install -D -m 644 data/bsnes.png $(DESTDIR)$(prefix)/share/icons/bsnes.png
|
||||
install -D -m 644 data/bsnes.png $(DESTDIR)$(prefix)/share/pixmaps/bsnes.png
|
||||
install -D -m 644 data/bsnes.desktop $(DESTDIR)$(prefix)/share/applications/bsnes.desktop
|
||||
|
||||
clean:
|
||||
-@$(call delete,obj/*.$(obj))
|
||||
clean: ui_clean
|
||||
-@$(call delete,obj/*.o)
|
||||
-@$(call delete,*.res)
|
||||
-@$(call delete,*.pgd)
|
||||
-@$(call delete,*.pgc)
|
||||
@@ -266,7 +243,6 @@ help:
|
||||
@echo " gcc - GCC compiler"
|
||||
@echo " mingw32-gcc - MinGW compiler"
|
||||
@echo " i586-mingw32-gcc - MinGW cross compiler"
|
||||
@echo " cl - Visual C++"
|
||||
@echo ""
|
||||
@echo "Available options:"
|
||||
@echo " enable_gzip=[true|false] - Enable ZIP / GZ support (default=false)"
|
||||
@@ -274,3 +250,4 @@ help:
|
||||
@echo ""
|
||||
@echo "Example: $(MAKE) platform=x compiler=gcc enable_gzip=true"
|
||||
@echo ""
|
||||
|
||||
|
15
src/base.hpp
15
src/base.hpp
@@ -1,4 +1,4 @@
|
||||
#define BSNES_VERSION "0.039"
|
||||
#define BSNES_VERSION "0.046"
|
||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||
|
||||
#define BUSCORE sBus
|
||||
@@ -9,12 +9,7 @@
|
||||
|
||||
//S-DSP can be encapsulated into a state machine using #define magic
|
||||
//this avoids ~2.048m co_switch() calls per second (~5% speedup)
|
||||
#define USE_STATE_MACHINE
|
||||
|
||||
//FAST_FRAMESKIP disables calculation of RTO during frameskip
|
||||
//frameskip offers near-zero speedup if RTO is calculated
|
||||
//accuracy is not affected by this define when frameskipping is off
|
||||
#define FAST_FRAMESKIP
|
||||
#define DSP_STATE_MACHINE
|
||||
|
||||
//game genie + pro action replay code support (~2% speed hit)
|
||||
#define CHEAT_SYSTEM
|
||||
@@ -25,12 +20,13 @@
|
||||
#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/property.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/string.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
@@ -40,10 +36,9 @@ 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"
|
||||
|
||||
|
BIN
src/bsnes.lnk
Normal file
BIN
src/bsnes.lnk
Normal file
Binary file not shown.
@@ -1,199 +0,0 @@
|
||||
#include <../base.hpp>
|
||||
#include <../chip/chip.hpp>
|
||||
#include <../reader/reader.hpp>
|
||||
#define CART_CPP
|
||||
|
||||
#include <nall/crc32.hpp>
|
||||
#include <nall/ups.hpp>
|
||||
|
||||
#include "cart.hpp"
|
||||
#include "cart_load.cpp"
|
||||
#include "cart_normal.cpp"
|
||||
#include "cart_bsx.cpp"
|
||||
#include "cart_bsc.cpp"
|
||||
#include "cart_st.cpp"
|
||||
|
||||
#include "cart_file.cpp"
|
||||
#include "cart_header.cpp"
|
||||
|
||||
namespace memory {
|
||||
MappedRAM cartrom, cartram, cartrtc;
|
||||
MappedRAM bscram;
|
||||
MappedRAM stArom, stAram;
|
||||
MappedRAM stBrom, stBram;
|
||||
};
|
||||
|
||||
Cartridge cartridge;
|
||||
|
||||
const char* Cartridge::name() const { return info.filename; }
|
||||
Cartridge::CartridgeMode Cartridge::mode() const { return info.mode; }
|
||||
Cartridge::MemoryMapper Cartridge::mapper() const { return info.mapper; }
|
||||
Cartridge::Region Cartridge::region() const { return info.region; }
|
||||
bool Cartridge::loaded() const { return cart.loaded; }
|
||||
|
||||
void Cartridge::load_begin(CartridgeMode mode) {
|
||||
cart.rom = cart.ram = cart.rtc = 0;
|
||||
bs.ram = 0;
|
||||
stA.rom = stA.ram = 0;
|
||||
stB.rom = stB.ram = 0;
|
||||
|
||||
cart.rom_size = cart.ram_size = cart.rtc_size = 0;
|
||||
bs.ram_size = 0;
|
||||
stA.rom_size = stA.ram_size = 0;
|
||||
stB.rom_size = stB.ram_size = 0;
|
||||
|
||||
info.mode = mode;
|
||||
info.patched = false;
|
||||
|
||||
info.bsxcart = false;
|
||||
info.bsxflash = false;
|
||||
}
|
||||
|
||||
void Cartridge::load_end() {
|
||||
memory::cartrom.map(cart.rom, cart.rom_size);
|
||||
memory::cartram.map(cart.ram, cart.ram_size);
|
||||
memory::cartrtc.map(cart.rtc, cart.rtc_size);
|
||||
memory::bscram.map(bs.ram, bs.ram_size);
|
||||
memory::stArom.map(stA.rom, stA.rom_size);
|
||||
memory::stAram.map(stA.ram, stA.ram_size);
|
||||
memory::stBrom.map(stB.rom, stB.rom_size);
|
||||
memory::stBram.map(stB.ram, stB.ram_size);
|
||||
|
||||
memory::cartrom.write_protect(true);
|
||||
memory::cartram.write_protect(false);
|
||||
memory::bscram.write_protect(true);
|
||||
memory::stArom.write_protect(true);
|
||||
memory::stAram.write_protect(false);
|
||||
memory::stBrom.write_protect(true);
|
||||
memory::stBram.write_protect(false);
|
||||
|
||||
if(file::exists(get_cheat_filename(cart.fn, "cht"))) {
|
||||
cheat.clear();
|
||||
cheat.load(cheatfn);
|
||||
}
|
||||
|
||||
cart.loaded = true;
|
||||
bus.load_cart();
|
||||
}
|
||||
|
||||
bool Cartridge::unload() {
|
||||
if(cart.loaded == false) return false;
|
||||
|
||||
bus.unload_cart();
|
||||
|
||||
switch(info.mode) {
|
||||
case ModeNormal: unload_cart_normal(); break;
|
||||
case ModeBSX: unload_cart_bsx(); break;
|
||||
case ModeBSC: unload_cart_bsc(); break;
|
||||
case ModeSufamiTurbo: unload_cart_st(); break;
|
||||
}
|
||||
|
||||
if(cart.rom) { delete[] cart.rom; cart.rom = 0; }
|
||||
if(cart.ram) { delete[] cart.ram; cart.ram = 0; }
|
||||
if(cart.rtc) { delete[] cart.rtc; cart.rtc = 0; }
|
||||
if(bs.ram) { delete[] bs.ram; bs.ram = 0; }
|
||||
if(stA.rom) { delete[] stA.rom; stA.rom = 0; }
|
||||
if(stA.ram) { delete[] stA.ram; stA.ram = 0; }
|
||||
if(stB.rom) { delete[] stB.rom; stB.rom = 0; }
|
||||
if(stB.ram) { delete[] stB.ram; stB.ram = 0; }
|
||||
|
||||
if(cheat.count() > 0 || file::exists(get_cheat_filename(cart.fn, "cht"))) {
|
||||
cheat.save(cheatfn);
|
||||
cheat.clear();
|
||||
}
|
||||
|
||||
cart.loaded = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Cartridge::Cartridge() {
|
||||
cart.loaded = false;
|
||||
}
|
||||
|
||||
Cartridge::~Cartridge() {
|
||||
if(cart.loaded == true) unload();
|
||||
}
|
||||
|
||||
//==========
|
||||
//cartinfo_t
|
||||
//==========
|
||||
|
||||
void Cartridge::cartinfo_t::reset() {
|
||||
type = TypeUnknown;
|
||||
mapper = LoROM;
|
||||
dsp1_mapper = DSP1Unmapped;
|
||||
region = NTSC;
|
||||
|
||||
rom_size = 0;
|
||||
ram_size = 0;
|
||||
|
||||
bsxslot = 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;
|
||||
}
|
||||
|
||||
//apply cart-specific settings to current cartridge mode settings
|
||||
Cartridge::info_t& Cartridge::info_t::operator=(const Cartridge::cartinfo_t &source) {
|
||||
mapper = source.mapper;
|
||||
dsp1_mapper = source.dsp1_mapper;
|
||||
region = source.region;
|
||||
|
||||
bsxslot = source.bsxslot;
|
||||
superfx = source.superfx;
|
||||
sa1 = source.sa1;
|
||||
srtc = source.srtc;
|
||||
sdd1 = source.sdd1;
|
||||
spc7110 = source.spc7110;
|
||||
spc7110rtc = source.spc7110rtc;
|
||||
cx4 = source.cx4;
|
||||
dsp1 = source.dsp1;
|
||||
dsp2 = source.dsp2;
|
||||
dsp3 = source.dsp3;
|
||||
dsp4 = source.dsp4;
|
||||
obc1 = source.obc1;
|
||||
st010 = source.st010;
|
||||
st011 = source.st011;
|
||||
st018 = source.st018;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//=======
|
||||
//utility
|
||||
//=======
|
||||
|
||||
string Cartridge::filepath(const char *filename, const char *pathname) {
|
||||
//if no pathname, return filename as-is
|
||||
string file(filename);
|
||||
replace(file, "\\", "/");
|
||||
if(!pathname || !*pathname) return file;
|
||||
|
||||
//ensure path ends with trailing '/'
|
||||
string path(pathname);
|
||||
replace(path, "\\", "/");
|
||||
if(!strend(path, "/")) strcat(path, "/");
|
||||
|
||||
//replace relative path with absolute path
|
||||
if(strbegin(path, "./")) {
|
||||
ltrim(path, "./");
|
||||
path = string() << snes.config.path.base << path;
|
||||
}
|
||||
|
||||
//remove folder part of filename
|
||||
lstring part;
|
||||
split(part, "/", file);
|
||||
return path << part[count(part) - 1];
|
||||
}
|
@@ -1,205 +0,0 @@
|
||||
class Cartridge {
|
||||
public:
|
||||
enum CartridgeMode {
|
||||
ModeNormal,
|
||||
ModeBSC,
|
||||
ModeBSX,
|
||||
ModeSufamiTurbo,
|
||||
};
|
||||
|
||||
enum CartridgeType {
|
||||
TypeNormal,
|
||||
TypeBSC,
|
||||
TypeBSXBIOS,
|
||||
TypeBSX,
|
||||
TypeSufamiTurboBIOS,
|
||||
TypeSufamiTurbo,
|
||||
TypeUnknown,
|
||||
};
|
||||
|
||||
enum HeaderField {
|
||||
CartName = 0x00,
|
||||
Mapper = 0x15,
|
||||
RomType = 0x16,
|
||||
RomSize = 0x17,
|
||||
RamSize = 0x18,
|
||||
CartRegion = 0x19,
|
||||
Company = 0x1a,
|
||||
Version = 0x1b,
|
||||
Complement = 0x1c, //inverse checksum
|
||||
Checksum = 0x1e,
|
||||
ResetVector = 0x3c,
|
||||
};
|
||||
|
||||
enum Region {
|
||||
NTSC,
|
||||
PAL,
|
||||
};
|
||||
|
||||
enum MemoryMapper {
|
||||
LoROM,
|
||||
HiROM,
|
||||
ExLoROM,
|
||||
ExHiROM,
|
||||
SPC7110ROM,
|
||||
BSCLoROM,
|
||||
BSCHiROM,
|
||||
BSXROM,
|
||||
STROM,
|
||||
};
|
||||
|
||||
enum DSP1MemoryMapper {
|
||||
DSP1Unmapped,
|
||||
DSP1LoROM1MB,
|
||||
DSP1LoROM2MB,
|
||||
DSP1HiROM,
|
||||
};
|
||||
|
||||
const char* name() const;
|
||||
CartridgeMode mode() const;
|
||||
MemoryMapper mapper() const;
|
||||
Region region() const;
|
||||
|
||||
struct {
|
||||
bool loaded;
|
||||
char fn[PATH_MAX];
|
||||
uint8 *rom, *ram, *rtc;
|
||||
unsigned rom_size, ram_size, rtc_size;
|
||||
} cart;
|
||||
|
||||
struct {
|
||||
char fn[PATH_MAX];
|
||||
uint8 *ram;
|
||||
unsigned ram_size;
|
||||
} bs;
|
||||
|
||||
struct {
|
||||
char fn[PATH_MAX];
|
||||
uint8 *rom, *ram;
|
||||
unsigned rom_size, ram_size;
|
||||
} stA, stB;
|
||||
|
||||
struct cartinfo_t {
|
||||
CartridgeType type;
|
||||
MemoryMapper mapper;
|
||||
DSP1MemoryMapper dsp1_mapper;
|
||||
Region region;
|
||||
|
||||
unsigned rom_size;
|
||||
unsigned ram_size;
|
||||
|
||||
bool bsxslot;
|
||||
bool superfx;
|
||||
bool sa1;
|
||||
bool srtc;
|
||||
bool sdd1;
|
||||
bool spc7110;
|
||||
bool spc7110rtc;
|
||||
bool cx4;
|
||||
bool dsp1;
|
||||
bool dsp2;
|
||||
bool dsp3;
|
||||
bool dsp4;
|
||||
bool obc1;
|
||||
bool st010;
|
||||
bool st011;
|
||||
bool st018;
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
struct info_t {
|
||||
char filename[PATH_MAX * 4];
|
||||
bool patched;
|
||||
|
||||
CartridgeMode mode;
|
||||
MemoryMapper mapper;
|
||||
DSP1MemoryMapper dsp1_mapper;
|
||||
Region region;
|
||||
|
||||
bool bsxcart; //is BS-X cart inserted?
|
||||
bool bsxflash; //is BS-X flash cart inserted into BS-X cart?
|
||||
|
||||
bool bsxslot;
|
||||
bool superfx;
|
||||
bool sa1;
|
||||
bool srtc;
|
||||
bool sdd1;
|
||||
bool spc7110;
|
||||
bool spc7110rtc;
|
||||
bool cx4;
|
||||
bool dsp1;
|
||||
bool dsp2;
|
||||
bool dsp3;
|
||||
bool dsp4;
|
||||
bool obc1;
|
||||
bool st010;
|
||||
bool st011;
|
||||
bool st018;
|
||||
|
||||
info_t& operator=(const cartinfo_t&);
|
||||
} info;
|
||||
|
||||
struct {
|
||||
char fn[PATH_MAX];
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
} image;
|
||||
bool load_image(const char*);
|
||||
bool inspect_image(cartinfo_t &cartinfo, const char *filename);
|
||||
bool load_ram(const char *filename, uint8_t *&data, unsigned size, uint8_t init);
|
||||
|
||||
void load_cart_normal(const char*);
|
||||
void load_cart_bsc(const char*, const char*);
|
||||
void load_cart_bsx(const char*, const char*);
|
||||
void load_cart_st(const char*, const char*, const char*);
|
||||
|
||||
void unload_cart_normal();
|
||||
void unload_cart_bsx();
|
||||
void unload_cart_bsc();
|
||||
void unload_cart_st();
|
||||
|
||||
bool loaded() const;
|
||||
void load_begin(CartridgeMode);
|
||||
void load_end();
|
||||
bool unload();
|
||||
|
||||
void read_header(cartinfo_t &info, const uint8_t *data, unsigned size);
|
||||
unsigned find_header(const uint8_t *data, unsigned size);
|
||||
unsigned score_header(const uint8_t *data, unsigned size, unsigned addr);
|
||||
|
||||
enum CompressionMode {
|
||||
CompressionNone, //always load without compression
|
||||
CompressionInspect, //use file header inspection
|
||||
CompressionAuto, //use file extension or file header inspection (configured by user)
|
||||
};
|
||||
bool load_file(const char *fn, uint8 *&data, unsigned &size, CompressionMode compression = CompressionNone);
|
||||
bool save_file(const char *fn, uint8 *data, unsigned size);
|
||||
bool apply_patch(const uint8_t *pdata, unsigned psize, uint8_t *&data, unsigned &size);
|
||||
char* modify_extension(char *filename, const char *extension);
|
||||
char* get_base_filename(char *filename);
|
||||
char* get_path_filename(char *filename, const char *path, const char *source, const char *extension);
|
||||
char* get_patch_filename(const char *source, const char *extension);
|
||||
char* get_save_filename(const char *source, const char *extension);
|
||||
char* get_cheat_filename(const char *source, const char *extension);
|
||||
|
||||
static string filepath(const char *filename, const char *pathname);
|
||||
|
||||
Cartridge();
|
||||
~Cartridge();
|
||||
|
||||
private:
|
||||
char patchfn[PATH_MAX];
|
||||
char savefn[PATH_MAX];
|
||||
char rtcfn[PATH_MAX];
|
||||
char cheatfn[PATH_MAX];
|
||||
};
|
||||
|
||||
namespace memory {
|
||||
extern MappedRAM cartrom, cartram, cartrtc;
|
||||
extern MappedRAM bscram;
|
||||
extern MappedRAM stArom, stAram;
|
||||
extern MappedRAM stBrom, stBram;
|
||||
};
|
||||
|
||||
extern Cartridge cartridge;
|
@@ -1,44 +0,0 @@
|
||||
#ifdef CART_CPP
|
||||
|
||||
void Cartridge::load_cart_bsc(const char *base, const char *slot) {
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
strcpy(cart.fn, base);
|
||||
strcpy(bs.fn, slot);
|
||||
|
||||
load_begin(ModeBSC);
|
||||
if(load_image(base) == false) return;
|
||||
|
||||
cartinfo_t cartinfo;
|
||||
read_header(cartinfo, cart.rom = image.data, cart.rom_size = image.size);
|
||||
info = cartinfo;
|
||||
|
||||
if(load_image(slot) == true) {
|
||||
info.bsxflash = true;
|
||||
bs.ram = image.data;
|
||||
bs.ram_size = image.size;
|
||||
}
|
||||
|
||||
if(cartinfo.ram_size > 0) {
|
||||
load_ram(get_save_filename(base, "srm"), cart.ram, cart.ram_size = cartinfo.ram_size, 0xff);
|
||||
}
|
||||
|
||||
load_end();
|
||||
|
||||
//set base filename
|
||||
strcpy(info.filename, base);
|
||||
get_base_filename(info.filename);
|
||||
if(*slot) {
|
||||
char filenameBS[PATH_MAX];
|
||||
strcpy(filenameBS, slot);
|
||||
get_base_filename(filenameBS);
|
||||
strcat(info.filename, " + ");
|
||||
strcat(info.filename, filenameBS);
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::unload_cart_bsc() {
|
||||
if(cart.ram) save_file(get_save_filename(cart.fn, "srm"), cart.ram, cart.ram_size);
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,49 +0,0 @@
|
||||
#ifdef CART_CPP
|
||||
|
||||
void Cartridge::load_cart_bsx(const char *base, const char *slot) {
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
strcpy(cart.fn, base);
|
||||
strcpy(bs.fn, slot);
|
||||
|
||||
load_begin(ModeBSX);
|
||||
if(load_image(base) == false) return;
|
||||
info.bsxcart = true;
|
||||
|
||||
cartinfo_t cartinfo;
|
||||
read_header(cartinfo, cart.rom = image.data, cart.rom_size = image.size);
|
||||
info = cartinfo;
|
||||
cart.ram = 0;
|
||||
cart.ram_size = 0;
|
||||
|
||||
memset(bsxcart.sram.handle (), 0x00, bsxcart.sram.size ());
|
||||
memset(bsxcart.psram.handle(), 0x00, bsxcart.psram.size());
|
||||
|
||||
if(load_file(get_save_filename(cart.fn, "srm"), data, size, CompressionNone) == true) {
|
||||
memcpy(bsxcart.sram.handle (), data, min(bsxcart.sram.size (), size));
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
if(load_file(get_save_filename(cart.fn, "psr"), data, size, CompressionNone) == true) {
|
||||
memcpy(bsxcart.psram.handle(), data, min(bsxcart.psram.size(), size));
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
if(load_image(slot)) {
|
||||
info.bsxflash = true;
|
||||
bs.ram = image.data;
|
||||
bs.ram_size = image.size;
|
||||
}
|
||||
|
||||
load_end();
|
||||
|
||||
strcpy(info.filename, !*slot ? base : slot);
|
||||
get_base_filename(info.filename);
|
||||
}
|
||||
|
||||
void Cartridge::unload_cart_bsx() {
|
||||
save_file(get_save_filename(cart.fn, "srm"), bsxcart.sram.handle (), bsxcart.sram.size ());
|
||||
save_file(get_save_filename(cart.fn, "psr"), bsxcart.psram.handle(), bsxcart.psram.size());
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,152 +0,0 @@
|
||||
#ifdef CART_CPP
|
||||
|
||||
#include "../reader/filereader.hpp"
|
||||
|
||||
#if defined(GZIP_SUPPORT)
|
||||
#include "../reader/gzreader.hpp"
|
||||
#include "../reader/zipreader.hpp"
|
||||
#endif
|
||||
|
||||
#if defined(JMA_SUPPORT)
|
||||
#include "../reader/jmareader.hpp"
|
||||
#endif
|
||||
|
||||
char* Cartridge::modify_extension(char *filename, const char *extension) {
|
||||
int i;
|
||||
for(i = strlen(filename); i >= 0; i--) {
|
||||
if(filename[i] == '.') break;
|
||||
if(filename[i] == '/') break;
|
||||
if(filename[i] == '\\') break;
|
||||
}
|
||||
if(i > 0 && filename[i] == '.') filename[i] = 0;
|
||||
strcat(filename, ".");
|
||||
strcat(filename, extension);
|
||||
return filename;
|
||||
}
|
||||
|
||||
//remove directory information and file extension ("/foo/bar.ext" -> "bar")
|
||||
char* Cartridge::get_base_filename(char *filename) {
|
||||
//remove extension
|
||||
for(int i = strlen(filename) - 1; i >= 0; i--) {
|
||||
if(filename[i] == '.') {
|
||||
filename[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//remove directory information
|
||||
for(int i = strlen(filename) - 1; i >= 0; i--) {
|
||||
if(filename[i] == '/' || filename[i] == '\\') {
|
||||
i++;
|
||||
char *output = filename;
|
||||
while(true) {
|
||||
*output++ = filename[i];
|
||||
if(!filename[i]) break;
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
char* Cartridge::get_path_filename(char *filename, const char *path, const char *source, const char *extension) {
|
||||
strcpy(filename, source);
|
||||
modify_extension(filename, extension);
|
||||
strcpy(filename, filepath(filename, path));
|
||||
return filename;
|
||||
}
|
||||
|
||||
char* Cartridge::get_patch_filename(const char *source, const char *extension) {
|
||||
return get_path_filename(patchfn, snes.config.path.patch, source, extension);
|
||||
}
|
||||
|
||||
char* Cartridge::get_save_filename(const char *source, const char *extension) {
|
||||
return get_path_filename(savefn, snes.config.path.save, source, extension);
|
||||
}
|
||||
|
||||
char* Cartridge::get_cheat_filename(const char *source, const char *extension) {
|
||||
return get_path_filename(cheatfn, snes.config.path.cheat, source, extension);
|
||||
}
|
||||
|
||||
bool Cartridge::load_file(const char *fn, uint8 *&data, unsigned &size, CompressionMode compression) {
|
||||
if(file::exists(fn) == false) return false;
|
||||
|
||||
Reader::Type filetype = Reader::Normal;
|
||||
if(compression == CompressionInspect) filetype = Reader::detect(fn, true);
|
||||
if(compression == CompressionAuto) filetype = Reader::detect(fn, snes.config.file.autodetect_type);
|
||||
|
||||
switch(filetype) { default:
|
||||
case Reader::Normal: {
|
||||
FileReader ff(fn);
|
||||
if(!ff.ready()) return false;
|
||||
size = ff.size();
|
||||
data = ff.read();
|
||||
} break;
|
||||
|
||||
#ifdef GZIP_SUPPORT
|
||||
case Reader::GZIP: {
|
||||
GZReader gf(fn);
|
||||
if(!gf.ready()) return false;
|
||||
size = gf.size();
|
||||
data = gf.read();
|
||||
} break;
|
||||
|
||||
case Reader::ZIP: {
|
||||
ZipReader zf(fn);
|
||||
if(!zf.ready()) return false;
|
||||
size = zf.size();
|
||||
data = zf.read();
|
||||
} break;
|
||||
#endif
|
||||
|
||||
#ifdef JMA_SUPPORT
|
||||
case Reader::JMA: {
|
||||
try {
|
||||
JMAReader jf(fn);
|
||||
size = jf.size();
|
||||
data = jf.read();
|
||||
} catch(JMA::jma_errors jma_error) {
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cartridge::apply_patch(const uint8_t *pdata, const unsigned psize, uint8_t *&data, unsigned &size) {
|
||||
uint8_t *outdata = 0;
|
||||
unsigned outsize;
|
||||
ups patcher;
|
||||
ups::result result = patcher.apply(pdata, psize, data, size, outdata, outsize);
|
||||
|
||||
bool apply = false;
|
||||
if(result == ups::ok) apply = true;
|
||||
if(snes.config.file.bypass_patch_crc32 == true) {
|
||||
if(result == ups::input_crc32_invalid) apply = true;
|
||||
if(result == ups::output_crc32_invalid) apply = true;
|
||||
}
|
||||
|
||||
//if patch application was successful, replace old data, size with new data, size
|
||||
if(apply == true) {
|
||||
delete[] data;
|
||||
data = new uint8_t[size = outsize];
|
||||
memcpy(data, outdata, outsize);
|
||||
}
|
||||
|
||||
if(outdata) delete[] outdata;
|
||||
return apply;
|
||||
}
|
||||
|
||||
bool Cartridge::save_file(const char *fn, uint8 *data, unsigned size) {
|
||||
file fp;
|
||||
if(!fp.open(fn, file::mode_write)) return false;
|
||||
fp.write(data, size);
|
||||
fp.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,50 +0,0 @@
|
||||
#ifdef CART_CPP
|
||||
|
||||
bool Cartridge::load_image(const char *filename) {
|
||||
if(!filename || !*filename) return false;
|
||||
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
if(!load_file(filename, data, size, CompressionAuto)) return false;
|
||||
|
||||
if((size & 0x7fff) != 512) {
|
||||
image.data = data;
|
||||
image.size = size;
|
||||
} else {
|
||||
//remove 512-byte header
|
||||
image.data = new uint8_t[image.size = size - 512];
|
||||
memcpy(image.data, data + 512, image.size);
|
||||
}
|
||||
|
||||
if(load_file(get_patch_filename(filename, "ups"), data, size, CompressionInspect) == true) {
|
||||
apply_patch(data, size, image.data, image.size);
|
||||
delete[] data;
|
||||
info.patched = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cartridge::inspect_image(cartinfo_t &cartinfo, const char *filename) {
|
||||
cartinfo.reset();
|
||||
if(!load_image(filename)) return false;
|
||||
|
||||
read_header(cartinfo, image.data, image.size);
|
||||
delete[] image.data;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cartridge::load_ram(const char *filename, uint8_t *&data, unsigned size, uint8_t init) {
|
||||
data = new uint8_t[size];
|
||||
memset(data, init, size);
|
||||
|
||||
uint8_t *savedata;
|
||||
unsigned savesize;
|
||||
if(load_file(filename, savedata, savesize, CompressionNone) == false) return false;
|
||||
|
||||
memcpy(data, savedata, min(size, savesize));
|
||||
delete[] savedata;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,35 +0,0 @@
|
||||
#ifdef CART_CPP
|
||||
|
||||
void Cartridge::load_cart_normal(const char *base) {
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
strcpy(cart.fn, base);
|
||||
|
||||
load_begin(ModeNormal);
|
||||
if(load_image(base) == false) return;
|
||||
|
||||
cartinfo_t cartinfo;
|
||||
read_header(cartinfo, cart.rom = image.data, cart.rom_size = image.size);
|
||||
info = cartinfo;
|
||||
|
||||
if(cartinfo.ram_size > 0) {
|
||||
load_ram(get_save_filename(base, "srm"), cart.ram, cart.ram_size = cartinfo.ram_size, 0xff);
|
||||
}
|
||||
|
||||
if(cartinfo.srtc || cartinfo.spc7110rtc) {
|
||||
load_ram(get_save_filename(base, "rtc"), cart.rtc, cart.rtc_size = 20, 0x00);
|
||||
}
|
||||
|
||||
load_end();
|
||||
|
||||
//set base filename
|
||||
strcpy(info.filename, base);
|
||||
get_base_filename(info.filename);
|
||||
}
|
||||
|
||||
void Cartridge::unload_cart_normal() {
|
||||
if(cart.ram) save_file(get_save_filename(cart.fn, "srm"), cart.ram, cart.ram_size);
|
||||
if(cart.rtc) save_file(get_save_filename(cart.fn, "rtc"), cart.rtc, cart.rtc_size);
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,62 +0,0 @@
|
||||
#ifdef CART_CPP
|
||||
|
||||
void Cartridge::load_cart_st(const char *base, const char *slotA, const char *slotB) {
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
strcpy(cart.fn, base);
|
||||
strcpy(stA.fn, slotA);
|
||||
strcpy(stB.fn, slotB);
|
||||
|
||||
load_begin(ModeSufamiTurbo);
|
||||
if(load_image(base) == false) return;
|
||||
|
||||
cartinfo_t cartinfo;
|
||||
read_header(cartinfo, cart.rom = image.data, cart.rom_size = image.size);
|
||||
info = cartinfo;
|
||||
|
||||
if(load_image(slotA)) {
|
||||
stA.rom = new(zeromemory) uint8_t[stA.rom_size = 0x100000];
|
||||
memcpy(stA.rom, image.data, min(image.size, stA.rom_size));
|
||||
delete[] image.data;
|
||||
|
||||
load_ram(get_save_filename(slotA, "srm"), stA.ram, stA.ram_size = 0x020000, 0xff);
|
||||
}
|
||||
|
||||
if(load_image(slotB)) {
|
||||
stB.rom = new(zeromemory) uint8_t[stB.rom_size = 0x100000];
|
||||
memcpy(stB.rom, image.data, min(image.size, stB.rom_size));
|
||||
delete[] image.data;
|
||||
|
||||
load_ram(get_save_filename(slotB, "srm"), stB.ram, stB.ram_size = 0x020000, 0xff);
|
||||
}
|
||||
|
||||
load_end();
|
||||
|
||||
//set base filename
|
||||
if(!*slotA && !*slotB) {
|
||||
strcpy(info.filename, cart.fn);
|
||||
get_base_filename(info.filename);
|
||||
} else if(*slotA && !*slotB) {
|
||||
strcpy(info.filename, slotA);
|
||||
get_base_filename(info.filename);
|
||||
} else if(!*slotA && *slotB) {
|
||||
strcpy(info.filename, slotB);
|
||||
get_base_filename(info.filename);
|
||||
} else {
|
||||
char filenameA[PATH_MAX], filenameB[PATH_MAX];
|
||||
strcpy(filenameA, slotA);
|
||||
get_base_filename(filenameA);
|
||||
strcpy(filenameB, slotB);
|
||||
get_base_filename(filenameB);
|
||||
strcpy(info.filename, filenameA);
|
||||
strcat(info.filename, " + ");
|
||||
strcat(info.filename, filenameB);
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::unload_cart_st() {
|
||||
if(stA.ram) save_file(get_save_filename(stA.fn, "srm"), stA.ram, stA.ram_size);
|
||||
if(stB.ram) save_file(get_save_filename(stB.fn, "srm"), stB.ram, stB.ram_size);
|
||||
}
|
||||
|
||||
#endif
|
157
src/cartridge/cartridge.cpp
Normal file
157
src/cartridge/cartridge.cpp
Normal file
@@ -0,0 +1,157 @@
|
||||
#include <../base.hpp>
|
||||
|
||||
#define CARTRIDGE_CPP
|
||||
namespace SNES {
|
||||
|
||||
#include "header.cpp"
|
||||
|
||||
namespace memory {
|
||||
MappedRAM cartrom, cartram, cartrtc;
|
||||
MappedRAM bsxflash, bsxram, bsxpram;
|
||||
MappedRAM stArom, stAram;
|
||||
MappedRAM stBrom, stBram;
|
||||
MappedRAM gbrom, gbram;
|
||||
};
|
||||
|
||||
Cartridge cartridge;
|
||||
|
||||
void Cartridge::load(Mode cartridge_mode) {
|
||||
cartinfo_t cartinfo;
|
||||
read_header(cartinfo, memory::cartrom.data(), memory::cartrom.size());
|
||||
set_cartinfo(cartinfo);
|
||||
|
||||
set(mode, cartridge_mode);
|
||||
|
||||
if(cartinfo.ram_size > 0) {
|
||||
memory::cartram.map(new(zeromemory) uint8_t[cartinfo.ram_size], cartinfo.ram_size);
|
||||
}
|
||||
|
||||
if(cartinfo.srtc || cartinfo.spc7110rtc) {
|
||||
memory::cartrtc.map(new(zeromemory) uint8_t[20], 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() == 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() == ModeSuperGameBoy) {
|
||||
if(memory::gbrom.data()) memory::gbram.map(new(zeromemory) uint8_t[64 * 1024], 64 * 1024);
|
||||
}
|
||||
|
||||
memory::cartrom.write_protect(true);
|
||||
memory::cartram.write_protect(false);
|
||||
memory::cartrtc.write_protect(false);
|
||||
memory::bsxflash.write_protect(true);
|
||||
memory::bsxram.write_protect(false);
|
||||
memory::bsxpram.write_protect(false);
|
||||
memory::stArom.write_protect(true);
|
||||
memory::stAram.write_protect(false);
|
||||
memory::stBrom.write_protect(true);
|
||||
memory::stBram.write_protect(false);
|
||||
memory::gbrom.write_protect(true);
|
||||
memory::gbram.write_protect(false);
|
||||
|
||||
bus.load_cart();
|
||||
set(loaded, true);
|
||||
}
|
||||
|
||||
void Cartridge::unload() {
|
||||
memory::cartrom.reset();
|
||||
memory::cartram.reset();
|
||||
memory::cartrtc.reset();
|
||||
memory::bsxflash.reset();
|
||||
memory::bsxram.reset();
|
||||
memory::bsxpram.reset();
|
||||
memory::stArom.reset();
|
||||
memory::stAram.reset();
|
||||
memory::stBrom.reset();
|
||||
memory::stBram.reset();
|
||||
memory::gbrom.reset();
|
||||
memory::gbram.reset();
|
||||
|
||||
if(loaded() == false) return;
|
||||
bus.unload_cart();
|
||||
set(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;
|
||||
}
|
||||
|
||||
Cartridge::Cartridge() {
|
||||
set(loaded, false);
|
||||
unload();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
};
|
||||
|
130
src/cartridge/cartridge.hpp
Normal file
130
src/cartridge/cartridge.hpp
Normal file
@@ -0,0 +1,130 @@
|
||||
class Cartridge : public property {
|
||||
public:
|
||||
enum Mode {
|
||||
ModeNormal,
|
||||
ModeBsxSlotted,
|
||||
ModeBsx,
|
||||
ModeSufamiTurbo,
|
||||
ModeSuperGameBoy,
|
||||
};
|
||||
|
||||
enum Type {
|
||||
TypeNormal,
|
||||
TypeBsxSlotted,
|
||||
TypeBsxBios,
|
||||
TypeBsx,
|
||||
TypeSufamiTurboBios,
|
||||
TypeSufamiTurbo,
|
||||
TypeSuperGameBoyBios,
|
||||
TypeGameBoy,
|
||||
TypeUnknown,
|
||||
};
|
||||
|
||||
enum Region {
|
||||
NTSC,
|
||||
PAL,
|
||||
};
|
||||
|
||||
enum MemoryMapper {
|
||||
LoROM,
|
||||
HiROM,
|
||||
ExLoROM,
|
||||
ExHiROM,
|
||||
SA1ROM,
|
||||
SPC7110ROM,
|
||||
BSCLoROM,
|
||||
BSCHiROM,
|
||||
BSXROM,
|
||||
STROM,
|
||||
};
|
||||
|
||||
enum DSP1MemoryMapper {
|
||||
DSP1Unmapped,
|
||||
DSP1LoROM1MB,
|
||||
DSP1LoROM2MB,
|
||||
DSP1HiROM,
|
||||
};
|
||||
|
||||
//properties can be read via operator(), eg "if(cartridge.loaded() == true)";
|
||||
//warning: if loaded() == false, no other property is considered valid!
|
||||
|
||||
property_t<bool> loaded; //is a base cartridge inserted?
|
||||
|
||||
property_t<Mode> mode;
|
||||
property_t<Region> region;
|
||||
property_t<MemoryMapper> mapper;
|
||||
property_t<DSP1MemoryMapper> dsp1_mapper;
|
||||
|
||||
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;
|
||||
|
||||
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,
|
||||
RomType = 0x16,
|
||||
RomSize = 0x17,
|
||||
RamSize = 0x18,
|
||||
CartRegion = 0x19,
|
||||
Company = 0x1a,
|
||||
Version = 0x1b,
|
||||
Complement = 0x1c, //inverse checksum
|
||||
Checksum = 0x1e,
|
||||
ResetVector = 0x3c,
|
||||
};
|
||||
|
||||
void read_header(cartinfo_t &info, const uint8_t *data, unsigned size) const;
|
||||
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&);
|
||||
};
|
||||
|
||||
namespace memory {
|
||||
extern MappedRAM cartrom, cartram, cartrtc;
|
||||
extern MappedRAM bsxflash, bsxram, bsxpram;
|
||||
extern MappedRAM stArom, stAram;
|
||||
extern MappedRAM stBrom, stBram;
|
||||
extern MappedRAM gbrom, gbram;
|
||||
};
|
||||
|
||||
extern Cartridge cartridge;
|
@@ -1,8 +1,35 @@
|
||||
#ifdef CART_CPP
|
||||
#ifdef CARTRIDGE_CPP
|
||||
|
||||
void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size) {
|
||||
void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size) const {
|
||||
info.reset();
|
||||
unsigned index = find_header(data, size);
|
||||
|
||||
//=====================
|
||||
//detect Game Boy carts
|
||||
//=====================
|
||||
|
||||
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;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned index = find_header(data, size);
|
||||
const uint8 mapper = 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;
|
||||
|
||||
if(data[index + RamSize] & 7) {
|
||||
info.ram_size = 1024 << (data[index + RamSize] & 7);
|
||||
} else {
|
||||
info.ram_size = 0;
|
||||
}
|
||||
|
||||
//0, 1, 13 = NTSC; 2 - 12 = PAL
|
||||
info.region = (region <= 1 || region >= 13) ? NTSC : PAL;
|
||||
|
||||
//=======================
|
||||
//detect BS-X flash carts
|
||||
@@ -13,7 +40,7 @@ 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.type = TypeBsx;
|
||||
info.mapper = BSXROM;
|
||||
info.region = NTSC; //BS-X only released in Japan
|
||||
return;
|
||||
@@ -28,7 +55,7 @@ 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;
|
||||
info.type = TypeSufamiTurboBios;
|
||||
} else {
|
||||
info.type = TypeSufamiTurbo;
|
||||
}
|
||||
@@ -37,38 +64,40 @@ void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size
|
||||
return; //RAM size handled internally by load_cart_st();
|
||||
}
|
||||
|
||||
//==========================
|
||||
//detect Super Game Boy BIOS
|
||||
//==========================
|
||||
|
||||
if(!memcmp(data + index, "Super GAMEBOY", 13)) {
|
||||
info.type = TypeSuperGameBoyBios;
|
||||
return;
|
||||
}
|
||||
|
||||
//=====================
|
||||
//detect standard carts
|
||||
//=====================
|
||||
|
||||
const uint8 mapper = 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;
|
||||
|
||||
//detect presence of BS-X flash cartridge connector (reads extended header information)
|
||||
if(data[index - 14] == 'Z') {
|
||||
if(data[index - 11] == 'J') {
|
||||
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.bsxslot = true;
|
||||
info.bsx_slot = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(info.bsxslot == true) {
|
||||
if(info.bsx_slot == true) {
|
||||
if(!memcmp(data + index, "Satellaview BS-X ", 21)) {
|
||||
//BS-X base cart
|
||||
info.type = TypeBSXBIOS;
|
||||
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
|
||||
} else {
|
||||
//BS-X slotted cart
|
||||
info.type = TypeBSC;
|
||||
info.type = TypeBsxSlotted;
|
||||
info.mapper = (index == 0x7fc0 ? BSCLoROM : BSCHiROM);
|
||||
}
|
||||
} else {
|
||||
@@ -92,8 +121,9 @@ void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size
|
||||
info.superfx = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x23 && (rom_type == 0x34 || rom_type == 0x35)) {
|
||||
if(mapper == 0x23 && (rom_type == 0x32 || rom_type == 0x34 || rom_type == 0x35)) {
|
||||
info.sa1 = true;
|
||||
info.mapper = SA1ROM;
|
||||
}
|
||||
|
||||
if(mapper == 0x35 && rom_type == 0x55) {
|
||||
@@ -163,18 +193,9 @@ void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size
|
||||
if(mapper == 0x30 && rom_type == 0xf5) {
|
||||
info.st018 = true;
|
||||
}
|
||||
|
||||
if(data[index + RamSize] & 7) {
|
||||
info.ram_size = 1024 << (data[index + RamSize] & 7);
|
||||
} else {
|
||||
info.ram_size = 0;
|
||||
}
|
||||
|
||||
//0, 1, 13 = NTSC; 2 - 12 = PAL
|
||||
info.region = (region <= 1 || region >= 13) ? NTSC : PAL;
|
||||
}
|
||||
|
||||
unsigned Cartridge::find_header(const uint8_t *data, unsigned size) {
|
||||
unsigned Cartridge::find_header(const uint8_t *data, unsigned size) const {
|
||||
unsigned score_lo = score_header(data, size, 0x007fc0);
|
||||
unsigned score_hi = score_header(data, size, 0x00ffc0);
|
||||
unsigned score_ex = score_header(data, size, 0x40ffc0);
|
||||
@@ -189,7 +210,7 @@ unsigned Cartridge::find_header(const uint8_t *data, unsigned size) {
|
||||
}
|
||||
}
|
||||
|
||||
unsigned Cartridge::score_header(const uint8_t *data, unsigned size, unsigned addr) {
|
||||
unsigned Cartridge::score_header(const uint8_t *data, unsigned size, unsigned addr) const {
|
||||
if(size < addr + 64) return 0; //image too small to contain header at this location?
|
||||
int score = 0;
|
||||
|
@@ -1,3 +1,3 @@
|
||||
@mingw32-make platform=win compiler=mingw32-gcc
|
||||
::@mingw32-make platform=win compiler=mingw32-gcc enable_gzip=true enable_jma=true
|
||||
@mingw32-make
|
||||
::@mingw32-make enable_gzip=true enable_jma=true
|
||||
@pause
|
||||
|
@@ -1,2 +0,0 @@
|
||||
make platform=x compiler=gcc
|
||||
#make platform=x compiler=gcc enable_gzip=true enable_jma=true
|
@@ -1,5 +1,7 @@
|
||||
#include <../base.hpp>
|
||||
#include <nall/sort.hpp>
|
||||
|
||||
#define CHEAT_CPP
|
||||
namespace SNES {
|
||||
|
||||
Cheat cheat;
|
||||
|
||||
@@ -31,7 +33,7 @@ bool Cheat::decode(const char *s, Cheat::cheat_t &item) const {
|
||||
item.count = 0;
|
||||
|
||||
lstring list;
|
||||
split(list, "+", s);
|
||||
list.split("+", s);
|
||||
|
||||
for(unsigned n = 0; n < list.size(); n++) {
|
||||
unsigned addr;
|
||||
@@ -67,6 +69,28 @@ bool Cheat::read(unsigned addr, uint8_t &data) const {
|
||||
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;
|
||||
}
|
||||
|
||||
void Cheat::enable() {
|
||||
cheat_system_enabled = true;
|
||||
cheat_enabled = (cheat_system_enabled && cheat_enabled_code_exists);
|
||||
}
|
||||
|
||||
void Cheat::disable() {
|
||||
cheat_system_enabled = false;
|
||||
cheat_enabled = false;
|
||||
}
|
||||
|
||||
//================================
|
||||
//cheat list manipulation routines
|
||||
//================================
|
||||
@@ -157,54 +181,38 @@ void Cheat::disable(unsigned i) {
|
||||
//...
|
||||
//===============================
|
||||
|
||||
bool Cheat::load(const char *fn) {
|
||||
string data;
|
||||
if(!fread(data, fn)) return false;
|
||||
replace(data, "\r\n", "\n");
|
||||
qreplace(data, " ", "");
|
||||
void Cheat::load(string data) {
|
||||
data.replace("\r\n", "\n");
|
||||
data.qreplace(" ", "");
|
||||
|
||||
lstring line;
|
||||
split(line, "\n", data);
|
||||
line.split("\n", data);
|
||||
for(unsigned i = 0; i < line.size(); i++) {
|
||||
lstring part;
|
||||
qsplit(part, ",", line[i]);
|
||||
part.qsplit(",", line[i]);
|
||||
if(part.size() != 3) continue;
|
||||
trim(part[0], "\"");
|
||||
add(part[1] == "enabled", /* code = */ part[2], /* desc = */ part[0]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cheat::save(const char *fn) const {
|
||||
file fp;
|
||||
if(!fp.open(fn, file::mode_write)) return false;
|
||||
string Cheat::save() const {
|
||||
string data;
|
||||
for(unsigned i = 0; i < code.size(); i++) {
|
||||
fp.print(string()
|
||||
<< "\"" << code[i].desc << "\", "
|
||||
data << "\"" << code[i].desc << "\", "
|
||||
<< (code[i].enabled ? "enabled, " : "disabled, ")
|
||||
<< code[i].code << "\r\n");
|
||||
<< code[i].code << "\r\n";
|
||||
}
|
||||
fp.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Cheat::sort() {
|
||||
if(code.size() <= 1) return; //nothing to sort?
|
||||
cheat_t *buffer = new cheat_t[code.size()];
|
||||
for(unsigned i = 0; i < code.size(); i++) buffer[i] = code[i];
|
||||
nall::sort(buffer, code.size());
|
||||
for(unsigned i = 0; i < code.size(); i++) code[i] = buffer[i];
|
||||
delete[] buffer;
|
||||
return data;
|
||||
}
|
||||
|
||||
void Cheat::clear() {
|
||||
cheat_system_enabled = false;
|
||||
cheat_enabled_code_exists = false;
|
||||
memset(mask, 0, 0x200000);
|
||||
code.reset();
|
||||
}
|
||||
|
||||
Cheat::Cheat() {
|
||||
Cheat::Cheat() : cheat_system_enabled(true) {
|
||||
clear();
|
||||
}
|
||||
|
||||
@@ -294,17 +302,18 @@ bool Cheat::encode(string &s, unsigned addr, uint8_t data, type_t type) const {
|
||||
}
|
||||
}
|
||||
|
||||
//update_cheat_status() will scan to see if any codes are
|
||||
//enabled. if any are, make sure the cheat system is on.
|
||||
//otherwise, turn cheat system off to speed up emulation.
|
||||
//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_system_enabled = true;
|
||||
cheat_enabled_code_exists = true;
|
||||
cheat_enabled = (cheat_system_enabled && cheat_enabled_code_exists);
|
||||
return;
|
||||
}
|
||||
}
|
||||
cheat_system_enabled = false;
|
||||
cheat_enabled_code_exists = false;
|
||||
cheat_enabled = false;
|
||||
}
|
||||
|
||||
//address lookup table manipulation and mirroring
|
||||
@@ -367,13 +376,16 @@ void Cheat::clear(unsigned addr) {
|
||||
//these two functions are used to safely store description text inside .cfg file format.
|
||||
|
||||
string& Cheat::encode_description(string &desc) const {
|
||||
replace(desc, "\"", "\\q");
|
||||
replace(desc, "\n", "\\n");
|
||||
desc.replace("\"", "\\q");
|
||||
desc.replace("\n", "\\n");
|
||||
return desc;
|
||||
}
|
||||
|
||||
string& Cheat::decode_description(string &desc) const {
|
||||
replace(desc, "\\q", "\"");
|
||||
replace(desc, "\\n", "\n");
|
||||
desc.replace("\\q", "\"");
|
||||
desc.replace("\\n", "\n");
|
||||
return desc;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@@ -21,8 +21,12 @@ public:
|
||||
bool decode(const char *s, cheat_t &item) const;
|
||||
bool read(unsigned addr, uint8_t &data) const;
|
||||
|
||||
inline bool enabled() const { return cheat_system_enabled; }
|
||||
bool enabled() const;
|
||||
void enable();
|
||||
void disable();
|
||||
|
||||
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);
|
||||
@@ -34,16 +38,17 @@ public:
|
||||
void enable(unsigned i);
|
||||
void disable(unsigned i);
|
||||
|
||||
bool load(const char *fn);
|
||||
bool save(const char *fn) const;
|
||||
|
||||
void sort();
|
||||
void load(string data);
|
||||
string save() const;
|
||||
void clear();
|
||||
|
||||
Cheat();
|
||||
|
||||
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;
|
||||
|
||||
|
@@ -1,8 +1,10 @@
|
||||
#include <../base.hpp>
|
||||
#include <../cart/cart.hpp>
|
||||
#define BSX_CPP
|
||||
|
||||
#include "bsx.hpp"
|
||||
#define BSX_CPP
|
||||
namespace SNES {
|
||||
|
||||
#include "bsx_base.cpp"
|
||||
#include "bsx_cart.cpp"
|
||||
#include "bsx_flash.cpp"
|
||||
};
|
||||
|
||||
|
@@ -32,16 +32,10 @@ public:
|
||||
uint8 mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
|
||||
MappedRAM sram;
|
||||
MappedRAM psram;
|
||||
|
||||
BSXCart();
|
||||
~BSXCart();
|
||||
|
||||
private:
|
||||
uint8 *sram_data; //256kbit SRAM
|
||||
uint8 *psram_data; // 4mbit PSRAM
|
||||
|
||||
struct {
|
||||
uint8 r[16];
|
||||
} regs;
|
||||
@@ -56,7 +50,7 @@ public:
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
unsigned size();
|
||||
unsigned size() const;
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#ifdef BSX_CPP
|
||||
|
||||
BSXBase bsxbase;
|
||||
|
||||
void BSXBase::init() {
|
||||
}
|
||||
|
||||
@@ -135,3 +137,4 @@ void BSXBase::mmio_write(unsigned addr, uint8 data) {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#ifdef BSX_CPP
|
||||
|
||||
BSXCart bsxcart;
|
||||
|
||||
void BSXCart::init() {
|
||||
}
|
||||
|
||||
@@ -20,12 +22,14 @@ void BSXCart::reset() {
|
||||
}
|
||||
|
||||
void BSXCart::update_memory_map() {
|
||||
Memory &cart = (regs.r[0x01] & 0x80) == 0x00 ? (Memory&)bsxflash : (Memory&)psram;
|
||||
Memory &cart = (regs.r[0x01] & 0x80) == 0x00 ? (Memory&)bsxflash : (Memory&)memory::bsxpram;
|
||||
|
||||
if((regs.r[0x02] & 0x80) == 0x00) { //LoROM mapping
|
||||
if((regs.r[0x02] & 0x80) == 0x00) {
|
||||
//LoROM mapping
|
||||
bus.map(Bus::MapLinear, 0x00, 0x7d, 0x8000, 0xffff, cart);
|
||||
bus.map(Bus::MapLinear, 0x80, 0xff, 0x8000, 0xffff, cart);
|
||||
} else { //HiROM mapping
|
||||
} else {
|
||||
//HiROM mapping
|
||||
bus.map(Bus::MapShadow, 0x00, 0x3f, 0x8000, 0xffff, cart);
|
||||
bus.map(Bus::MapLinear, 0x40, 0x7d, 0x0000, 0xffff, cart);
|
||||
bus.map(Bus::MapShadow, 0x80, 0xbf, 0x8000, 0xffff, cart);
|
||||
@@ -33,16 +37,16 @@ void BSXCart::update_memory_map() {
|
||||
}
|
||||
|
||||
if(regs.r[0x03] & 0x80) {
|
||||
bus.map(Bus::MapLinear, 0x60, 0x6f, 0x0000, 0xffff, psram);
|
||||
//bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, psram);
|
||||
bus.map(Bus::MapLinear, 0x60, 0x6f, 0x0000, 0xffff, memory::bsxpram);
|
||||
//bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, memory::bsxpram);
|
||||
}
|
||||
|
||||
if((regs.r[0x05] & 0x80) == 0x00) {
|
||||
bus.map(Bus::MapLinear, 0x40, 0x4f, 0x0000, 0xffff, psram);
|
||||
bus.map(Bus::MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::bsxpram);
|
||||
}
|
||||
|
||||
if((regs.r[0x06] & 0x80) == 0x00) {
|
||||
bus.map(Bus::MapLinear, 0x50, 0x5f, 0x0000, 0xffff, psram);
|
||||
bus.map(Bus::MapLinear, 0x50, 0x5f, 0x0000, 0xffff, memory::bsxpram);
|
||||
}
|
||||
|
||||
if(regs.r[0x07] & 0x80) {
|
||||
@@ -53,8 +57,8 @@ void BSXCart::update_memory_map() {
|
||||
bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom);
|
||||
}
|
||||
|
||||
bus.map(Bus::MapShadow, 0x20, 0x3f, 0x6000, 0x7fff, psram);
|
||||
bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, psram);
|
||||
bus.map(Bus::MapShadow, 0x20, 0x3f, 0x6000, 0x7fff, memory::bsxpram);
|
||||
bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, memory::bsxpram);
|
||||
}
|
||||
|
||||
uint8 BSXCart::mmio_read(unsigned addr) {
|
||||
@@ -64,7 +68,7 @@ uint8 BSXCart::mmio_read(unsigned addr) {
|
||||
}
|
||||
|
||||
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM
|
||||
return sram.read(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff));
|
||||
return memory::bsxram.read(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff));
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
@@ -79,21 +83,15 @@ void BSXCart::mmio_write(unsigned addr, uint8 data) {
|
||||
}
|
||||
|
||||
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM
|
||||
return sram.write(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff), data);
|
||||
return memory::bsxram.write(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff), data);
|
||||
}
|
||||
}
|
||||
|
||||
BSXCart::BSXCart() {
|
||||
sram_data = new uint8_t[ 32 * 1024];
|
||||
psram_data = new uint8_t[512 * 1024];
|
||||
|
||||
sram.map (sram_data, 32 * 1024);
|
||||
psram.map(psram_data, 512 * 1024);
|
||||
}
|
||||
|
||||
BSXCart::~BSXCart() {
|
||||
delete[] sram_data;
|
||||
delete[] psram_data;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#ifdef BSX_CPP
|
||||
|
||||
BSXFlash bsxflash;
|
||||
|
||||
void BSXFlash::init() {}
|
||||
void BSXFlash::enable() {}
|
||||
|
||||
@@ -15,10 +17,11 @@ void BSXFlash::reset() {
|
||||
regs.flash_enable = false;
|
||||
regs.read_enable = false;
|
||||
regs.write_enable = false;
|
||||
memory::bsxflash.write_protect(!regs.write_enable);
|
||||
}
|
||||
|
||||
unsigned BSXFlash::size() {
|
||||
return memory::bscram.size();
|
||||
unsigned BSXFlash::size() const {
|
||||
return memory::bsxflash.size();
|
||||
}
|
||||
|
||||
uint8 BSXFlash::read(unsigned addr) {
|
||||
@@ -45,18 +48,18 @@ uint8 BSXFlash::read(unsigned addr) {
|
||||
}
|
||||
}
|
||||
|
||||
return memory::bscram.read(addr);
|
||||
return memory::bsxflash.read(addr);
|
||||
}
|
||||
|
||||
void BSXFlash::write(unsigned addr, uint8 data) {
|
||||
//there exist both read-only and read-write BS-X flash cartridges ...
|
||||
//unfortunately, the vendor info is not stored inside memory dumps
|
||||
//of BS-X flashcarts, so it is impossible to determine whether a
|
||||
//given flashcart is writeable.
|
||||
//however, it has been observed that LoROM-mapped BS-X carts always
|
||||
//use read-write flashcarts, and HiROM-mapped BS-X carts always use
|
||||
//read-only flashcarts.
|
||||
//below is an unfortunately necessary workaround to this problem.
|
||||
//there exist both read-only and read-write BS-X flash cartridges ...
|
||||
//unfortunately, the vendor info is not stored inside memory dumps
|
||||
//of BS-X flashcarts, so it is impossible to determine whether a
|
||||
//given flashcart is writeable.
|
||||
//however, it has been observed that LoROM-mapped BS-X carts always
|
||||
//use read-write flashcarts, and HiROM-mapped BS-X carts always use
|
||||
//read-only flashcarts.
|
||||
//below is an unfortunately necessary workaround to this problem.
|
||||
if(cartridge.mapper() == Cartridge::BSCHiROM) return;
|
||||
|
||||
if((addr & 0xff0000) == 0) {
|
||||
@@ -64,11 +67,11 @@ void BSXFlash::write(unsigned addr, uint8 data) {
|
||||
regs.write_new = data;
|
||||
|
||||
if(regs.write_enable && regs.write_old == regs.write_new) {
|
||||
return memory::bscram.write(addr, data);
|
||||
return memory::bsxflash.write(addr, data);
|
||||
}
|
||||
} else {
|
||||
if(regs.write_enable) {
|
||||
return memory::bscram.write(addr, data);
|
||||
return memory::bsxflash.write(addr, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +110,10 @@ void BSXFlash::write(unsigned addr, uint8 data) {
|
||||
regs.read_enable = false;
|
||||
regs.write_enable = false;
|
||||
}
|
||||
|
||||
memory::bsxflash.write_protect(!regs.write_enable);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#include "sgb/sgb.hpp"
|
||||
#include "sa1/sa1.hpp"
|
||||
#include "bsx/bsx.hpp"
|
||||
#include "srtc/srtc.hpp"
|
||||
#include "sdd1/sdd1.hpp"
|
||||
|
@@ -6,9 +6,12 @@
|
||||
*/
|
||||
|
||||
#include <../base.hpp>
|
||||
#define CX4_CPP
|
||||
|
||||
#include "cx4.hpp"
|
||||
#define CX4_CPP
|
||||
namespace SNES {
|
||||
|
||||
Cx4 cx4;
|
||||
|
||||
#include "cx4data.cpp"
|
||||
#include "cx4fn.cpp"
|
||||
#include "cx4oam.cpp"
|
||||
@@ -30,8 +33,8 @@ uint16 addr = 0x0080 + (r * 3);
|
||||
}
|
||||
|
||||
void Cx4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) {
|
||||
int64 rx = x & 0xffffff;
|
||||
int64 ry = y & 0xffffff;
|
||||
int64_t rx = x & 0xffffff;
|
||||
int64_t ry = y & 0xffffff;
|
||||
if(rx & 0x800000)rx |= ~0x7fffff;
|
||||
if(ry & 0x800000)ry |= ~0x7fffff;
|
||||
|
||||
@@ -195,3 +198,5 @@ void Cx4::reset() {
|
||||
memset(ram, 0, 0x0c00);
|
||||
memset(reg, 0, 0x0100);
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -1,8 +1,10 @@
|
||||
#include <../base.hpp>
|
||||
#include <../cart/cart.hpp>
|
||||
#define DSP1_CPP
|
||||
|
||||
#include "dsp1.hpp"
|
||||
#define DSP1_CPP
|
||||
namespace SNES {
|
||||
|
||||
DSP1 dsp1;
|
||||
|
||||
#include "dsp1emu.cpp"
|
||||
|
||||
void DSP1::init() {}
|
||||
@@ -28,7 +30,7 @@ void DSP1::reset() {
|
||||
* of expected ranges
|
||||
*****/
|
||||
bool DSP1::addr_decode(uint16 addr) {
|
||||
switch(cartridge.info.dsp1_mapper) {
|
||||
switch(cartridge.dsp1_mapper()) {
|
||||
case Cartridge::DSP1LoROM1MB: {
|
||||
//$[20-3f]:[8000-bfff] = DR, $[20-3f]:[c000-ffff] = SR
|
||||
return (addr >= 0xc000);
|
||||
@@ -57,3 +59,5 @@ void DSP1::write(unsigned addr, uint8 data) {
|
||||
dsp1.setDr(data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -1,7 +1,10 @@
|
||||
#include <../base.hpp>
|
||||
#define DSP2_CPP
|
||||
|
||||
#include "dsp2.hpp"
|
||||
#define DSP2_CPP
|
||||
namespace SNES {
|
||||
|
||||
DSP2 dsp2;
|
||||
|
||||
#include "dsp2_op.cpp"
|
||||
|
||||
void DSP2::init() {}
|
||||
@@ -134,3 +137,5 @@ void DSP2::write(unsigned addr, uint8 data) {
|
||||
|
||||
DSP2::DSP2() {}
|
||||
DSP2::~DSP2() {}
|
||||
};
|
||||
|
||||
|
@@ -1,7 +1,10 @@
|
||||
#include <../base.hpp>
|
||||
#define DSP3_CPP
|
||||
|
||||
#include "dsp3.hpp"
|
||||
#define DSP3_CPP
|
||||
namespace SNES {
|
||||
|
||||
DSP3 dsp3;
|
||||
|
||||
namespace DSP3i {
|
||||
#define bool8 uint8
|
||||
#include "dsp3emu.c"
|
||||
@@ -33,3 +36,5 @@ void DSP3::write(unsigned addr, uint8 data) {
|
||||
DSP3i::dsp3_byte = data;
|
||||
DSP3i::DSP3SetByte();
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -1,7 +1,10 @@
|
||||
#include <../base.hpp>
|
||||
#define DSP4_CPP
|
||||
|
||||
#include "dsp4.hpp"
|
||||
#define DSP4_CPP
|
||||
namespace SNES {
|
||||
|
||||
DSP4 dsp4;
|
||||
|
||||
namespace DSP4i {
|
||||
inline uint16 READ_WORD(uint8 *addr) {
|
||||
return (addr[0]) + (addr[1] << 8);
|
||||
@@ -53,3 +56,5 @@ void DSP4::write(unsigned addr, uint8 data) {
|
||||
DSP4i::DSP4SetByte();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -1,6 +1,9 @@
|
||||
#include <../base.hpp>
|
||||
#include <../cart/cart.hpp>
|
||||
#include "obc1.hpp"
|
||||
|
||||
#define OBC1_CPP
|
||||
namespace SNES {
|
||||
|
||||
OBC1 obc1;
|
||||
|
||||
void OBC1::init() {}
|
||||
void OBC1::enable() {}
|
||||
@@ -70,3 +73,6 @@ void OBC1::ram_write(unsigned addr, uint8 data) {
|
||||
|
||||
OBC1::OBC1() {}
|
||||
OBC1::~OBC1() {}
|
||||
|
||||
};
|
||||
|
||||
|
164
src/chip/sa1/bus/bus.cpp
Normal file
164
src/chip/sa1/bus/bus.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
#ifdef SA1_CPP
|
||||
|
||||
SA1Bus sa1bus;
|
||||
|
||||
namespace memory {
|
||||
VectorSelectionPage vectorsp;
|
||||
StaticRAM iram(2048);
|
||||
MappedRAM &bwram = memory::cartram;
|
||||
CC1BWRAM cc1bwram;
|
||||
BitmapRAM bitmapram;
|
||||
}
|
||||
|
||||
void SA1Bus::init() {
|
||||
for(uint32_t i = 0x0000; i <= 0xffff; i++) {
|
||||
map(i << 8, memory::memory_unmapped, 0);
|
||||
}
|
||||
|
||||
for(uint16_t i = 0x2200; i <= 0x23ff; i++) {
|
||||
memory::mmio.map(i, sa1);
|
||||
}
|
||||
|
||||
map(MapLinear, 0x00, 0x3f, 0x0000, 0x07ff, memory::iram);
|
||||
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, 0x8000, 0xffff, memory::cartrom);
|
||||
map(MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::bwram);
|
||||
map(MapLinear, 0x60, 0x6f, 0x0000, 0xffff, memory::bitmapram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x0000, 0x07ff, memory::iram);
|
||||
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, 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, 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, 0x6000, 0x7fff, memory::cc1bwram);
|
||||
bus.map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
|
||||
bus.map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom);
|
||||
|
||||
memory::vectorsp.sync();
|
||||
}
|
||||
|
||||
//===================
|
||||
//VectorSelectionPage
|
||||
//===================
|
||||
|
||||
//this class maps $00:[ff00-ffff] for the purpose of supporting:
|
||||
//$2209.d6 IVSW (S-CPU IRQ vector selection) (0 = cart, 1 = SA-1)
|
||||
//$2209.d4 NVSW (S-CPU NMI vector selection) (0 = cart, 1 = SA-1)
|
||||
//when set, vector addresses are over-ridden with SA-1 register settings:
|
||||
//SIV = S-CPU IRQ vector address override
|
||||
//SNV = S-CPU NMI vector address override
|
||||
//
|
||||
//$00:[ffea-ffeb|ffee-ffef] are special cased on read;
|
||||
//all other addresses return original mapped data.
|
||||
|
||||
uint8_t 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));
|
||||
} break;
|
||||
|
||||
case 0xffee: case 0xffef: {
|
||||
if(sa1.mmio.cpu_ivsw == true) return (sa1.mmio.siv >> ((addr & 1) << 3));
|
||||
} break;
|
||||
}
|
||||
|
||||
return access->read(addr);
|
||||
}
|
||||
|
||||
void VectorSelectionPage::write(unsigned addr, uint8_t data) {
|
||||
return access->write(addr, data);
|
||||
}
|
||||
|
||||
//call this whenever bus is remapped.
|
||||
//note: S-CPU and SA-1 bus always share $00:[ff00-ffff] as cartridge ROM data;
|
||||
//the SA-1 MMC does not allow mapping these independently between processors.
|
||||
//this allows this class to be shared for both, caching only ones' access class.
|
||||
void VectorSelectionPage::sync() {
|
||||
if(bus.page[0x00ff00 >> 8].access != this) {
|
||||
//bus was re-mapped, hook access routine
|
||||
access = bus.page[0x00ff00 >> 8].access;
|
||||
bus.page[0x00ff00 >> 8].access = this;
|
||||
sa1bus.page[0x00ff00 >> 8].access = this;
|
||||
}
|
||||
}
|
||||
|
||||
//========
|
||||
//CC1BWRAM
|
||||
//========
|
||||
|
||||
unsigned CC1BWRAM::size() const {
|
||||
return memory::cartram.size();
|
||||
}
|
||||
|
||||
uint8_t CC1BWRAM::read(unsigned addr) {
|
||||
if(dma) return sa1.dma_cc1_read(addr);
|
||||
return memory::cartram.read(addr);
|
||||
}
|
||||
|
||||
void CC1BWRAM::write(unsigned addr, uint8_t data) {
|
||||
memory::cartram.write(addr, data);
|
||||
}
|
||||
|
||||
//=========
|
||||
//BitmapRAM
|
||||
//=========
|
||||
|
||||
unsigned BitmapRAM::size() const {
|
||||
return 0x100000;
|
||||
}
|
||||
|
||||
uint8_t BitmapRAM::read(unsigned addr) {
|
||||
if(sa1.mmio.bbf == 0) {
|
||||
//4bpp
|
||||
unsigned shift = addr & 1;
|
||||
addr = (addr >> 1) & (memory::cartram.size() - 1);
|
||||
switch(shift) {
|
||||
case 0: return (memory::cartram.read(addr) >> 0) & 15;
|
||||
case 1: return (memory::cartram.read(addr) >> 4) & 15;
|
||||
}
|
||||
} else {
|
||||
//2bpp
|
||||
unsigned shift = addr & 3;
|
||||
addr = (addr >> 2) & (memory::cartram.size() - 1);
|
||||
switch(shift) {
|
||||
case 0: return (memory::cartram.read(addr) >> 0) & 3;
|
||||
case 1: return (memory::cartram.read(addr) >> 2) & 3;
|
||||
case 2: return (memory::cartram.read(addr) >> 4) & 3;
|
||||
case 3: return (memory::cartram.read(addr) >> 6) & 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BitmapRAM::write(unsigned addr, uint8_t data) {
|
||||
if(sa1.mmio.bbf == 0) {
|
||||
//4bpp
|
||||
uint8_t shift = addr & 1;
|
||||
addr = (addr >> 1) & (memory::cartram.size() - 1);
|
||||
switch(shift) {
|
||||
case 0: data = (memory::cartram.read(addr) & 0xf0) | ((data & 15) << 0); break;
|
||||
case 1: data = (memory::cartram.read(addr) & 0x0f) | ((data & 15) << 4); break;
|
||||
}
|
||||
} else {
|
||||
//2bpp
|
||||
uint8_t shift = addr & 3;
|
||||
addr = (addr >> 2) & (memory::cartram.size() - 1);
|
||||
switch(shift) {
|
||||
case 0: data = (memory::cartram.read(addr) & 0xfc) | ((data & 3) << 0); break;
|
||||
case 1: data = (memory::cartram.read(addr) & 0xf3) | ((data & 3) << 2); break;
|
||||
case 2: data = (memory::cartram.read(addr) & 0xcf) | ((data & 3) << 4); break;
|
||||
case 3: data = (memory::cartram.read(addr) & 0x3f) | ((data & 3) << 6); break;
|
||||
}
|
||||
}
|
||||
|
||||
memory::cartram.write(addr, data);
|
||||
}
|
||||
|
||||
#endif
|
31
src/chip/sa1/bus/bus.hpp
Normal file
31
src/chip/sa1/bus/bus.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
struct SA1Bus : Bus {
|
||||
void init();
|
||||
};
|
||||
|
||||
struct VectorSelectionPage : Memory {
|
||||
alwaysinline uint8_t read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8_t);
|
||||
void sync();
|
||||
Memory *access;
|
||||
};
|
||||
|
||||
struct CC1BWRAM : Memory {
|
||||
unsigned size() const;
|
||||
alwaysinline uint8_t read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8_t);
|
||||
bool dma;
|
||||
};
|
||||
|
||||
struct BitmapRAM : Memory {
|
||||
unsigned size() const;
|
||||
alwaysinline uint8_t read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8_t);
|
||||
};
|
||||
|
||||
namespace memory {
|
||||
extern VectorSelectionPage vectorsp;
|
||||
extern StaticRAM iram;
|
||||
extern MappedRAM &bwram;
|
||||
extern CC1BWRAM cc1bwram;
|
||||
extern BitmapRAM bitmapram;
|
||||
}
|
139
src/chip/sa1/dma/dma.cpp
Normal file
139
src/chip/sa1/dma/dma.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
#ifdef SA1_CPP
|
||||
|
||||
//====================
|
||||
//direct data transfer
|
||||
//====================
|
||||
|
||||
void SA1::dma_normal() {
|
||||
while(mmio.dtc--) {
|
||||
uint8_t data = regs.mdr;
|
||||
uint32_t dsa = mmio.dsa++;
|
||||
uint32_t dda = mmio.dda++;
|
||||
|
||||
//source and destination cannot be the same
|
||||
if(mmio.sd == DMA::SourceBWRAM && mmio.dd == DMA::DestBWRAM) continue;
|
||||
if(mmio.sd == DMA::SourceIRAM && mmio.dd == DMA::DestIRAM ) continue;
|
||||
|
||||
switch(mmio.sd) {
|
||||
case DMA::SourceROM: {
|
||||
if((dsa & 0x408000) == 0x008000 || (dsa & 0xc00000) == 0xc00000) {
|
||||
data = sa1bus.read(dsa);
|
||||
}
|
||||
} break;
|
||||
|
||||
case DMA::SourceBWRAM: {
|
||||
if((dsa & 0x40e000) == 0x006000 || (dsa & 0xf00000) == 0x400000) {
|
||||
data = sa1bus.read(dsa);
|
||||
}
|
||||
} break;
|
||||
|
||||
case DMA::SourceIRAM: {
|
||||
data = memory::iram.read(dsa & 0x07ff);
|
||||
} break;
|
||||
}
|
||||
|
||||
switch(mmio.dd) {
|
||||
case DMA::DestBWRAM: {
|
||||
if((dda & 0x40e000) == 0x006000 || (dda & 0xf00000) == 0x400000) {
|
||||
sa1bus.write(dda, data);
|
||||
}
|
||||
} break;
|
||||
|
||||
case DMA::DestIRAM: {
|
||||
memory::iram.write(dda & 0x07ff, data);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
mmio.dma_irqfl = true;
|
||||
if(mmio.dma_irqen) mmio.dma_irqcl = 0;
|
||||
}
|
||||
|
||||
//((byte & 6) << 3) + (byte & 1) explanation:
|
||||
//transforms a byte index (0-7) into a planar index:
|
||||
//result[] = { 0, 1, 16, 17, 32, 33, 48, 49 };
|
||||
//works for 2bpp, 4bpp and 8bpp modes
|
||||
|
||||
//===========================
|
||||
//type-1 character conversion
|
||||
//===========================
|
||||
|
||||
void SA1::dma_cc1() {
|
||||
memory::cc1bwram.dma = true;
|
||||
mmio.chdma_irqfl = true;
|
||||
if(mmio.chdma_irqen) {
|
||||
mmio.chdma_irqcl = 0;
|
||||
cpu.regs.irq = 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t 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;
|
||||
|
||||
if((addr & charmask) == 0) {
|
||||
//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 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;
|
||||
for(unsigned byte = 0; byte < bpp; byte++) {
|
||||
data |= (uint64_t)memory::bwram.read((bwaddr + byte) & bwmask) << (byte << 3);
|
||||
}
|
||||
bwaddr += bpl;
|
||||
|
||||
uint8_t 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;
|
||||
if(mmio.dmacb == 2) continue;
|
||||
out[2] |= (data & 1) << (7 - x); data >>= 1;
|
||||
out[3] |= (data & 1) << (7 - x); data >>= 1;
|
||||
if(mmio.dmacb == 1) continue;
|
||||
out[4] |= (data & 1) << (7 - x); data >>= 1;
|
||||
out[5] |= (data & 1) << (7 - x); data >>= 1;
|
||||
out[6] |= (data & 1) << (7 - x); data >>= 1;
|
||||
out[7] |= (data & 1) << (7 - x); data >>= 1;
|
||||
}
|
||||
|
||||
for(unsigned byte = 0; byte < bpp; byte++) {
|
||||
unsigned p = mmio.dda + (y << 1) + ((byte & 6) << 3) + (byte & 1);
|
||||
memory::iram.write(p & 0x07ff, out[byte]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return memory::iram.read((mmio.dda + (addr & charmask)) & 0x07ff);
|
||||
}
|
||||
|
||||
//===========================
|
||||
//type-2 character conversion
|
||||
//===========================
|
||||
|
||||
void SA1::dma_cc2() {
|
||||
//select register file index (0-7 or 8-15)
|
||||
const uint8_t *brf = &mmio.brf[(dma.line & 1) << 3];
|
||||
unsigned bpp = 2 << (2 - mmio.dmacb);
|
||||
unsigned addr = mmio.dda & 0x07ff;
|
||||
addr &= ~((1 << (7 - mmio.dmacb)) - 1);
|
||||
addr += (dma.line & 8) * bpp;
|
||||
addr += (dma.line & 7) * 2;
|
||||
|
||||
for(unsigned byte = 0; byte < bpp; byte++) {
|
||||
uint8_t output = 0;
|
||||
for(unsigned bit = 0; bit < 8; bit++) {
|
||||
output |= ((brf[bit] >> byte) & 1) << (7 - bit);
|
||||
}
|
||||
memory::iram.write(addr + ((byte & 6) << 3) + (byte & 1), output);
|
||||
}
|
||||
|
||||
dma.line = (dma.line + 1) & 15;
|
||||
}
|
||||
|
||||
#endif
|
11
src/chip/sa1/dma/dma.hpp
Normal file
11
src/chip/sa1/dma/dma.hpp
Normal file
@@ -0,0 +1,11 @@
|
||||
struct DMA {
|
||||
enum CDEN { DmaNormal = 0, DmaCharConversion = 1 };
|
||||
enum SD { SourceROM = 0, SourceBWRAM = 1, SourceIRAM = 2 };
|
||||
enum DD { DestIRAM = 0, DestBWRAM = 1 };
|
||||
unsigned line;
|
||||
} dma;
|
||||
|
||||
void dma_normal();
|
||||
void dma_cc1();
|
||||
uint8_t dma_cc1_read(unsigned addr);
|
||||
void dma_cc2();
|
39
src/chip/sa1/memory/memory.cpp
Normal file
39
src/chip/sa1/memory/memory.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#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) {
|
||||
tick();
|
||||
if(is_bwram(addr)) tick();
|
||||
scheduler.sync_copcpu();
|
||||
return sa1bus.read(addr);
|
||||
}
|
||||
|
||||
void SA1::op_write(unsigned addr, uint8_t data) {
|
||||
tick();
|
||||
if(is_bwram(addr)) tick();
|
||||
scheduler.sync_copcpu();
|
||||
sa1bus.write(addr, data);
|
||||
}
|
||||
|
||||
#undef is_bwram
|
||||
|
||||
#endif
|
4
src/chip/sa1/memory/memory.hpp
Normal file
4
src/chip/sa1/memory/memory.hpp
Normal file
@@ -0,0 +1,4 @@
|
||||
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);
|
631
src/chip/sa1/mmio/mmio.cpp
Normal file
631
src/chip/sa1/mmio/mmio.cpp
Normal file
@@ -0,0 +1,631 @@
|
||||
#ifdef SA1_CPP
|
||||
|
||||
//BS-X flash carts, when present, are mapped to 0x400000+
|
||||
Memory& SA1::mmio_access(unsigned &addr) {
|
||||
if(!memory::bsxflash.data()) return memory::cartrom;
|
||||
if(addr < 0x400000) return memory::cartrom;
|
||||
addr &= 0x3fffff;
|
||||
return bsxflash;
|
||||
}
|
||||
|
||||
//(CCNT) SA-1 control
|
||||
void SA1::mmio_w2200(uint8_t data) {
|
||||
if(mmio.sa1_resb && !(data & 0x80)) {
|
||||
//reset SA-1 CPU
|
||||
regs.pc.w = mmio.crv;
|
||||
regs.pc.b = 0x00;
|
||||
}
|
||||
|
||||
mmio.sa1_irq = (data & 0x80);
|
||||
mmio.sa1_rdyb = (data & 0x40);
|
||||
mmio.sa1_resb = (data & 0x20);
|
||||
mmio.sa1_nmi = (data & 0x10);
|
||||
mmio.smeg = (data & 0x0f);
|
||||
|
||||
if(mmio.sa1_irq) {
|
||||
mmio.sa1_irqfl = true;
|
||||
if(mmio.sa1_irqen) mmio.sa1_irqcl = 0;
|
||||
}
|
||||
|
||||
if(mmio.sa1_nmi) {
|
||||
mmio.sa1_nmifl = true;
|
||||
if(mmio.sa1_nmien) mmio.sa1_nmicl = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//(SIE) S-CPU interrupt enable
|
||||
void SA1::mmio_w2201(uint8_t data) {
|
||||
if(!mmio.cpu_irqen && (data & 0x80)) {
|
||||
if(mmio.cpu_irqfl) {
|
||||
mmio.cpu_irqcl = 0;
|
||||
cpu.regs.irq = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(!mmio.chdma_irqen && (data & 0x20)) {
|
||||
if(mmio.chdma_irqfl) {
|
||||
mmio.chdma_irqcl = 0;
|
||||
cpu.regs.irq = 1;
|
||||
}
|
||||
}
|
||||
|
||||
mmio.cpu_irqen = (data & 0x80);
|
||||
mmio.chdma_irqen = (data & 0x20);
|
||||
}
|
||||
|
||||
//(SIC) S-CPU interrupt clear
|
||||
void SA1::mmio_w2202(uint8_t data) {
|
||||
mmio.cpu_irqcl = (data & 0x80);
|
||||
mmio.chdma_irqcl = (data & 0x20);
|
||||
|
||||
if(mmio.cpu_irqcl ) mmio.cpu_irqfl = false;
|
||||
if(mmio.chdma_irqcl) mmio.chdma_irqfl = false;
|
||||
|
||||
if(!mmio.cpu_irqfl && !mmio.chdma_irqfl) cpu.regs.irq = 0;
|
||||
}
|
||||
|
||||
//(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); }
|
||||
|
||||
//(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); }
|
||||
|
||||
//(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); }
|
||||
|
||||
//(SCNT) S-CPU control
|
||||
void SA1::mmio_w2209(uint8_t data) {
|
||||
mmio.cpu_irq = (data & 0x80);
|
||||
mmio.cpu_ivsw = (data & 0x40);
|
||||
mmio.cpu_nvsw = (data & 0x10);
|
||||
mmio.cmeg = (data & 0x0f);
|
||||
|
||||
if(mmio.cpu_irq) {
|
||||
mmio.cpu_irqfl = true;
|
||||
if(mmio.cpu_irqen) {
|
||||
mmio.cpu_irqcl = 0;
|
||||
cpu.regs.irq = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//(CIE) SA-1 interrupt enable
|
||||
void SA1::mmio_w220a(uint8_t 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;
|
||||
if(!mmio.sa1_nmien && (data & 0x10) && mmio.sa1_nmifl ) mmio.sa1_nmicl = 0;
|
||||
|
||||
mmio.sa1_irqen = (data & 0x80);
|
||||
mmio.timer_irqen = (data & 0x40);
|
||||
mmio.dma_irqen = (data & 0x20);
|
||||
mmio.sa1_nmien = (data & 0x10);
|
||||
}
|
||||
|
||||
//(CIC) SA-1 interrupt clear
|
||||
void SA1::mmio_w220b(uint8_t data) {
|
||||
mmio.sa1_irqcl = (data & 0x80);
|
||||
mmio.timer_irqcl = (data & 0x40);
|
||||
mmio.dma_irqcl = (data & 0x20);
|
||||
mmio.sa1_nmicl = (data & 0x10);
|
||||
|
||||
if(mmio.sa1_irqcl) mmio.sa1_irqfl = false;
|
||||
if(mmio.timer_irqcl) mmio.timer_irqfl = false;
|
||||
if(mmio.dma_irqcl) mmio.dma_irqfl = false;
|
||||
if(mmio.sa1_nmicl) mmio.sa1_nmifl = false;
|
||||
}
|
||||
|
||||
//(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); }
|
||||
|
||||
//(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); }
|
||||
|
||||
//(TMC) H/V timer control
|
||||
void SA1::mmio_w2210(uint8_t 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) {
|
||||
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); }
|
||||
|
||||
//(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); }
|
||||
|
||||
//(CXB) Super MMC bank C
|
||||
void SA1::mmio_w2220(uint8_t data) {
|
||||
mmio.cbmode = (data & 0x80);
|
||||
mmio.cb = (data & 0x07);
|
||||
|
||||
unsigned addr = mmio.cb << 20;
|
||||
Memory &access = mmio_access(addr);
|
||||
|
||||
if(mmio.cbmode == 0) {
|
||||
bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom, 0x000000);
|
||||
sa1bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom, 0x000000);
|
||||
} else {
|
||||
bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, access, addr);
|
||||
sa1bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, access, addr);
|
||||
}
|
||||
|
||||
bus.map(Bus::MapLinear, 0xc0, 0xcf, 0x0000, 0xffff, access, addr);
|
||||
sa1bus.map(Bus::MapLinear, 0xc0, 0xcf, 0x0000, 0xffff, access, addr);
|
||||
|
||||
memory::vectorsp.sync();
|
||||
}
|
||||
|
||||
//(DXB) Super MMC bank D
|
||||
void SA1::mmio_w2221(uint8_t data) {
|
||||
mmio.dbmode = (data & 0x80);
|
||||
mmio.db = (data & 0x07);
|
||||
|
||||
unsigned addr = mmio.db << 20;
|
||||
Memory &access = mmio_access(addr);
|
||||
|
||||
if(mmio.dbmode == 0) {
|
||||
bus.map(Bus::MapLinear, 0x20, 0x3f, 0x8000, 0xffff, memory::cartrom, 0x100000);
|
||||
sa1bus.map(Bus::MapLinear, 0x20, 0x3f, 0x8000, 0xffff, memory::cartrom, 0x100000);
|
||||
} else {
|
||||
bus.map(Bus::MapLinear, 0x20, 0x3f, 0x8000, 0xffff, access, addr);
|
||||
sa1bus.map(Bus::MapLinear, 0x20, 0x3f, 0x8000, 0xffff, access, addr);
|
||||
}
|
||||
|
||||
bus.map(Bus::MapLinear, 0xd0, 0xdf, 0x0000, 0xffff, access, addr);
|
||||
sa1bus.map(Bus::MapLinear, 0xd0, 0xdf, 0x0000, 0xffff, access, addr);
|
||||
}
|
||||
|
||||
//(EXB) Super MMC bank E
|
||||
void SA1::mmio_w2222(uint8_t data) {
|
||||
mmio.ebmode = (data & 0x80);
|
||||
mmio.eb = (data & 0x07);
|
||||
|
||||
unsigned addr = mmio.eb << 20;
|
||||
Memory &access = mmio_access(addr);
|
||||
|
||||
if(mmio.ebmode == 0) {
|
||||
bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom, 0x200000);
|
||||
sa1bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom, 0x200000);
|
||||
} else {
|
||||
bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, access, addr);
|
||||
sa1bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, access, addr);
|
||||
}
|
||||
|
||||
bus.map(Bus::MapLinear, 0xe0, 0xef, 0x0000, 0xffff, access, addr);
|
||||
sa1bus.map(Bus::MapLinear, 0xe0, 0xef, 0x0000, 0xffff, access, addr);
|
||||
}
|
||||
|
||||
//(FXB) Super MMC bank F
|
||||
void SA1::mmio_w2223(uint8_t data) {
|
||||
mmio.fbmode = (data & 0x80);
|
||||
mmio.fb = (data & 0x07);
|
||||
|
||||
unsigned addr = mmio.fb << 20;
|
||||
Memory &access = mmio_access(addr);
|
||||
|
||||
if(mmio.fbmode == 0) {
|
||||
bus.map(Bus::MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, memory::cartrom, 0x300000);
|
||||
sa1bus.map(Bus::MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, memory::cartrom, 0x300000);
|
||||
} else {
|
||||
bus.map(Bus::MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, access, addr);
|
||||
sa1bus.map(Bus::MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, access, addr);
|
||||
}
|
||||
|
||||
bus.map(Bus::MapLinear, 0xf0, 0xff, 0x0000, 0xffff, access, addr);
|
||||
sa1bus.map(Bus::MapLinear, 0xf0, 0xff, 0x0000, 0xffff, access, addr);
|
||||
}
|
||||
|
||||
//(BMAPS) S-CPU BW-RAM address mapping
|
||||
void SA1::mmio_w2224(uint8_t data) {
|
||||
mmio.sbm = (data & 0x1f);
|
||||
|
||||
bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::cc1bwram, mmio.sbm * 0x2000, 0x2000);
|
||||
bus.map(Bus::MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::cc1bwram, mmio.sbm * 0x2000, 0x2000);
|
||||
}
|
||||
|
||||
//(BMAP) SA-1 BW-RAM address mapping
|
||||
void SA1::mmio_w2225(uint8_t 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);
|
||||
} else {
|
||||
//$[60-6f]:[0000-ffff] x 128 projection
|
||||
sa1bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::bitmapram, mmio.cbm * 0x2000, 0x2000);
|
||||
sa1bus.map(Bus::MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::bitmapram, mmio.cbm * 0x2000, 0x2000);
|
||||
}
|
||||
}
|
||||
|
||||
//(SWBE) S-CPU BW-RAM write enable
|
||||
void SA1::mmio_w2226(uint8_t data) {
|
||||
mmio.swen = (data & 0x80);
|
||||
}
|
||||
|
||||
//(CWBE) SA-1 BW-RAM write enable
|
||||
void SA1::mmio_w2227(uint8_t data) {
|
||||
mmio.cwen = (data & 0x80);
|
||||
}
|
||||
|
||||
//(BWPA) BW-RAM write-protected area
|
||||
void SA1::mmio_w2228(uint8_t data) {
|
||||
mmio.bwp = (data & 0x0f);
|
||||
}
|
||||
|
||||
//(SIWP) S-CPU I-RAM write protection
|
||||
void SA1::mmio_w2229(uint8_t data) {
|
||||
mmio.siwp = data;
|
||||
}
|
||||
|
||||
//(CIWP) SA-1 I-RAM write protection
|
||||
void SA1::mmio_w222a(uint8_t data) {
|
||||
mmio.ciwp = data;
|
||||
}
|
||||
|
||||
//(DCNT) DMA control
|
||||
void SA1::mmio_w2230(uint8_t data) {
|
||||
mmio.dmaen = (data & 0x80);
|
||||
mmio.dprio = (data & 0x40);
|
||||
mmio.cden = (data & 0x20);
|
||||
mmio.cdsel = (data & 0x10);
|
||||
mmio.dd = (data & 0x04);
|
||||
mmio.sd = (data & 0x03);
|
||||
|
||||
if(mmio.dmaen == 0) dma.line = 0;
|
||||
}
|
||||
|
||||
//(CDMA) character conversion DMA parameters
|
||||
void SA1::mmio_w2231(uint8_t data) {
|
||||
mmio.chdend = (data & 0x80);
|
||||
mmio.dmasize = (data >> 2) & 7;
|
||||
mmio.dmacb = (data & 0x03);
|
||||
|
||||
if(mmio.chdend) memory::cc1bwram.dma = false;
|
||||
if(mmio.dmasize > 5) mmio.dmasize = 5;
|
||||
if(mmio.dmacb > 2) mmio.dmacb = 2;
|
||||
}
|
||||
|
||||
//(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); }
|
||||
|
||||
//(DDA) DMA destination start address
|
||||
void SA1::mmio_w2235(uint8_t data) {
|
||||
mmio.dda = (mmio.dda & 0xffff00) | (data << 0);
|
||||
}
|
||||
|
||||
void SA1::mmio_w2236(uint8_t data) {
|
||||
mmio.dda = (mmio.dda & 0xff00ff) | (data << 8);
|
||||
|
||||
if(mmio.dmaen == true) {
|
||||
if(mmio.cden == 0 && mmio.dd == DMA::DestIRAM) {
|
||||
dma_normal();
|
||||
} else if(mmio.cden == 1 && mmio.cdsel == 1) {
|
||||
dma_cc1();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SA1::mmio_w2237(uint8_t data) {
|
||||
mmio.dda = (mmio.dda & 0x00ffff) | (data << 16);
|
||||
|
||||
if(mmio.dmaen == true) {
|
||||
if(mmio.cden == 0 && mmio.dd == DMA::DestBWRAM) {
|
||||
dma_normal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//(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); }
|
||||
|
||||
//(BBF) BW-RAM bitmap format
|
||||
void SA1::mmio_w223f(uint8_t 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;
|
||||
if(mmio.dmaen == true) {
|
||||
if(mmio.cden == 1 && mmio.cdsel == 0) {
|
||||
dma_cc2();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
if(mmio.dmaen == true) {
|
||||
if(mmio.cden == 1 && mmio.cdsel == 0) {
|
||||
dma_cc2();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//(MCNT) arithmetic control
|
||||
void SA1::mmio_w2250(uint8_t data) {
|
||||
mmio.acm = (data & 0x02);
|
||||
mmio.md = (data & 0x01);
|
||||
|
||||
if(mmio.acm) mmio.mr = 0;
|
||||
}
|
||||
|
||||
//(MAL) multiplicand / dividend low
|
||||
void SA1::mmio_w2251(uint8_t data) {
|
||||
mmio.ma = (mmio.ma & 0xff00) | data;
|
||||
}
|
||||
|
||||
//(MAH) multiplicand / dividend high
|
||||
void SA1::mmio_w2252(uint8_t data) {
|
||||
mmio.ma = (data << 8) | (mmio.ma & 0x00ff);
|
||||
}
|
||||
|
||||
//(MBL) multiplier / divisor low
|
||||
void SA1::mmio_w2253(uint8_t 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) {
|
||||
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.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;
|
||||
mmio.mr = (remainder << 16) | quotient;
|
||||
}
|
||||
mmio.ma = 0;
|
||||
mmio.mb = 0;
|
||||
}
|
||||
} else {
|
||||
//sigma (accumulative multiplication)
|
||||
mmio.mr += (int16_t)mmio.ma * (int16_t)mmio.mb;
|
||||
mmio.overflow = (mmio.mr >= (1ULL << 40));
|
||||
mmio.mr &= (1ULL << 40) - 1;
|
||||
mmio.mb = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//(VBD) variable-length bit processing
|
||||
void SA1::mmio_w2258(uint8_t data) {
|
||||
mmio.hl = (data & 0x80);
|
||||
mmio.vb = (data & 0x0f);
|
||||
if(mmio.vb == 0) mmio.vb = 16;
|
||||
|
||||
if(mmio.hl == 0) {
|
||||
//fixed mode
|
||||
mmio.vbit += mmio.vb;
|
||||
mmio.va += (mmio.vbit >> 3);
|
||||
mmio.vbit &= 7;
|
||||
}
|
||||
}
|
||||
|
||||
//(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; }
|
||||
|
||||
//(SFR) S-CPU flag read
|
||||
uint8_t SA1::mmio_r2300() {
|
||||
uint8_t data;
|
||||
data = mmio.cpu_irqfl << 7;
|
||||
data |= mmio.cpu_ivsw << 6;
|
||||
data |= mmio.chdma_irqfl << 5;
|
||||
data |= mmio.cpu_nvsw << 4;
|
||||
data |= mmio.cmeg;
|
||||
return data;
|
||||
}
|
||||
|
||||
//(CFR) SA-1 flag read
|
||||
uint8_t SA1::mmio_r2301() {
|
||||
uint8_t data;
|
||||
data = mmio.sa1_irqfl << 7;
|
||||
data |= mmio.timer_irqfl << 6;
|
||||
data |= mmio.dma_irqfl << 5;
|
||||
data |= mmio.sa1_nmifl << 4;
|
||||
data |= mmio.smeg;
|
||||
return data;
|
||||
}
|
||||
|
||||
//(HCR) hcounter read
|
||||
uint8_t 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; }
|
||||
|
||||
//(VCR) vcounter read
|
||||
uint8_t SA1::mmio_r2304() { return mmio.vcr >> 0; }
|
||||
uint8_t 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; }
|
||||
|
||||
//(OF) arithmetic overflow flag
|
||||
uint8_t 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);
|
||||
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);
|
||||
data >>= mmio.vbit;
|
||||
|
||||
if(mmio.hl == 1) {
|
||||
//auto-increment mode
|
||||
mmio.vbit += mmio.vb;
|
||||
mmio.va += (mmio.vbit >> 3);
|
||||
mmio.vbit &= 7;
|
||||
}
|
||||
|
||||
return data >> 8;
|
||||
}
|
||||
|
||||
//(VC) version code register
|
||||
uint8_t SA1::mmio_r230e() {
|
||||
return 0x01; //true value unknown
|
||||
}
|
||||
|
||||
uint8_t SA1::mmio_read(unsigned addr) {
|
||||
addr &= 0xffff;
|
||||
|
||||
switch(addr) {
|
||||
case 0x2300: return mmio_r2300();
|
||||
case 0x2301: return mmio_r2301();
|
||||
case 0x2302: return mmio_r2302();
|
||||
case 0x2303: return mmio_r2303();
|
||||
case 0x2304: return mmio_r2304();
|
||||
case 0x2305: return mmio_r2305();
|
||||
case 0x2306: return mmio_r2306();
|
||||
case 0x2307: return mmio_r2307();
|
||||
case 0x2308: return mmio_r2308();
|
||||
case 0x2309: return mmio_r2309();
|
||||
case 0x230a: return mmio_r230a();
|
||||
case 0x230b: return mmio_r230b();
|
||||
case 0x230c: return mmio_r230c();
|
||||
case 0x230d: return mmio_r230d();
|
||||
case 0x230e: return mmio_r230e();
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void SA1::mmio_write(unsigned addr, uint8_t data) {
|
||||
addr &= 0xffff;
|
||||
|
||||
switch(addr) {
|
||||
case 0x2200: return mmio_w2200(data);
|
||||
case 0x2201: return mmio_w2201(data);
|
||||
case 0x2202: return mmio_w2202(data);
|
||||
case 0x2203: return mmio_w2203(data);
|
||||
case 0x2204: return mmio_w2204(data);
|
||||
case 0x2205: return mmio_w2205(data);
|
||||
case 0x2206: return mmio_w2206(data);
|
||||
case 0x2207: return mmio_w2207(data);
|
||||
case 0x2208: return mmio_w2208(data);
|
||||
case 0x2209: return mmio_w2209(data);
|
||||
case 0x220a: return mmio_w220a(data);
|
||||
case 0x220b: return mmio_w220b(data);
|
||||
case 0x220c: return mmio_w220c(data);
|
||||
case 0x220d: return mmio_w220d(data);
|
||||
case 0x220e: return mmio_w220e(data);
|
||||
case 0x220f: return mmio_w220f(data);
|
||||
|
||||
case 0x2210: return mmio_w2210(data);
|
||||
case 0x2211: return mmio_w2211(data);
|
||||
case 0x2212: return mmio_w2212(data);
|
||||
case 0x2213: return mmio_w2213(data);
|
||||
case 0x2214: return mmio_w2214(data);
|
||||
case 0x2215: return mmio_w2215(data);
|
||||
|
||||
case 0x2220: return mmio_w2220(data);
|
||||
case 0x2221: return mmio_w2221(data);
|
||||
case 0x2222: return mmio_w2222(data);
|
||||
case 0x2223: return mmio_w2223(data);
|
||||
case 0x2224: return mmio_w2224(data);
|
||||
case 0x2225: return mmio_w2225(data);
|
||||
case 0x2226: return mmio_w2226(data);
|
||||
case 0x2227: return mmio_w2227(data);
|
||||
case 0x2228: return mmio_w2228(data);
|
||||
case 0x2229: return mmio_w2229(data);
|
||||
case 0x222a: return mmio_w222a(data);
|
||||
|
||||
case 0x2230: return mmio_w2230(data);
|
||||
case 0x2231: return mmio_w2231(data);
|
||||
case 0x2232: return mmio_w2232(data);
|
||||
case 0x2233: return mmio_w2233(data);
|
||||
case 0x2234: return mmio_w2234(data);
|
||||
case 0x2235: return mmio_w2235(data);
|
||||
case 0x2236: return mmio_w2236(data);
|
||||
case 0x2237: return mmio_w2237(data);
|
||||
case 0x2238: return mmio_w2238(data);
|
||||
case 0x2239: return mmio_w2239(data);
|
||||
|
||||
case 0x223f: return mmio_w223f(data);
|
||||
case 0x2240: return mmio_w2240(data);
|
||||
case 0x2241: return mmio_w2241(data);
|
||||
case 0x2242: return mmio_w2242(data);
|
||||
case 0x2243: return mmio_w2243(data);
|
||||
case 0x2244: return mmio_w2244(data);
|
||||
case 0x2245: return mmio_w2245(data);
|
||||
case 0x2246: return mmio_w2246(data);
|
||||
case 0x2247: return mmio_w2247(data);
|
||||
case 0x2248: return mmio_w2248(data);
|
||||
case 0x2249: return mmio_w2249(data);
|
||||
case 0x224a: return mmio_w224a(data);
|
||||
case 0x224b: return mmio_w224b(data);
|
||||
case 0x224c: return mmio_w224c(data);
|
||||
case 0x224d: return mmio_w224d(data);
|
||||
case 0x224e: return mmio_w224e(data);
|
||||
case 0x224f: return mmio_w224f(data);
|
||||
|
||||
case 0x2250: return mmio_w2250(data);
|
||||
case 0x2251: return mmio_w2251(data);
|
||||
case 0x2252: return mmio_w2252(data);
|
||||
case 0x2253: return mmio_w2253(data);
|
||||
case 0x2254: return mmio_w2254(data);
|
||||
|
||||
case 0x2258: return mmio_w2258(data);
|
||||
case 0x2259: return mmio_w2259(data);
|
||||
case 0x225a: return mmio_w225a(data);
|
||||
case 0x225b: return mmio_w225b(data);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
256
src/chip/sa1/mmio/mmio.hpp
Normal file
256
src/chip/sa1/mmio/mmio.hpp
Normal file
@@ -0,0 +1,256 @@
|
||||
uint8_t mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8_t data);
|
||||
Memory& mmio_access(unsigned &addr);
|
||||
|
||||
struct MMIO {
|
||||
//$2200 CCNT
|
||||
bool sa1_irq;
|
||||
bool sa1_rdyb;
|
||||
bool sa1_resb;
|
||||
bool sa1_nmi;
|
||||
uint8_t smeg;
|
||||
|
||||
//$2201 SIE
|
||||
bool cpu_irqen;
|
||||
bool chdma_irqen;
|
||||
|
||||
//$2202 SIC
|
||||
bool cpu_irqcl;
|
||||
bool chdma_irqcl;
|
||||
|
||||
//$2203,$2204 CRV
|
||||
uint16_t crv;
|
||||
|
||||
//$2205,$2206 CNV
|
||||
uint16_t cnv;
|
||||
|
||||
//$2207,$2208 CIV
|
||||
uint16_t civ;
|
||||
|
||||
//$2209 SCNT
|
||||
bool cpu_irq;
|
||||
bool cpu_ivsw;
|
||||
bool cpu_nvsw;
|
||||
uint8_t cmeg;
|
||||
|
||||
//$220a CIE
|
||||
bool sa1_irqen;
|
||||
bool timer_irqen;
|
||||
bool dma_irqen;
|
||||
bool sa1_nmien;
|
||||
|
||||
//$220b CIC
|
||||
bool sa1_irqcl;
|
||||
bool timer_irqcl;
|
||||
bool dma_irqcl;
|
||||
bool sa1_nmicl;
|
||||
|
||||
//$220c,$220d SNV
|
||||
uint16_t snv;
|
||||
|
||||
//$220e,$220f SIV
|
||||
uint16_t siv;
|
||||
|
||||
//$2210 TMC
|
||||
bool hvselb;
|
||||
bool ven;
|
||||
bool hen;
|
||||
|
||||
//$2212,$2213
|
||||
uint16_t hcnt;
|
||||
|
||||
//$2214,$2215
|
||||
uint16_t vcnt;
|
||||
|
||||
//$2220 CXB
|
||||
bool cbmode;
|
||||
uint8_t cb;
|
||||
|
||||
//$2221 DXB
|
||||
bool dbmode;
|
||||
uint8_t db;
|
||||
|
||||
//$2222 EXB
|
||||
bool ebmode;
|
||||
uint8_t eb;
|
||||
|
||||
//$2223 FXB
|
||||
bool fbmode;
|
||||
uint8_t fb;
|
||||
|
||||
//$2224 BMAPS
|
||||
uint8_t sbm;
|
||||
|
||||
//$2225 BMAP
|
||||
bool sw46;
|
||||
uint8_t cbm;
|
||||
|
||||
//$2226 SBWE
|
||||
bool swen;
|
||||
|
||||
//$2227 CBWE
|
||||
bool cwen;
|
||||
|
||||
//$2228 BWPA
|
||||
uint8_t bwp;
|
||||
|
||||
//$2229 SIWP
|
||||
uint8_t siwp;
|
||||
|
||||
//$222a CIWP
|
||||
uint8_t ciwp;
|
||||
|
||||
//$2230 DCNT
|
||||
bool dmaen;
|
||||
bool dprio;
|
||||
bool cden;
|
||||
bool cdsel;
|
||||
bool dd;
|
||||
uint8_t sd;
|
||||
|
||||
//$2231 CDMA
|
||||
bool chdend;
|
||||
uint8_t dmasize;
|
||||
uint8_t dmacb;
|
||||
|
||||
//$2232-$2234 SDA
|
||||
uint32_t dsa;
|
||||
|
||||
//$2235-$2237 DDA
|
||||
uint32_t dda;
|
||||
|
||||
//$2238,$2239 DTC
|
||||
uint16_t dtc;
|
||||
|
||||
//$223f BBF
|
||||
bool bbf;
|
||||
|
||||
//$2240-224f BRF
|
||||
uint8_t brf[16];
|
||||
|
||||
//$2250 MCNT
|
||||
bool acm;
|
||||
bool md;
|
||||
|
||||
//$2251,$2252 MA
|
||||
uint16_t ma;
|
||||
|
||||
//$2253,$2254 MB
|
||||
uint16_t mb;
|
||||
|
||||
//$2258 VBD
|
||||
bool hl;
|
||||
uint8_t vb;
|
||||
|
||||
//$2259-$225b VDA
|
||||
uint32_t va;
|
||||
uint8_t vbit;
|
||||
|
||||
//$2300 SFR
|
||||
bool cpu_irqfl;
|
||||
bool chdma_irqfl;
|
||||
|
||||
//$2301 CFR
|
||||
bool sa1_irqfl;
|
||||
bool timer_irqfl;
|
||||
bool dma_irqfl;
|
||||
bool sa1_nmifl;
|
||||
|
||||
//$2302,$2303 HCR
|
||||
uint16_t hcr;
|
||||
|
||||
//$2304,$2305 VCR
|
||||
uint16_t vcr;
|
||||
|
||||
//$2306-230a MR
|
||||
uint64_t 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
|
||||
|
||||
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
|
318
src/chip/sa1/sa1.cpp
Normal file
318
src/chip/sa1/sa1.cpp
Normal file
@@ -0,0 +1,318 @@
|
||||
#include <../base.hpp>
|
||||
|
||||
#define SA1_CPP
|
||||
namespace SNES {
|
||||
|
||||
SA1 sa1;
|
||||
|
||||
#include "bus/bus.cpp"
|
||||
#include "dma/dma.cpp"
|
||||
#include "memory/memory.cpp"
|
||||
#include "mmio/mmio.cpp"
|
||||
|
||||
void SA1::enter() {
|
||||
while(true) {
|
||||
while(mmio.sa1_rdyb || mmio.sa1_resb) {
|
||||
//SA-1 co-processor is asleep
|
||||
tick();
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
|
||||
if(status.interrupt_pending) {
|
||||
status.interrupt_pending = false;
|
||||
interrupt(status.interrupt_vector);
|
||||
}
|
||||
|
||||
(this->*opcode_table[op_readpc()])();
|
||||
}
|
||||
}
|
||||
|
||||
void SA1::last_cycle() {
|
||||
if(mmio.sa1_nmi && !mmio.sa1_nmicl) {
|
||||
status.interrupt_pending = true;
|
||||
status.interrupt_vector = mmio.cnv;
|
||||
mmio.sa1_nmifl = true;
|
||||
mmio.sa1_nmicl = 1;
|
||||
regs.wai = false;
|
||||
} else if(!regs.p.i) {
|
||||
if(mmio.timer_irqen && !mmio.timer_irqcl) {
|
||||
status.interrupt_pending = true;
|
||||
status.interrupt_vector = mmio.civ;
|
||||
mmio.timer_irqfl = true;
|
||||
regs.wai = false;
|
||||
} else if(mmio.dma_irqen && !mmio.dma_irqcl) {
|
||||
status.interrupt_pending = true;
|
||||
status.interrupt_vector = mmio.civ;
|
||||
mmio.dma_irqfl = true;
|
||||
regs.wai = false;
|
||||
} else if(mmio.sa1_irq && !mmio.sa1_irqcl) {
|
||||
status.interrupt_pending = true;
|
||||
status.interrupt_vector = mmio.civ;
|
||||
mmio.sa1_irqfl = true;
|
||||
regs.wai = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SA1::interrupt(uint16_t vector) {
|
||||
op_read(regs.pc.d);
|
||||
op_io();
|
||||
if(!regs.e) op_writestack(regs.pc.b);
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestack(regs.e ? (regs.p & ~0x10) : regs.p);
|
||||
regs.pc.w = vector;
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
}
|
||||
|
||||
bool SA1::interrupt_pending() {
|
||||
return status.interrupt_pending;
|
||||
}
|
||||
|
||||
void SA1::tick() {
|
||||
scheduler.addclocks_cop(2);
|
||||
|
||||
//adjust counters:
|
||||
//note that internally, status counters are in clocks;
|
||||
//whereas MMIO register counters are in dots (4 clocks = 1 dot)
|
||||
if(mmio.hvselb == 0) {
|
||||
//HV timer
|
||||
status.hcounter += 2;
|
||||
if(status.hcounter >= 1364) {
|
||||
status.hcounter = 0;
|
||||
if(++status.vcounter >= status.scanlines) status.vcounter = 0;
|
||||
}
|
||||
} else {
|
||||
//linear timer
|
||||
status.hcounter += 2;
|
||||
status.vcounter += (status.hcounter >> 11);
|
||||
status.hcounter &= 0x07ff;
|
||||
status.vcounter &= 0x01ff;
|
||||
}
|
||||
|
||||
//test counters for timer IRQ
|
||||
switch((mmio.ven << 1) + (mmio.hen << 0)) {
|
||||
case 0: break;
|
||||
case 1: if(status.hcounter == (mmio.hcnt << 2)) trigger_irq(); break;
|
||||
case 2: if(status.vcounter == mmio.vcnt && status.hcounter == 0) trigger_irq(); break;
|
||||
case 3: if(status.vcounter == mmio.hcnt && status.hcounter == (mmio.hcnt << 2)) trigger_irq(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void SA1::trigger_irq() {
|
||||
mmio.timer_irqfl = true;
|
||||
if(mmio.timer_irqen) mmio.timer_irqcl = 0;
|
||||
}
|
||||
|
||||
void SA1::init() {
|
||||
}
|
||||
|
||||
void SA1::enable() {
|
||||
}
|
||||
|
||||
void SA1::power() {
|
||||
regs.a = regs.x = regs.y = 0x0000;
|
||||
regs.s = 0x01ff;
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
void SA1::reset() {
|
||||
memory::vectorsp.access = 0;
|
||||
memory::cc1bwram.dma = false;
|
||||
for(unsigned addr = 0; addr < memory::iram.size(); addr++) {
|
||||
memory::iram.write(addr, 0x00);
|
||||
}
|
||||
sa1bus.init();
|
||||
|
||||
regs.pc.d = 0x000000;
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
regs.s.h = 0x01;
|
||||
regs.d = 0x0000;
|
||||
regs.db = 0x00;
|
||||
regs.p = 0x34;
|
||||
regs.e = 1;
|
||||
regs.mdr = 0x00;
|
||||
regs.wai = false;
|
||||
update_table();
|
||||
|
||||
status.interrupt_pending = false;
|
||||
status.interrupt_vector = 0x0000;
|
||||
|
||||
status.scanlines = (system.region() == System::NTSC ? 262 : 312);
|
||||
status.vcounter = 0;
|
||||
status.hcounter = 0;
|
||||
|
||||
dma.line = 0;
|
||||
|
||||
//$2200 CCNT
|
||||
mmio.sa1_irq = false;
|
||||
mmio.sa1_rdyb = false;
|
||||
mmio.sa1_resb = true;
|
||||
mmio.sa1_nmi = false;
|
||||
mmio.smeg = 0;
|
||||
|
||||
//$2201 SIE
|
||||
mmio.cpu_irqen = false;
|
||||
mmio.chdma_irqen = false;
|
||||
|
||||
//$2202 SIC
|
||||
mmio.cpu_irqcl = false;
|
||||
mmio.chdma_irqcl = false;
|
||||
|
||||
//$2203,$2204 CRV
|
||||
mmio.crv = 0x0000;
|
||||
|
||||
//$2205,$2206 CNV
|
||||
mmio.cnv = 0x0000;
|
||||
|
||||
//$2207,$2208 CIV
|
||||
mmio.civ = 0x0000;
|
||||
|
||||
//$2209 SCNT
|
||||
mmio.cpu_irq = false;
|
||||
mmio.cpu_ivsw = false;
|
||||
mmio.cpu_nvsw = false;
|
||||
mmio.cmeg = 0;
|
||||
|
||||
//$220a CIE
|
||||
mmio.sa1_irqen = false;
|
||||
mmio.timer_irqen = false;
|
||||
mmio.dma_irqen = false;
|
||||
mmio.sa1_nmien = false;
|
||||
|
||||
//$220b CIC
|
||||
mmio.sa1_irqcl = false;
|
||||
mmio.timer_irqcl = false;
|
||||
mmio.dma_irqcl = false;
|
||||
mmio.sa1_nmicl = false;
|
||||
|
||||
//$220c,$220d SNV
|
||||
mmio.snv = 0x0000;
|
||||
|
||||
//$220e,$220f SIV
|
||||
mmio.siv = 0x0000;
|
||||
|
||||
//$2210
|
||||
mmio.hvselb = false;
|
||||
mmio.ven = false;
|
||||
mmio.hen = false;
|
||||
|
||||
//$2212,$2213 HCNT
|
||||
mmio.hcnt = 0x0000;
|
||||
|
||||
//$2214,$2215 VCNT
|
||||
mmio.vcnt = 0x0000;
|
||||
|
||||
//$2220-2223 CXB, DXB, EXB, FXB
|
||||
mmio.cbmode = 0;
|
||||
mmio.dbmode = 0;
|
||||
mmio.ebmode = 0;
|
||||
mmio.fbmode = 0;
|
||||
|
||||
mmio.cb = 0x00;
|
||||
mmio.db = 0x01;
|
||||
mmio.eb = 0x02;
|
||||
mmio.fb = 0x03;
|
||||
|
||||
//$2224 BMAPS
|
||||
mmio.sbm = 0x00;
|
||||
|
||||
//$2225 BMAP
|
||||
mmio.sw46 = false;
|
||||
mmio.cbm = 0x00;
|
||||
|
||||
//$2226 SWBE
|
||||
mmio.swen = false;
|
||||
|
||||
//$2227 CWBE
|
||||
mmio.cwen = false;
|
||||
|
||||
//$2228 BWPA
|
||||
mmio.bwp = 0x0f;
|
||||
|
||||
//$2229 SIWP
|
||||
mmio.siwp = 0x00;
|
||||
|
||||
//$222a CIWP
|
||||
mmio.ciwp = 0x00;
|
||||
|
||||
//$2230 DCNT
|
||||
mmio.dmaen = false;
|
||||
mmio.dprio = false;
|
||||
mmio.cden = false;
|
||||
mmio.cdsel = false;
|
||||
mmio.dd = 0;
|
||||
mmio.sd = 0;
|
||||
|
||||
//$2231 CDMA
|
||||
mmio.chdend = false;
|
||||
mmio.dmasize = 0;
|
||||
mmio.dmacb = 0;
|
||||
|
||||
//$2232-$2234 SDA
|
||||
mmio.dsa = 0x000000;
|
||||
|
||||
//$2235-$2237 DDA
|
||||
mmio.dda = 0x000000;
|
||||
|
||||
//$2238,$2239 DTC
|
||||
mmio.dtc = 0x0000;
|
||||
|
||||
//$223f BBF
|
||||
mmio.bbf = 0;
|
||||
|
||||
//$2240-$224f BRF
|
||||
for(unsigned i = 0; i < 16; i++) {
|
||||
mmio.brf[i] = 0x00;
|
||||
}
|
||||
|
||||
//$2250 MCNT
|
||||
mmio.acm = 0;
|
||||
mmio.md = 0;
|
||||
|
||||
//$2251,$2252 MA
|
||||
mmio.ma = 0x0000;
|
||||
|
||||
//$2253,$2254 MB
|
||||
mmio.mb = 0x0000;
|
||||
|
||||
//$2258 VBD
|
||||
mmio.hl = false;
|
||||
mmio.vb = 16;
|
||||
|
||||
//$2259-$225b
|
||||
mmio.va = 0x000000;
|
||||
mmio.vbit = 0;
|
||||
|
||||
//$2300 SFR
|
||||
mmio.cpu_irqfl = false;
|
||||
mmio.chdma_irqfl = false;
|
||||
|
||||
//$2301 CFR
|
||||
mmio.sa1_irqfl = false;
|
||||
mmio.timer_irqfl = false;
|
||||
mmio.dma_irqfl = false;
|
||||
mmio.sa1_nmifl = false;
|
||||
|
||||
//$2302,$2303 HCR
|
||||
mmio.hcr = 0x0000;
|
||||
|
||||
//$2304,$2305 VCR
|
||||
mmio.vcr = 0x0000;
|
||||
|
||||
//$2306-$230a MR
|
||||
mmio.mr = 0;
|
||||
|
||||
//$230b
|
||||
mmio.overflow = false;
|
||||
}
|
||||
|
||||
SA1::SA1() {
|
||||
}
|
||||
|
||||
};
|
||||
|
35
src/chip/sa1/sa1.hpp
Normal file
35
src/chip/sa1/sa1.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "bus/bus.hpp"
|
||||
|
||||
class SA1 : public CPUcore, public MMIO {
|
||||
public:
|
||||
#include "dma/dma.hpp"
|
||||
#include "memory/memory.hpp"
|
||||
#include "mmio/mmio.hpp"
|
||||
|
||||
struct Status {
|
||||
bool interrupt_pending;
|
||||
uint16_t interrupt_vector;
|
||||
|
||||
uint16_t scanlines;
|
||||
uint16_t vcounter;
|
||||
uint16_t hcounter;
|
||||
} status;
|
||||
|
||||
void enter();
|
||||
void interrupt(uint16_t vector);
|
||||
void tick();
|
||||
|
||||
alwaysinline void trigger_irq();
|
||||
alwaysinline void last_cycle();
|
||||
alwaysinline bool interrupt_pending();
|
||||
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
SA1();
|
||||
};
|
||||
|
||||
extern SA1 sa1;
|
||||
extern SA1Bus sa1bus;
|
@@ -1,8 +1,10 @@
|
||||
#include <../base.hpp>
|
||||
#include <../cart/cart.hpp>
|
||||
#define SDD1_CPP
|
||||
|
||||
#include "sdd1.hpp"
|
||||
#define SDD1_CPP
|
||||
namespace SNES {
|
||||
|
||||
SDD1 sdd1;
|
||||
|
||||
#include "sdd1emu.cpp"
|
||||
|
||||
void SDD1::init() {}
|
||||
@@ -11,7 +13,7 @@ void SDD1::enable() {
|
||||
//hook S-CPU DMA MMIO registers to gather information for struct dma[];
|
||||
//buffer address and transfer size information for use in SDD1::read()
|
||||
for(unsigned i = 0x4300; i <= 0x437f; i++) {
|
||||
cpu_mmio[i & 0x7f] = memory::mmio.get(i);
|
||||
cpu_mmio[i & 0x7f] = memory::mmio.mmio[i - 0x2000];
|
||||
memory::mmio.map(i, *this);
|
||||
}
|
||||
|
||||
@@ -156,3 +158,5 @@ SDD1::SDD1() {
|
||||
SDD1::~SDD1() {
|
||||
delete[] buffer.data;
|
||||
}
|
||||
};
|
||||
|
||||
|
66
src/chip/sgb/sgb.cpp
Normal file
66
src/chip/sgb/sgb.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#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();
|
||||
}
|
||||
|
||||
};
|
||||
|
28
src/chip/sgb/sgb.hpp
Normal file
28
src/chip/sgb/sgb.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
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;
|
||||
|
@@ -1,8 +1,10 @@
|
||||
#include <../base.hpp>
|
||||
#include <../cart/cart.hpp>
|
||||
#define SPC7110_CPP
|
||||
|
||||
#include "spc7110.hpp"
|
||||
#define SPC7110_CPP
|
||||
namespace SNES {
|
||||
|
||||
SPC7110 spc7110;
|
||||
|
||||
#include "decomp.cpp"
|
||||
|
||||
const unsigned SPC7110::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
@@ -10,7 +12,7 @@ const unsigned SPC7110::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 3
|
||||
void SPC7110::init() {}
|
||||
|
||||
void SPC7110::enable() {
|
||||
uint16_t limit = (cartridge.info.spc7110rtc ? 0x4842 : 0x483f);
|
||||
uint16_t limit = (cartridge.has_spc7110rtc() ? 0x4842 : 0x483f);
|
||||
for(uint16_t i = 0x4800; i <= limit; i++) memory::mmio.map(i, *this);
|
||||
}
|
||||
|
||||
@@ -74,7 +76,7 @@ void SPC7110::reset() {
|
||||
r4841 = 0x00;
|
||||
r4842 = 0x00;
|
||||
|
||||
if(cartridge.info.spc7110rtc) {
|
||||
if(cartridge.has_spc7110rtc()) {
|
||||
rtc_state = RTCS_Inactive;
|
||||
rtc_mode = RTCM_Linear;
|
||||
rtc_index = 0;
|
||||
@@ -99,7 +101,7 @@ void SPC7110::update_time(int offset) {
|
||||
| (memory::cartrtc.read(17) << 8)
|
||||
| (memory::cartrtc.read(18) << 16)
|
||||
| (memory::cartrtc.read(19) << 24);
|
||||
time_t current_time = time(0);
|
||||
time_t current_time = time(0) - offset;
|
||||
|
||||
//sizeof(time_t) is platform-dependent; though memory::cartrtc needs to be platform-agnostic.
|
||||
//yet platforms with 32-bit signed time_t will overflow every ~68 years. handle this by
|
||||
@@ -670,3 +672,6 @@ void SPC7110::write(unsigned addr, uint8 data) {
|
||||
|
||||
SPC7110::SPC7110() {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@@ -1,6 +1,9 @@
|
||||
#include <../base.hpp>
|
||||
#include <../cart/cart.hpp>
|
||||
#include "srtc.hpp"
|
||||
|
||||
#define SRTC_CPP
|
||||
namespace SNES {
|
||||
|
||||
SRTC srtc;
|
||||
|
||||
const unsigned SRTC::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
@@ -224,3 +227,6 @@ void SRTC::mmio_write(unsigned addr, uint8 data) {
|
||||
|
||||
SRTC::SRTC() {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@@ -1,7 +1,10 @@
|
||||
#include <../base.hpp>
|
||||
#define ST010_CPP
|
||||
|
||||
#include "st010.hpp"
|
||||
#define ST010_CPP
|
||||
namespace SNES {
|
||||
|
||||
ST010 st010;
|
||||
|
||||
#include "st010_data.hpp"
|
||||
#include "st010_op.cpp"
|
||||
|
||||
@@ -85,3 +88,5 @@ void ST010::write(unsigned addr, uint8 data) {
|
||||
ram[0x0021] &= ~0x80;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -1 +1 @@
|
||||
@mingw32-make platform=win compiler=mingw32-gcc clean
|
||||
@mingw32-make clean
|
||||
|
@@ -1 +0,0 @@
|
||||
make platform=x compiler=gcc clean
|
3
src/cpu/core/bpp.sh
Normal file
3
src/cpu/core/bpp.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
clear
|
||||
bpp opcode_functions.cpp opcode_functions.bpp
|
||||
bpp opcode_headers.hpp opcode_headers.bpp
|
51
src/cpu/core/core.cpp
Normal file
51
src/cpu/core/core.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include <../base.hpp>
|
||||
|
||||
#define CPUCORE_CPP
|
||||
namespace SNES {
|
||||
|
||||
#include "opcode_algorithms.cpp"
|
||||
#include "opcode_functions.cpp"
|
||||
#include "opcode_tables.cpp"
|
||||
#include "disasm/disasm.cpp"
|
||||
|
||||
//immediate, 2-cycle opcodes with I/O cycle will become bus read
|
||||
//when an IRQ is to be triggered immediately after opcode completion.
|
||||
//this affects the following opcodes:
|
||||
// clc, cld, cli, clv, sec, sed, sei,
|
||||
// tax, tay, txa, txy, tya, tyx,
|
||||
// tcd, tcs, tdc, tsc, tsx, txs,
|
||||
// inc, inx, iny, dec, dex, dey,
|
||||
// asl, lsr, rol, ror, nop, xce.
|
||||
alwaysinline void CPUcore::op_io_irq() {
|
||||
if(interrupt_pending()) {
|
||||
//modify I/O cycle to bus read cycle, do not increment PC
|
||||
op_read(regs.pc.d);
|
||||
} else {
|
||||
op_io();
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void CPUcore::op_io_cond2() {
|
||||
if(regs.d.l != 0x00) {
|
||||
op_io();
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void CPUcore::op_io_cond4(uint16 x, uint16 y) {
|
||||
if(!regs.p.x || (x & 0xff00) != (y & 0xff00)) {
|
||||
op_io();
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void CPUcore::op_io_cond6(uint16 addr) {
|
||||
if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) {
|
||||
op_io();
|
||||
}
|
||||
}
|
||||
|
||||
CPUcore::CPUcore() {
|
||||
initialize_opcode_table();
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -1,11 +1,25 @@
|
||||
class CPUcore {
|
||||
public:
|
||||
#include "registers.hpp"
|
||||
#include "memory.hpp"
|
||||
#include "opcode_headers.hpp"
|
||||
#include "disasm/disasm.hpp"
|
||||
|
||||
regs_t regs;
|
||||
reg24_t aa, rd;
|
||||
uint8_t dp, sp;
|
||||
uint8_t sp, dp;
|
||||
|
||||
void op_irq();
|
||||
virtual void op_io() = 0;
|
||||
virtual uint8_t op_read(uint32_t addr) = 0;
|
||||
virtual void op_write(uint32_t addr, uint8_t data) = 0;
|
||||
virtual void last_cycle() = 0;
|
||||
virtual bool interrupt_pending() = 0;
|
||||
|
||||
inline bool in_opcode() { return status.in_opcode; }
|
||||
void op_io_irq();
|
||||
void op_io_cond2();
|
||||
void op_io_cond4(uint16 x, uint16 y);
|
||||
void op_io_cond6(uint16 addr);
|
||||
|
||||
//op_read
|
||||
void op_adc_b();
|
||||
void op_adc_w();
|
||||
void op_and_b();
|
||||
@@ -30,7 +44,7 @@
|
||||
void op_ora_w();
|
||||
void op_sbc_b();
|
||||
void op_sbc_w();
|
||||
//op_rmw
|
||||
|
||||
void op_inc_b();
|
||||
void op_inc_w();
|
||||
void op_dec_b();
|
||||
@@ -48,7 +62,18 @@
|
||||
void op_tsb_b();
|
||||
void op_tsb_w();
|
||||
|
||||
void op_io_irq();
|
||||
void op_io_cond2();
|
||||
void op_io_cond4(uint16 x, uint16 y);
|
||||
void op_io_cond6(uint16 addr);
|
||||
void (CPUcore::**opcode_table)();
|
||||
void (CPUcore::*op_table[256 * 5])();
|
||||
void initialize_opcode_table();
|
||||
void update_table();
|
||||
|
||||
enum {
|
||||
table_EM = 0, // 8-bit accumulator, 8-bit index (emulation mode)
|
||||
table_MX = 256, // 8-bit accumulator, 8-bit index
|
||||
table_Mx = 512, // 8-bit accumulator, 16-bit index
|
||||
table_mX = 768, //16-bit accumulator, 8-bit index
|
||||
table_mx = 1024, //16-bit accumulator, 16-bit index
|
||||
};
|
||||
|
||||
CPUcore();
|
||||
};
|
@@ -1,6 +1,4 @@
|
||||
#ifdef CPU_CPP
|
||||
|
||||
uint8 CPU::dreadb(uint32 addr) {
|
||||
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
|
||||
@@ -9,14 +7,14 @@ uint8 CPU::dreadb(uint32 addr) {
|
||||
return bus.read(addr);
|
||||
}
|
||||
|
||||
uint16 CPU::dreadw(uint32 addr) {
|
||||
uint16 CPUcore::dreadw(uint32 addr) {
|
||||
uint16 r;
|
||||
r = dreadb((addr + 0) & 0xffffff) << 0;
|
||||
r |= dreadb((addr + 1) & 0xffffff) << 8;
|
||||
return r;
|
||||
}
|
||||
|
||||
uint32 CPU::dreadl(uint32 addr) {
|
||||
uint32 CPUcore::dreadl(uint32 addr) {
|
||||
uint32 r;
|
||||
r = dreadb((addr + 0) & 0xffffff) << 0;
|
||||
r |= dreadb((addr + 1) & 0xffffff) << 8;
|
||||
@@ -24,7 +22,7 @@ uint32 CPU::dreadl(uint32 addr) {
|
||||
return r;
|
||||
}
|
||||
|
||||
uint32 CPU::decode(uint8 offset_type, uint32 addr) {
|
||||
uint32 CPUcore::decode(uint8 offset_type, uint32 addr) {
|
||||
uint32 r = 0;
|
||||
|
||||
switch(offset_type) {
|
||||
@@ -104,12 +102,12 @@ uint32 CPU::decode(uint8 offset_type, uint32 addr) {
|
||||
return(r & 0xffffff);
|
||||
}
|
||||
|
||||
void CPU::disassemble_opcode(char *output) {
|
||||
void CPUcore::disassemble_opcode(char *output) {
|
||||
static reg24_t pc;
|
||||
char t[256];
|
||||
char *s = output;
|
||||
|
||||
if(in_opcode() == true) {
|
||||
if(false /* in_opcode() == true */) {
|
||||
strcpy(s, "?????? <CPU within opcode>");
|
||||
return;
|
||||
}
|
||||
@@ -443,7 +441,7 @@ void CPU::disassemble_opcode(char *output) {
|
||||
//emulation mode, as regs.p.m/regs.p.x should *always* be
|
||||
//set in emulation mode.
|
||||
|
||||
uint8 CPU::opcode_length() {
|
||||
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
|
||||
@@ -469,7 +467,7 @@ uint8 CPU::opcode_length() {
|
||||
2,2,2,2, 3,2,2,2, 1,3,1,1, 3,3,3,4 //0xfn
|
||||
};
|
||||
|
||||
if(in_opcode() == true) {
|
||||
if(false /* in_opcode() == true */) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -479,5 +477,3 @@ uint8 CPU::opcode_length() {
|
||||
if(len == 6) return (regs.e || regs.p.x) ? 2 : 3;
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif //ifdef CPU_CPP
|
30
src/cpu/core/disasm/disasm.hpp
Normal file
30
src/cpu/core/disasm/disasm.hpp
Normal file
@@ -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);
|
||||
uint8 dreadb(uint32 addr);
|
||||
uint16 dreadw(uint32 addr);
|
||||
uint32 dreadl(uint32 addr);
|
||||
uint32 decode(uint8 offset_type, uint32 addr);
|
||||
uint8 opcode_length();
|
77
src/cpu/core/memory.hpp
Normal file
77
src/cpu/core/memory.hpp
Normal file
@@ -0,0 +1,77 @@
|
||||
alwaysinline uint8_t op_readpc() {
|
||||
return op_read((regs.pc.b << 16) + regs.pc.w++);
|
||||
}
|
||||
|
||||
alwaysinline uint8_t op_readstack() {
|
||||
regs.e ? regs.s.l++ : regs.s.w++;
|
||||
return op_read(regs.s.w);
|
||||
}
|
||||
|
||||
alwaysinline uint8_t op_readstackn() {
|
||||
return op_read(++regs.s.w);
|
||||
}
|
||||
|
||||
alwaysinline uint8_t op_readaddr(uint32_t addr) {
|
||||
return op_read(addr & 0xffff);
|
||||
}
|
||||
|
||||
alwaysinline uint8_t op_readlong(uint32_t addr) {
|
||||
return op_read(addr & 0xffffff);
|
||||
}
|
||||
|
||||
alwaysinline uint8_t op_readdbr(uint32_t addr) {
|
||||
return op_read(((regs.db << 16) + addr) & 0xffffff);
|
||||
}
|
||||
|
||||
alwaysinline uint8_t op_readpbr(uint32_t addr) {
|
||||
return op_read((regs.pc.b << 16) + (addr & 0xffff));
|
||||
}
|
||||
|
||||
alwaysinline uint8_t op_readdp(uint32_t addr) {
|
||||
if(regs.e && regs.d.l == 0x00) {
|
||||
return op_read((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff));
|
||||
} else {
|
||||
return op_read((regs.d + (addr & 0xffff)) & 0xffff);
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline uint8_t op_readsp(uint32_t addr) {
|
||||
return op_read((regs.s + (addr & 0xffff)) & 0xffff);
|
||||
}
|
||||
|
||||
alwaysinline void op_writestack(uint8_t data) {
|
||||
op_write(regs.s.w, data);
|
||||
regs.e ? regs.s.l-- : regs.s.w--;
|
||||
}
|
||||
|
||||
alwaysinline void op_writestackn(uint8_t data) {
|
||||
op_write(regs.s.w--, data);
|
||||
}
|
||||
|
||||
alwaysinline void op_writeaddr(uint32_t addr, uint8_t data) {
|
||||
op_write(addr & 0xffff, data);
|
||||
}
|
||||
|
||||
alwaysinline void op_writelong(uint32_t addr, uint8_t data) {
|
||||
op_write(addr & 0xffffff, data);
|
||||
}
|
||||
|
||||
alwaysinline void op_writedbr(uint32_t addr, uint8_t data) {
|
||||
op_write(((regs.db << 16) + addr) & 0xffffff, data);
|
||||
}
|
||||
|
||||
alwaysinline void op_writepbr(uint32_t addr, uint8_t data) {
|
||||
op_write((regs.pc.b << 16) + (addr & 0xffff), data);
|
||||
}
|
||||
|
||||
alwaysinline void op_writedp(uint32_t addr, uint8_t data) {
|
||||
if(regs.e && regs.d.l == 0x00) {
|
||||
op_write((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff), data);
|
||||
} else {
|
||||
op_write((regs.d + (addr & 0xffff)) & 0xffff, data);
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void op_writesp(uint32_t addr, uint8_t data) {
|
||||
op_write((regs.s + (addr & 0xffff)) & 0xffff, data);
|
||||
}
|
@@ -1,7 +1,6 @@
|
||||
#ifdef SCPU_CPP
|
||||
#ifdef CPUCORE_CPP
|
||||
|
||||
//op_read
|
||||
inline void sCPU::op_adc_b() {
|
||||
inline void CPUcore::op_adc_b() {
|
||||
int r;
|
||||
if(regs.p.d) {
|
||||
uint8 n0 = (regs.a.l ) & 15;
|
||||
@@ -29,7 +28,7 @@ inline void sCPU::op_adc_b() {
|
||||
regs.a.l = r;
|
||||
}
|
||||
|
||||
inline void sCPU::op_adc_w() {
|
||||
inline void CPUcore::op_adc_w() {
|
||||
int r;
|
||||
if(regs.p.d) {
|
||||
uint8 n0 = (regs.a.w ) & 15;
|
||||
@@ -69,133 +68,133 @@ inline void sCPU::op_adc_w() {
|
||||
regs.a.w = r;
|
||||
}
|
||||
|
||||
inline void sCPU::op_and_b() {
|
||||
inline void CPUcore::op_and_b() {
|
||||
regs.a.l &= rd.l;
|
||||
regs.p.n = regs.a.l & 0x80;
|
||||
regs.p.z = regs.a.l == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_and_w() {
|
||||
inline void CPUcore::op_and_w() {
|
||||
regs.a.w &= rd.w;
|
||||
regs.p.n = regs.a.w & 0x8000;
|
||||
regs.p.z = regs.a.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_bit_b() {
|
||||
inline void CPUcore::op_bit_b() {
|
||||
regs.p.n = rd.l & 0x80;
|
||||
regs.p.v = rd.l & 0x40;
|
||||
regs.p.z = (rd.l & regs.a.l) == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_bit_w() {
|
||||
inline void CPUcore::op_bit_w() {
|
||||
regs.p.n = rd.w & 0x8000;
|
||||
regs.p.v = rd.w & 0x4000;
|
||||
regs.p.z = (rd.w & regs.a.w) == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_cmp_b() {
|
||||
inline void CPUcore::op_cmp_b() {
|
||||
int r = regs.a.l - rd.l;
|
||||
regs.p.n = r & 0x80;
|
||||
regs.p.z = (uint8)r == 0;
|
||||
regs.p.c = r >= 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_cmp_w() {
|
||||
inline void CPUcore::op_cmp_w() {
|
||||
int r = regs.a.w - rd.w;
|
||||
regs.p.n = r & 0x8000;
|
||||
regs.p.z = (uint16)r == 0;
|
||||
regs.p.c = r >= 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_cpx_b() {
|
||||
inline void CPUcore::op_cpx_b() {
|
||||
int r = regs.x.l - rd.l;
|
||||
regs.p.n = r & 0x80;
|
||||
regs.p.z = (uint8)r == 0;
|
||||
regs.p.c = r >= 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_cpx_w() {
|
||||
inline void CPUcore::op_cpx_w() {
|
||||
int r = regs.x.w - rd.w;
|
||||
regs.p.n = r & 0x8000;
|
||||
regs.p.z = (uint16)r == 0;
|
||||
regs.p.c = r >= 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_cpy_b() {
|
||||
inline void CPUcore::op_cpy_b() {
|
||||
int r = regs.y.l - rd.l;
|
||||
regs.p.n = r & 0x80;
|
||||
regs.p.z = (uint8)r == 0;
|
||||
regs.p.c = r >= 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_cpy_w() {
|
||||
inline void CPUcore::op_cpy_w() {
|
||||
int r = regs.y.w - rd.w;
|
||||
regs.p.n = r & 0x8000;
|
||||
regs.p.z = (uint16)r == 0;
|
||||
regs.p.c = r >= 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_eor_b() {
|
||||
inline void CPUcore::op_eor_b() {
|
||||
regs.a.l ^= rd.l;
|
||||
regs.p.n = regs.a.l & 0x80;
|
||||
regs.p.z = regs.a.l == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_eor_w() {
|
||||
inline void CPUcore::op_eor_w() {
|
||||
regs.a.w ^= rd.w;
|
||||
regs.p.n = regs.a.w & 0x8000;
|
||||
regs.p.z = regs.a.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_lda_b() {
|
||||
inline void CPUcore::op_lda_b() {
|
||||
regs.a.l = rd.l;
|
||||
regs.p.n = regs.a.l & 0x80;
|
||||
regs.p.z = regs.a.l == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_lda_w() {
|
||||
inline void CPUcore::op_lda_w() {
|
||||
regs.a.w = rd.w;
|
||||
regs.p.n = regs.a.w & 0x8000;
|
||||
regs.p.z = regs.a.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_ldx_b() {
|
||||
inline void CPUcore::op_ldx_b() {
|
||||
regs.x.l = rd.l;
|
||||
regs.p.n = regs.x.l & 0x80;
|
||||
regs.p.z = regs.x.l == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_ldx_w() {
|
||||
inline void CPUcore::op_ldx_w() {
|
||||
regs.x.w = rd.w;
|
||||
regs.p.n = regs.x.w & 0x8000;
|
||||
regs.p.z = regs.x.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_ldy_b() {
|
||||
inline void CPUcore::op_ldy_b() {
|
||||
regs.y.l = rd.l;
|
||||
regs.p.n = regs.y.l & 0x80;
|
||||
regs.p.z = regs.y.l == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_ldy_w() {
|
||||
inline void CPUcore::op_ldy_w() {
|
||||
regs.y.w = rd.w;
|
||||
regs.p.n = regs.y.w & 0x8000;
|
||||
regs.p.z = regs.y.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_ora_b() {
|
||||
inline void CPUcore::op_ora_b() {
|
||||
regs.a.l |= rd.l;
|
||||
regs.p.n = regs.a.l & 0x80;
|
||||
regs.p.z = regs.a.l == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_ora_w() {
|
||||
inline void CPUcore::op_ora_w() {
|
||||
regs.a.w |= rd.w;
|
||||
regs.p.n = regs.a.w & 0x8000;
|
||||
regs.p.z = regs.a.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_sbc_b() {
|
||||
inline void CPUcore::op_sbc_b() {
|
||||
int r;
|
||||
if(regs.p.d) {
|
||||
uint8 n0 = (regs.a.l ) & 15;
|
||||
@@ -223,7 +222,7 @@ inline void sCPU::op_sbc_b() {
|
||||
regs.a.l = r;
|
||||
}
|
||||
|
||||
inline void sCPU::op_sbc_w() {
|
||||
inline void CPUcore::op_sbc_w() {
|
||||
int r;
|
||||
if(regs.p.d) {
|
||||
uint8 n0 = (regs.a.w ) & 15;
|
||||
@@ -263,60 +262,59 @@ inline void sCPU::op_sbc_w() {
|
||||
regs.a.w = r;
|
||||
}
|
||||
|
||||
//op_rmw
|
||||
inline void sCPU::op_inc_b() {
|
||||
inline void CPUcore::op_inc_b() {
|
||||
rd.l++;
|
||||
regs.p.n = rd.l & 0x80;
|
||||
regs.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_inc_w() {
|
||||
inline void CPUcore::op_inc_w() {
|
||||
rd.w++;
|
||||
regs.p.n = rd.w & 0x8000;
|
||||
regs.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_dec_b() {
|
||||
inline void CPUcore::op_dec_b() {
|
||||
rd.l--;
|
||||
regs.p.n = rd.l & 0x80;
|
||||
regs.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_dec_w() {
|
||||
inline void CPUcore::op_dec_w() {
|
||||
rd.w--;
|
||||
regs.p.n = rd.w & 0x8000;
|
||||
regs.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_asl_b() {
|
||||
inline void CPUcore::op_asl_b() {
|
||||
regs.p.c = rd.l & 0x80;
|
||||
rd.l <<= 1;
|
||||
regs.p.n = rd.l & 0x80;
|
||||
regs.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_asl_w() {
|
||||
inline void CPUcore::op_asl_w() {
|
||||
regs.p.c = rd.w & 0x8000;
|
||||
rd.w <<= 1;
|
||||
regs.p.n = rd.w & 0x8000;
|
||||
regs.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_lsr_b() {
|
||||
inline void CPUcore::op_lsr_b() {
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
regs.p.n = rd.l & 0x80;
|
||||
regs.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_lsr_w() {
|
||||
inline void CPUcore::op_lsr_w() {
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
regs.p.n = rd.w & 0x8000;
|
||||
regs.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_rol_b() {
|
||||
inline void CPUcore::op_rol_b() {
|
||||
unsigned carry = (unsigned)regs.p.c;
|
||||
regs.p.c = rd.l & 0x80;
|
||||
rd.l = (rd.l << 1) | carry;
|
||||
@@ -324,7 +322,7 @@ inline void sCPU::op_rol_b() {
|
||||
regs.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_rol_w() {
|
||||
inline void CPUcore::op_rol_w() {
|
||||
unsigned carry = (unsigned)regs.p.c;
|
||||
regs.p.c = rd.w & 0x8000;
|
||||
rd.w = (rd.w << 1) | carry;
|
||||
@@ -332,7 +330,7 @@ inline void sCPU::op_rol_w() {
|
||||
regs.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_ror_b() {
|
||||
inline void CPUcore::op_ror_b() {
|
||||
unsigned carry = (unsigned)regs.p.c << 7;
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l = carry | (rd.l >> 1);
|
||||
@@ -340,7 +338,7 @@ inline void sCPU::op_ror_b() {
|
||||
regs.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_ror_w() {
|
||||
inline void CPUcore::op_ror_w() {
|
||||
unsigned carry = (unsigned)regs.p.c << 15;
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w = carry | (rd.w >> 1);
|
||||
@@ -348,24 +346,24 @@ inline void sCPU::op_ror_w() {
|
||||
regs.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_trb_b() {
|
||||
inline void CPUcore::op_trb_b() {
|
||||
regs.p.z = (rd.l & regs.a.l) == 0;
|
||||
rd.l &= ~regs.a.l;
|
||||
}
|
||||
|
||||
inline void sCPU::op_trb_w() {
|
||||
inline void CPUcore::op_trb_w() {
|
||||
regs.p.z = (rd.w & regs.a.w) == 0;
|
||||
rd.w &= ~regs.a.w;
|
||||
}
|
||||
|
||||
inline void sCPU::op_tsb_b() {
|
||||
inline void CPUcore::op_tsb_b() {
|
||||
regs.p.z = (rd.l & regs.a.l) == 0;
|
||||
rd.l |= regs.a.l;
|
||||
}
|
||||
|
||||
inline void sCPU::op_tsb_w() {
|
||||
inline void CPUcore::op_tsb_w() {
|
||||
regs.p.z = (rd.w & regs.a.w) == 0;
|
||||
rd.w |= regs.a.w;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //ifdef SCPU_CPP
|
13
src/cpu/core/opcode_functions.bpp
Normal file
13
src/cpu/core/opcode_functions.bpp
Normal file
@@ -0,0 +1,13 @@
|
||||
//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"
|
4263
src/cpu/core/opcode_functions.cpp
Normal file
4263
src/cpu/core/opcode_functions.cpp
Normal file
File diff suppressed because it is too large
Load Diff
386
src/cpu/core/opcode_headers.bpp
Normal file
386
src/cpu/core/opcode_headers.bpp
Normal file
@@ -0,0 +1,386 @@
|
||||
//===============
|
||||
//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"
|
892
src/cpu/core/opcode_headers.hpp
Normal file
892
src/cpu/core/opcode_headers.hpp
Normal file
@@ -0,0 +1,892 @@
|
||||
//===============
|
||||
//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();
|
||||
|
||||
|
||||
|
317
src/cpu/core/opcode_list.bpp
Normal file
317
src/cpu/core/opcode_list.bpp
Normal file
@@ -0,0 +1,317 @@
|
||||
//===============
|
||||
//opcode_read.bpp
|
||||
//===============
|
||||
|
||||
@op_read_const(adc)
|
||||
@op_read_const(and)
|
||||
@op_read_const(cmp)
|
||||
@op_read_const(cpx)
|
||||
@op_read_const(cpy)
|
||||
@op_read_const(eor)
|
||||
@op_read_const(lda)
|
||||
@op_read_const(ldx)
|
||||
@op_read_const(ldy)
|
||||
@op_read_const(ora)
|
||||
@op_read_const(sbc)
|
||||
|
||||
@op_read_bit_const()
|
||||
|
||||
@op_read_addr(adc)
|
||||
@op_read_addr(and)
|
||||
@op_read_addr(bit)
|
||||
@op_read_addr(cmp)
|
||||
@op_read_addr(cpx)
|
||||
@op_read_addr(cpy)
|
||||
@op_read_addr(eor)
|
||||
@op_read_addr(lda)
|
||||
@op_read_addr(ldx)
|
||||
@op_read_addr(ldy)
|
||||
@op_read_addr(ora)
|
||||
@op_read_addr(sbc)
|
||||
|
||||
@op_read_addrx(adc)
|
||||
@op_read_addrx(and)
|
||||
@op_read_addrx(bit)
|
||||
@op_read_addrx(cmp)
|
||||
@op_read_addrx(eor)
|
||||
@op_read_addrx(lda)
|
||||
@op_read_addrx(ldy)
|
||||
@op_read_addrx(ora)
|
||||
@op_read_addrx(sbc)
|
||||
|
||||
@op_read_addry(adc)
|
||||
@op_read_addry(and)
|
||||
@op_read_addry(cmp)
|
||||
@op_read_addry(eor)
|
||||
@op_read_addry(lda)
|
||||
@op_read_addry(ldx)
|
||||
@op_read_addry(ora)
|
||||
@op_read_addry(sbc)
|
||||
|
||||
@op_read_long(adc)
|
||||
@op_read_long(and)
|
||||
@op_read_long(cmp)
|
||||
@op_read_long(eor)
|
||||
@op_read_long(lda)
|
||||
@op_read_long(ora)
|
||||
@op_read_long(sbc)
|
||||
|
||||
@op_read_longx(adc)
|
||||
@op_read_longx(and)
|
||||
@op_read_longx(cmp)
|
||||
@op_read_longx(eor)
|
||||
@op_read_longx(lda)
|
||||
@op_read_longx(ora)
|
||||
@op_read_longx(sbc)
|
||||
|
||||
@op_read_dp(adc)
|
||||
@op_read_dp(and)
|
||||
@op_read_dp(bit)
|
||||
@op_read_dp(cmp)
|
||||
@op_read_dp(cpx)
|
||||
@op_read_dp(cpy)
|
||||
@op_read_dp(eor)
|
||||
@op_read_dp(lda)
|
||||
@op_read_dp(ldx)
|
||||
@op_read_dp(ldy)
|
||||
@op_read_dp(ora)
|
||||
@op_read_dp(sbc)
|
||||
|
||||
@op_read_dpr(adc, x)
|
||||
@op_read_dpr(and, x)
|
||||
@op_read_dpr(bit, x)
|
||||
@op_read_dpr(cmp, x)
|
||||
@op_read_dpr(eor, x)
|
||||
@op_read_dpr(lda, x)
|
||||
@op_read_dpr(ldx, y)
|
||||
@op_read_dpr(ldy, x)
|
||||
@op_read_dpr(ora, x)
|
||||
@op_read_dpr(sbc, x)
|
||||
|
||||
@op_read_idp(adc)
|
||||
@op_read_idp(and)
|
||||
@op_read_idp(cmp)
|
||||
@op_read_idp(eor)
|
||||
@op_read_idp(lda)
|
||||
@op_read_idp(ora)
|
||||
@op_read_idp(sbc)
|
||||
|
||||
@op_read_idpx(adc)
|
||||
@op_read_idpx(and)
|
||||
@op_read_idpx(cmp)
|
||||
@op_read_idpx(eor)
|
||||
@op_read_idpx(lda)
|
||||
@op_read_idpx(ora)
|
||||
@op_read_idpx(sbc)
|
||||
|
||||
@op_read_idpy(adc)
|
||||
@op_read_idpy(and)
|
||||
@op_read_idpy(cmp)
|
||||
@op_read_idpy(eor)
|
||||
@op_read_idpy(lda)
|
||||
@op_read_idpy(ora)
|
||||
@op_read_idpy(sbc)
|
||||
|
||||
@op_read_ildp(adc)
|
||||
@op_read_ildp(and)
|
||||
@op_read_ildp(cmp)
|
||||
@op_read_ildp(eor)
|
||||
@op_read_ildp(lda)
|
||||
@op_read_ildp(ora)
|
||||
@op_read_ildp(sbc)
|
||||
|
||||
@op_read_ildpy(adc)
|
||||
@op_read_ildpy(and)
|
||||
@op_read_ildpy(cmp)
|
||||
@op_read_ildpy(eor)
|
||||
@op_read_ildpy(lda)
|
||||
@op_read_ildpy(ora)
|
||||
@op_read_ildpy(sbc)
|
||||
|
||||
@op_read_sr(adc)
|
||||
@op_read_sr(and)
|
||||
@op_read_sr(cmp)
|
||||
@op_read_sr(eor)
|
||||
@op_read_sr(lda)
|
||||
@op_read_sr(ora)
|
||||
@op_read_sr(sbc)
|
||||
|
||||
@op_read_isry(adc)
|
||||
@op_read_isry(and)
|
||||
@op_read_isry(cmp)
|
||||
@op_read_isry(eor)
|
||||
@op_read_isry(lda)
|
||||
@op_read_isry(ora)
|
||||
@op_read_isry(sbc)
|
||||
|
||||
//================
|
||||
//opcode_write.bpp
|
||||
//================
|
||||
|
||||
@op_store_addr(sta, regs.a.w)
|
||||
@op_store_addr(stx, regs.x.w)
|
||||
@op_store_addr(sty, regs.y.w)
|
||||
@op_store_addr(stz, 0x0000)
|
||||
|
||||
@op_store_addrr(sta, x, regs.a.w, regs.x.w)
|
||||
@op_store_addrr(sta, y, regs.a.w, regs.y.w)
|
||||
@op_store_addrr(stz, x, 0x0000, regs.x.w)
|
||||
|
||||
@op_store_longr(sta, , 0x0000)
|
||||
@op_store_longr(sta, x, regs.x.w)
|
||||
|
||||
@op_store_dp(sta, regs.a.w)
|
||||
@op_store_dp(stx, regs.x.w)
|
||||
@op_store_dp(sty, regs.y.w)
|
||||
@op_store_dp(stz, 0x0000)
|
||||
|
||||
@op_store_dpr(sta, regs.a.w, x)
|
||||
@op_store_dpr(stx, regs.x.w, y)
|
||||
@op_store_dpr(sty, regs.y.w, x)
|
||||
@op_store_dpr(stz, 0x0000, x)
|
||||
|
||||
@op_sta_idp()
|
||||
@op_sta_ildp()
|
||||
@op_sta_idpx()
|
||||
@op_sta_idpy()
|
||||
@op_sta_ildpy()
|
||||
@op_sta_sr()
|
||||
@op_sta_isry()
|
||||
|
||||
//==============
|
||||
//opcode_rmw.bpp
|
||||
//==============
|
||||
|
||||
@op_adjust(inc, a, ++)
|
||||
@op_adjust(inx, x, ++)
|
||||
@op_adjust(iny, y, ++)
|
||||
@op_adjust(dec, a, --)
|
||||
@op_adjust(dex, x, --)
|
||||
@op_adjust(dey, y, --)
|
||||
|
||||
@op_asl()
|
||||
@op_lsr()
|
||||
@op_rol()
|
||||
@op_ror()
|
||||
|
||||
@op_adjust_addr(inc)
|
||||
@op_adjust_addr(dec)
|
||||
@op_adjust_addr(asl)
|
||||
@op_adjust_addr(lsr)
|
||||
@op_adjust_addr(rol)
|
||||
@op_adjust_addr(ror)
|
||||
@op_adjust_addr(trb)
|
||||
@op_adjust_addr(tsb)
|
||||
|
||||
@op_adjust_addrx(inc)
|
||||
@op_adjust_addrx(dec)
|
||||
@op_adjust_addrx(asl)
|
||||
@op_adjust_addrx(lsr)
|
||||
@op_adjust_addrx(rol)
|
||||
@op_adjust_addrx(ror)
|
||||
|
||||
@op_adjust_dp(inc)
|
||||
@op_adjust_dp(dec)
|
||||
@op_adjust_dp(asl)
|
||||
@op_adjust_dp(lsr)
|
||||
@op_adjust_dp(rol)
|
||||
@op_adjust_dp(ror)
|
||||
@op_adjust_dp(trb)
|
||||
@op_adjust_dp(tsb)
|
||||
|
||||
@op_adjust_dpx(inc)
|
||||
@op_adjust_dpx(dec)
|
||||
@op_adjust_dpx(asl)
|
||||
@op_adjust_dpx(lsr)
|
||||
@op_adjust_dpx(rol)
|
||||
@op_adjust_dpx(ror)
|
||||
|
||||
//=============
|
||||
//opcode_pc.bpp
|
||||
//=============
|
||||
|
||||
@op_branch(bcc, !regs.p.c)
|
||||
@op_branch(bcs, regs.p.c)
|
||||
@op_branch(bne, !regs.p.z)
|
||||
@op_branch(beq, regs.p.z)
|
||||
@op_branch(bpl, !regs.p.n)
|
||||
@op_branch(bmi, regs.p.n)
|
||||
@op_branch(bvc, !regs.p.v)
|
||||
@op_branch(bvs, regs.p.v)
|
||||
|
||||
@op_bra()
|
||||
@op_brl()
|
||||
@op_jmp_addr()
|
||||
@op_jmp_long()
|
||||
@op_jmp_iaddr()
|
||||
@op_jmp_iaddrx()
|
||||
@op_jmp_iladdr()
|
||||
@op_jsr_addr()
|
||||
@op_jsr_long()
|
||||
@op_jsr_iaddrx()
|
||||
@op_rti()
|
||||
@op_rts()
|
||||
@op_rtl()
|
||||
|
||||
//===============
|
||||
//opcode_misc.bpp
|
||||
//===============
|
||||
|
||||
@op_nop()
|
||||
@op_wdm()
|
||||
@op_xba()
|
||||
|
||||
@op_move(mvn, ++)
|
||||
@op_move(mvp, --)
|
||||
|
||||
@op_interrupt(brk, 0xfffe, 0xffe6)
|
||||
@op_interrupt(cop, 0xfff4, 0xffe4)
|
||||
|
||||
@op_stp()
|
||||
@op_wai()
|
||||
@op_xce()
|
||||
|
||||
@op_flag(clc, regs.p.c = 0)
|
||||
@op_flag(cld, regs.p.d = 0)
|
||||
@op_flag(cli, regs.p.i = 0)
|
||||
@op_flag(clv, regs.p.v = 0)
|
||||
@op_flag(sec, regs.p.c = 1)
|
||||
@op_flag(sed, regs.p.d = 1)
|
||||
@op_flag(sei, regs.p.i = 1)
|
||||
|
||||
@op_pflag(rep, &=~)
|
||||
@op_pflag(sep, |=)
|
||||
|
||||
@op_transfer(tax, a, x)
|
||||
@op_transfer(tay, a, y)
|
||||
@op_transfer(txa, x, a)
|
||||
@op_transfer(txy, x, y)
|
||||
@op_transfer(tya, y, a)
|
||||
@op_transfer(tyx, y, x)
|
||||
|
||||
@op_transfer_word(tcd, a, d)
|
||||
@op_transfer_word(tdc, d, a)
|
||||
|
||||
@op_tcs()
|
||||
@op_tsc()
|
||||
@op_tsx()
|
||||
@op_txs()
|
||||
|
||||
@op_push(pha, a)
|
||||
@op_push(phx, x)
|
||||
@op_push(phy, y)
|
||||
@op_phd()
|
||||
@op_push_byte(phb, regs.db)
|
||||
@op_push_byte(phk, regs.pc.b)
|
||||
@op_push_byte(php, regs.p)
|
||||
|
||||
@op_pull(pla, a)
|
||||
@op_pull(plx, x)
|
||||
@op_pull(ply, y)
|
||||
@op_pld()
|
||||
@op_plb()
|
||||
@op_plp()
|
||||
|
||||
@op_pea()
|
||||
@op_pei()
|
||||
@op_per()
|
397
src/cpu/core/opcode_misc.bpp
Normal file
397
src/cpu/core/opcode_misc.bpp
Normal file
@@ -0,0 +1,397 @@
|
||||
@macro op_nop()
|
||||
void {class}::op_nop() {
|
||||
{lc}op_io_irq();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_wdm()
|
||||
void {class}::op_wdm() {
|
||||
{lc}op_readpc();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_xba()
|
||||
void {class}::op_xba() {
|
||||
op_io();
|
||||
{lc}op_io();
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.a.h ^= regs.a.l;
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.p.n = (regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_move(name, op)
|
||||
void {class}::op_{name}_b() {
|
||||
dp = op_readpc();
|
||||
sp = op_readpc();
|
||||
regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
op_io();
|
||||
regs.x.l {op};
|
||||
regs.y.l {op};
|
||||
{lc}op_io();
|
||||
if(regs.a.w--) regs.pc.w -= 3;
|
||||
}
|
||||
|
||||
void {class}::op_{name}_w() {
|
||||
dp = op_readpc();
|
||||
sp = op_readpc();
|
||||
regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
op_io();
|
||||
regs.x.w {op};
|
||||
regs.y.w {op};
|
||||
{lc}op_io();
|
||||
if(regs.a.w--) regs.pc.w -= 3;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_interrupt(name, vectorE, vectorN)
|
||||
void {class}::op_{name}_e() {
|
||||
op_readpc();
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestack(regs.p);
|
||||
rd.l = op_readlong({vectorE} + 0);
|
||||
regs.pc.b = 0;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
{lc}rd.h = op_readlong({vectorE} + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
void {class}::op_{name}_n() {
|
||||
op_readpc();
|
||||
op_writestack(regs.pc.b);
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestack(regs.p);
|
||||
rd.l = op_readlong({vectorN} + 0);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
{lc}rd.h = op_readlong({vectorN} + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_stp()
|
||||
void {class}::op_stp() {
|
||||
while({wai} = true) {
|
||||
{lc} op_io();
|
||||
}
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_wai()
|
||||
void {class}::op_wai() {
|
||||
{wai} = true;
|
||||
while({wai}) {
|
||||
{lc} op_io();
|
||||
}
|
||||
op_io();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_xce()
|
||||
void {class}::op_xce() {
|
||||
{lc}op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = regs.e;
|
||||
regs.e = carry;
|
||||
if(regs.e) {
|
||||
regs.p |= 0x30;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
update_table();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_flag(name, rule)
|
||||
void {class}::op_{name}() {
|
||||
{lc}op_io_irq();
|
||||
{rule};
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_pflag(name, op)
|
||||
void {class}::op_{name}_e() {
|
||||
rd.l = op_readpc();
|
||||
{lc}op_io();
|
||||
regs.p {op} rd.l;
|
||||
regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
update_table();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_n() {
|
||||
rd.l = op_readpc();
|
||||
{lc}op_io();
|
||||
regs.p {op} rd.l;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
update_table();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_transfer(name, from, to)
|
||||
void {class}::op_{name}_b() {
|
||||
{lc}op_io_irq();
|
||||
regs.{to}.l = regs.{from}.l;
|
||||
regs.p.n = (regs.{to}.l & 0x80);
|
||||
regs.p.z = (regs.{to}.l == 0);
|
||||
}
|
||||
|
||||
void {class}::op_{name}_w() {
|
||||
{lc}op_io_irq();
|
||||
regs.{to}.w = regs.{from}.w;
|
||||
regs.p.n = (regs.{to}.w & 0x8000);
|
||||
regs.p.z = (regs.{to}.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_transfer_word(name, from, to)
|
||||
void {class}::op_{name}() {
|
||||
{lc}op_io_irq();
|
||||
regs.{to}.w = regs.{from}.w;
|
||||
regs.p.n = (regs.{to}.w & 0x8000);
|
||||
regs.p.z = (regs.{to}.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_tcs()
|
||||
void {class}::op_tcs_e() {
|
||||
{lc}op_io_irq();
|
||||
regs.s.l = regs.a.l;
|
||||
}
|
||||
|
||||
void {class}::op_tcs_n() {
|
||||
{lc}op_io_irq();
|
||||
regs.s.w = regs.a.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_tsc()
|
||||
void {class}::op_tsc_e() {
|
||||
{lc}op_io_irq();
|
||||
regs.a.w = regs.s.w;
|
||||
regs.p.n = (regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void {class}::op_tsc_n() {
|
||||
{lc}op_io_irq();
|
||||
regs.a.w = regs.s.w;
|
||||
regs.p.n = (regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_tsx()
|
||||
void {class}::op_tsx_b() {
|
||||
{lc}op_io_irq();
|
||||
regs.x.l = regs.s.l;
|
||||
regs.p.n = (regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
}
|
||||
|
||||
void {class}::op_tsx_w() {
|
||||
{lc}op_io_irq();
|
||||
regs.x.w = regs.s.w;
|
||||
regs.p.n = (regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_txs()
|
||||
void {class}::op_txs_e() {
|
||||
{lc}op_io_irq();
|
||||
regs.s.l = regs.x.l;
|
||||
}
|
||||
|
||||
void {class}::op_txs_n() {
|
||||
{lc}op_io_irq();
|
||||
regs.s.w = regs.x.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_push(name, r)
|
||||
void {class}::op_{name}_b() {
|
||||
op_io();
|
||||
{lc}op_writestack(regs.{r}.l);
|
||||
}
|
||||
|
||||
void {class}::op_{name}_w() {
|
||||
op_io();
|
||||
op_writestack(regs.{r}.h);
|
||||
{lc}op_writestack(regs.{r}.l);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_phd()
|
||||
void {class}::op_phd_e() {
|
||||
op_io();
|
||||
op_writestackn(regs.d.h);
|
||||
{lc}op_writestackn(regs.d.l);
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void {class}::op_phd_n() {
|
||||
op_io();
|
||||
op_writestackn(regs.d.h);
|
||||
{lc}op_writestackn(regs.d.l);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_push_byte(name, r)
|
||||
void {class}::op_{name}() {
|
||||
op_io();
|
||||
{lc}op_writestack({r});
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_pull(name, r)
|
||||
void {class}::op_{name}_b() {
|
||||
op_io();
|
||||
op_io();
|
||||
{lc}regs.{r}.l = op_readstack();
|
||||
regs.p.n = (regs.{r}.l & 0x80);
|
||||
regs.p.z = (regs.{r}.l == 0);
|
||||
}
|
||||
|
||||
void {class}::op_{name}_w() {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.{r}.l = op_readstack();
|
||||
{lc}regs.{r}.h = op_readstack();
|
||||
regs.p.n = (regs.{r}.w & 0x8000);
|
||||
regs.p.z = (regs.{r}.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_pld()
|
||||
void {class}::op_pld_e() {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.d.l = op_readstackn();
|
||||
{lc}regs.d.h = op_readstackn();
|
||||
regs.p.n = (regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void {class}::op_pld_n() {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.d.l = op_readstackn();
|
||||
{lc}regs.d.h = op_readstackn();
|
||||
regs.p.n = (regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_plb()
|
||||
void {class}::op_plb() {
|
||||
op_io();
|
||||
op_io();
|
||||
{lc}regs.db = op_readstack();
|
||||
regs.p.n = (regs.db & 0x80);
|
||||
regs.p.z = (regs.db == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_plp()
|
||||
void {class}::op_plp_e() {
|
||||
op_io();
|
||||
op_io();
|
||||
{lc}regs.p = op_readstack() | 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
update_table();
|
||||
}
|
||||
|
||||
void {class}::op_plp_n() {
|
||||
op_io();
|
||||
op_io();
|
||||
{lc}regs.p = op_readstack();
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
update_table();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_pea()
|
||||
void {class}::op_pea_e() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(aa.h);
|
||||
{lc}op_writestackn(aa.l);
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void {class}::op_pea_n() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(aa.h);
|
||||
{lc}op_writestackn(aa.l);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_pei()
|
||||
void {class}::op_pei_e() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_writestackn(aa.h);
|
||||
{lc}op_writestackn(aa.l);
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void {class}::op_pei_n() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_writestackn(aa.h);
|
||||
{lc}op_writestackn(aa.l);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_per()
|
||||
void {class}::op_per_e() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.w = regs.pc.d + (int16_t)aa.w;
|
||||
op_writestackn(rd.h);
|
||||
{lc}op_writestackn(rd.l);
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void {class}::op_per_n() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.w = regs.pc.d + (int16_t)aa.w;
|
||||
op_writestackn(rd.h);
|
||||
{lc}op_writestackn(rd.l);
|
||||
}
|
||||
@endmacro
|
205
src/cpu/core/opcode_pc.bpp
Normal file
205
src/cpu/core/opcode_pc.bpp
Normal file
@@ -0,0 +1,205 @@
|
||||
@macro op_branch(name, condition)
|
||||
void {class}::op_{name}() {
|
||||
if({condition} == false) {
|
||||
{lc} rd.l = op_readpc();
|
||||
} else {
|
||||
rd.l = op_readpc();
|
||||
aa.w = regs.pc.d + (int8_t)rd.l;
|
||||
op_io_cond6(aa.w);
|
||||
{lc} op_io();
|
||||
regs.pc.w = aa.w;
|
||||
}
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_bra()
|
||||
void {class}::op_bra() {
|
||||
rd.l = op_readpc();
|
||||
aa.w = regs.pc.d + (int8_t)rd.l;
|
||||
op_io_cond6(aa.w);
|
||||
{lc}op_io();
|
||||
regs.pc.w = aa.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_brl()
|
||||
void {class}::op_brl() {
|
||||
rd.l = op_readpc();
|
||||
rd.h = op_readpc();
|
||||
{lc}op_io();
|
||||
regs.pc.w = regs.pc.d + (int16_t)rd.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_addr()
|
||||
void {class}::op_jmp_addr() {
|
||||
rd.l = op_readpc();
|
||||
{lc}rd.h = op_readpc();
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_long()
|
||||
void {class}::op_jmp_long() {
|
||||
rd.l = op_readpc();
|
||||
rd.h = op_readpc();
|
||||
{lc}rd.b = op_readpc();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_iaddr()
|
||||
void {class}::op_jmp_iaddr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readaddr(aa.w + 0);
|
||||
{lc}rd.h = op_readaddr(aa.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_iaddrx()
|
||||
void {class}::op_jmp_iaddrx() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readpbr(aa.w + regs.x.w + 0);
|
||||
{lc}rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_iladdr()
|
||||
void {class}::op_jmp_iladdr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readaddr(aa.w + 0);
|
||||
rd.h = op_readaddr(aa.w + 1);
|
||||
{lc}rd.b = op_readaddr(aa.w + 2);
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_jsr_addr()
|
||||
void {class}::op_jsr_addr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
regs.pc.w--;
|
||||
op_writestack(regs.pc.h);
|
||||
{lc}op_writestack(regs.pc.l);
|
||||
regs.pc.w = aa.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_jsr_long()
|
||||
void {class}::op_jsr_long_e() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(regs.pc.b);
|
||||
op_io();
|
||||
aa.b = op_readpc();
|
||||
regs.pc.w--;
|
||||
op_writestackn(regs.pc.h);
|
||||
{lc}op_writestackn(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void {class}::op_jsr_long_n() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(regs.pc.b);
|
||||
op_io();
|
||||
aa.b = op_readpc();
|
||||
regs.pc.w--;
|
||||
op_writestackn(regs.pc.h);
|
||||
{lc}op_writestackn(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_jsr_iaddrx()
|
||||
void {class}::op_jsr_iaddrx_e() {
|
||||
aa.l = op_readpc();
|
||||
op_writestackn(regs.pc.h);
|
||||
op_writestackn(regs.pc.l);
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readpbr(aa.w + regs.x.w + 0);
|
||||
{lc}rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void {class}::op_jsr_iaddrx_n() {
|
||||
aa.l = op_readpc();
|
||||
op_writestackn(regs.pc.h);
|
||||
op_writestackn(regs.pc.l);
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readpbr(aa.w + regs.x.w + 0);
|
||||
{lc}rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_rti()
|
||||
void {class}::op_rti_e() {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p = op_readstack() | 0x30;
|
||||
rd.l = op_readstack();
|
||||
{lc}rd.h = op_readstack();
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
void {class}::op_rti_n() {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p = op_readstack();
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
rd.l = op_readstack();
|
||||
rd.h = op_readstack();
|
||||
{lc}rd.b = op_readstack();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
update_table();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_rts()
|
||||
void {class}::op_rts() {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstack();
|
||||
rd.h = op_readstack();
|
||||
{lc}op_io();
|
||||
regs.pc.w = ++rd.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_rtl()
|
||||
void {class}::op_rtl_e() {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstackn();
|
||||
rd.h = op_readstackn();
|
||||
{lc}rd.b = op_readstackn();
|
||||
regs.pc.b = rd.b;
|
||||
regs.pc.w = ++rd.w;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void {class}::op_rtl_n() {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstackn();
|
||||
rd.h = op_readstackn();
|
||||
{lc}rd.b = op_readstackn();
|
||||
regs.pc.b = rd.b;
|
||||
regs.pc.w = ++rd.w;
|
||||
}
|
||||
@endmacro
|
307
src/cpu/core/opcode_read.bpp
Normal file
307
src/cpu/core/opcode_read.bpp
Normal file
@@ -0,0 +1,307 @@
|
||||
@macro op_read_const(name)
|
||||
void {class}::op_{name}_const_b() {
|
||||
{lc}rd.l = op_readpc();
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_const_w() {
|
||||
rd.l = op_readpc();
|
||||
{lc}rd.h = op_readpc();
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_bit_const()
|
||||
void {class}::op_bit_const_b() {
|
||||
{lc}rd.l = op_readpc();
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
}
|
||||
|
||||
void {class}::op_bit_const_w() {
|
||||
rd.l = op_readpc();
|
||||
{lc}rd.h = op_readpc();
|
||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_addr(name)
|
||||
void {class}::op_{name}_addr_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
{lc}rd.l = op_readdbr(aa.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_addr_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w + 0);
|
||||
{lc}rd.h = op_readdbr(aa.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_addrx(name)
|
||||
void {class}::op_{name}_addrx_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io_cond4(aa.w, aa.w + regs.x.w);
|
||||
{lc}rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_addrx_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io_cond4(aa.w, aa.w + regs.x.w);
|
||||
rd.l = op_readdbr(aa.w + regs.x.w + 0);
|
||||
{lc}rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_addry(name)
|
||||
void {class}::op_{name}_addry_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
{lc}rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_addry_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
rd.l = op_readdbr(aa.w + regs.y.w + 0);
|
||||
{lc}rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_long(name)
|
||||
void {class}::op_{name}_long_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
{lc}rd.l = op_readlong(aa.d);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_long_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
rd.l = op_readlong(aa.d + 0);
|
||||
{lc}rd.h = op_readlong(aa.d + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_longx(name)
|
||||
void {class}::op_{name}_longx_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
{lc}rd.l = op_readlong(aa.d + regs.x.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_longx_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
rd.l = op_readlong(aa.d + regs.x.w + 0);
|
||||
{lc}rd.h = op_readlong(aa.d + regs.x.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_dp(name)
|
||||
void {class}::op_{name}_dp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
{lc}rd.l = op_readdp(dp);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_dp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp + 0);
|
||||
{lc}rd.h = op_readdp(dp + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_dpr(name, r)
|
||||
void {class}::op_{name}_dpr_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
{lc}rd.l = op_readdp(dp + regs.{r}.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_dpr_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
{lc}rd.l = op_readdp(dp + regs.{r}.w + 0);
|
||||
rd.h = op_readdp(dp + regs.{r}.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_idp(name)
|
||||
void {class}::op_{name}_idp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
{lc}rd.l = op_readdbr(aa.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_idp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
rd.l = op_readdbr(aa.w + 0);
|
||||
{lc}rd.h = op_readdbr(aa.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_idpx(name)
|
||||
void {class}::op_{name}_idpx_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
aa.l = op_readdp(dp + regs.x.w + 0);
|
||||
aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
{lc}rd.l = op_readdbr(aa.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_idpx_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
aa.l = op_readdp(dp + regs.x.w + 0);
|
||||
aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
rd.l = op_readdbr(aa.w + 0);
|
||||
{lc}rd.h = op_readdbr(aa.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_idpy(name)
|
||||
void {class}::op_{name}_idpy_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
{lc}rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_idpy_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
rd.l = op_readdbr(aa.w + regs.y.w + 0);
|
||||
{lc}rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_ildp(name)
|
||||
void {class}::op_{name}_ildp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
{lc}rd.l = op_readlong(aa.d);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_ildp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
rd.l = op_readlong(aa.d + 0);
|
||||
{lc}rd.h = op_readlong(aa.d + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_ildpy(name)
|
||||
void {class}::op_{name}_ildpy_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
{lc}rd.l = op_readlong(aa.d + regs.y.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_ildpy_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
rd.l = op_readlong(aa.d + regs.y.w + 0);
|
||||
{lc}rd.h = op_readlong(aa.d + regs.y.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_sr(name)
|
||||
void {class}::op_{name}_sr_b() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
{lc}rd.l = op_readsp(sp);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_sr_w() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readsp(sp + 0);
|
||||
{lc}rd.h = op_readsp(sp + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_isry(name)
|
||||
void {class}::op_{name}_isry_b() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
aa.l = op_readsp(sp + 0);
|
||||
aa.h = op_readsp(sp + 1);
|
||||
op_io();
|
||||
{lc}rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_isry_w() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
aa.l = op_readsp(sp + 0);
|
||||
aa.h = op_readsp(sp + 1);
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.y.w + 0);
|
||||
{lc}rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
183
src/cpu/core/opcode_rmw.bpp
Normal file
183
src/cpu/core/opcode_rmw.bpp
Normal file
@@ -0,0 +1,183 @@
|
||||
@macro op_adjust(name, r, op)
|
||||
void {class}::op_{name}_imm_b() {
|
||||
{lc}op_io_irq();
|
||||
regs.{r}.l {op};
|
||||
regs.p.n = (regs.{r}.l & 0x80);
|
||||
regs.p.z = (regs.{r}.l == 0);
|
||||
}
|
||||
|
||||
void {class}::op_{name}_imm_w() {
|
||||
{lc}op_io_irq();
|
||||
regs.{r}.w {op};
|
||||
regs.p.n = (regs.{r}.w & 0x8000);
|
||||
regs.p.z = (regs.{r}.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_asl()
|
||||
void {class}::op_asl_imm_b() {
|
||||
{lc}op_io_irq();
|
||||
regs.p.c = (regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.p.n = (regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void {class}::op_asl_imm_w() {
|
||||
{lc}op_io_irq();
|
||||
regs.p.c = (regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.p.n = (regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_lsr()
|
||||
void {class}::op_lsr_imm_b() {
|
||||
{lc}op_io_irq();
|
||||
regs.p.c = (regs.a.l & 0x01);
|
||||
regs.a.l >>= 1;
|
||||
regs.p.n = (regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void {class}::op_lsr_imm_w() {
|
||||
{lc}op_io_irq();
|
||||
regs.p.c = (regs.a.w & 0x0001);
|
||||
regs.a.w >>= 1;
|
||||
regs.p.n = (regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_rol()
|
||||
void {class}::op_rol_imm_b() {
|
||||
{lc}op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = (regs.a.l & 0x80);
|
||||
regs.a.l = (regs.a.l << 1) | carry;
|
||||
regs.p.n = (regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void {class}::op_rol_imm_w() {
|
||||
{lc}op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = (regs.a.w & 0x8000);
|
||||
regs.a.w = (regs.a.w << 1) | carry;
|
||||
regs.p.n = (regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_ror()
|
||||
void {class}::op_ror_imm_b() {
|
||||
{lc}op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = (regs.a.l & 0x01);
|
||||
regs.a.l = (carry << 7) | (regs.a.l >> 1);
|
||||
regs.p.n = (regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void {class}::op_ror_imm_w() {
|
||||
{lc}op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = (regs.a.w & 0x0001);
|
||||
regs.a.w = (carry << 15) | (regs.a.w >> 1);
|
||||
regs.p.n = (regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_adjust_addr(name)
|
||||
void {class}::op_{name}_addr_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
op_io();
|
||||
op_{name}_b();
|
||||
{lc}op_writedbr(aa.w, rd.l);
|
||||
}
|
||||
|
||||
void {class}::op_{name}_addr_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w + 0);
|
||||
rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
op_{name}_w();
|
||||
op_writedbr(aa.w + 1, rd.h);
|
||||
{lc}op_writedbr(aa.w + 0, rd.l);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_adjust_addrx(name)
|
||||
void {class}::op_{name}_addrx_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
op_io();
|
||||
op_{name}_b();
|
||||
{lc}op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
}
|
||||
|
||||
void {class}::op_{name}_addrx_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w + 0);
|
||||
rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
op_{name}_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h);
|
||||
{lc}op_writedbr(aa.w + regs.x.w + 0, rd.l);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_adjust_dp(name)
|
||||
void {class}::op_{name}_dp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
op_io();
|
||||
op_{name}_b();
|
||||
{lc}op_writedp(dp, rd.l);
|
||||
}
|
||||
|
||||
void {class}::op_{name}_dp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp + 0);
|
||||
rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
op_{name}_w();
|
||||
op_writedp(dp + 1, rd.h);
|
||||
{lc}op_writedp(dp + 0, rd.l);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_adjust_dpx(name)
|
||||
void {class}::op_{name}_dpx_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
op_io();
|
||||
op_{name}_b();
|
||||
{lc}op_writedp(dp + regs.x.w, rd.l);
|
||||
}
|
||||
|
||||
void {class}::op_{name}_dpx_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w + 0);
|
||||
rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
op_{name}_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h);
|
||||
{lc}op_writedp(dp + regs.x.w + 0, rd.l);
|
||||
}
|
||||
@endmacro
|
141
src/cpu/core/opcode_tables.cpp
Normal file
141
src/cpu/core/opcode_tables.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
#ifdef CPUCORE_CPP
|
||||
|
||||
void CPUcore::initialize_opcode_table() {
|
||||
//same implementation for all processor states
|
||||
#define opA(id, name) \
|
||||
op_table[table_EM + id] = &CPUcore::op_ ## name; \
|
||||
op_table[table_MX + id] = &CPUcore::op_ ## name; \
|
||||
op_table[table_Mx + id] = &CPUcore::op_ ## name; \
|
||||
op_table[table_mX + id] = &CPUcore::op_ ## name; \
|
||||
op_table[table_mx + id] = &CPUcore::op_ ## name;
|
||||
|
||||
//implementation changes based on E processor state
|
||||
#define opE(id, name) \
|
||||
op_table[table_EM + id] = &CPUcore::op_ ## name ## _e; \
|
||||
op_table[table_MX + id] = &CPUcore::op_ ## name ## _n; \
|
||||
op_table[table_Mx + id] = &CPUcore::op_ ## name ## _n; \
|
||||
op_table[table_mX + id] = &CPUcore::op_ ## name ## _n; \
|
||||
op_table[table_mx + id] = &CPUcore::op_ ## name ## _n; \
|
||||
|
||||
//implementation changes based on M processor state
|
||||
#define opM(id, name) \
|
||||
op_table[table_EM + id] = &CPUcore::op_ ## name ## _b; \
|
||||
op_table[table_MX + id] = &CPUcore::op_ ## name ## _b; \
|
||||
op_table[table_Mx + id] = &CPUcore::op_ ## name ## _b; \
|
||||
op_table[table_mX + id] = &CPUcore::op_ ## name ## _w; \
|
||||
op_table[table_mx + id] = &CPUcore::op_ ## name ## _w;
|
||||
|
||||
//implementation changes based on X processor state
|
||||
#define opX(id, name) \
|
||||
op_table[table_EM + id] = &CPUcore::op_ ## name ## _b; \
|
||||
op_table[table_MX + id] = &CPUcore::op_ ## name ## _b; \
|
||||
op_table[table_Mx + id] = &CPUcore::op_ ## name ## _w; \
|
||||
op_table[table_mX + id] = &CPUcore::op_ ## name ## _b; \
|
||||
op_table[table_mx + id] = &CPUcore::op_ ## name ## _w;
|
||||
|
||||
opE(0x00, brk) opM(0x01, ora_idpx) opE(0x02, cop) opM(0x03, ora_sr)
|
||||
opM(0x04, tsb_dp) opM(0x05, ora_dp) opM(0x06, asl_dp) opM(0x07, ora_ildp)
|
||||
opA(0x08, php) opM(0x09, ora_const) opM(0x0a, asl_imm) opE(0x0b, phd)
|
||||
opM(0x0c, tsb_addr) opM(0x0d, ora_addr) opM(0x0e, asl_addr) opM(0x0f, ora_long)
|
||||
|
||||
opA(0x10, bpl) opM(0x11, ora_idpy) opM(0x12, ora_idp) opM(0x13, ora_isry)
|
||||
opM(0x14, trb_dp) opM(0x15, ora_dpr) opM(0x16, asl_dpx) opM(0x17, ora_ildpy)
|
||||
opA(0x18, clc) opM(0x19, ora_addry) opM(0x1a, inc_imm) opE(0x1b, tcs)
|
||||
opM(0x1c, trb_addr) opM(0x1d, ora_addrx) opM(0x1e, asl_addrx) opM(0x1f, ora_longx)
|
||||
|
||||
opA(0x20, jsr_addr) opM(0x21, and_idpx) opE(0x22, jsr_long) opM(0x23, and_sr)
|
||||
opM(0x24, bit_dp) opM(0x25, and_dp) opM(0x26, rol_dp) opM(0x27, and_ildp)
|
||||
opE(0x28, plp) opM(0x29, and_const) opM(0x2a, rol_imm) opE(0x2b, pld)
|
||||
opM(0x2c, bit_addr) opM(0x2d, and_addr) opM(0x2e, rol_addr) opM(0x2f, and_long)
|
||||
|
||||
opA(0x30, bmi) opM(0x31, and_idpy) opM(0x32, and_idp) opM(0x33, and_isry)
|
||||
opM(0x34, bit_dpr) opM(0x35, and_dpr) opM(0x36, rol_dpx) opM(0x37, and_ildpy)
|
||||
opA(0x38, sec) opM(0x39, and_addry) opM(0x3a, dec_imm) opE(0x3b, tsc)
|
||||
opM(0x3c, bit_addrx) opM(0x3d, and_addrx) opM(0x3e, rol_addrx) opM(0x3f, and_longx)
|
||||
|
||||
opE(0x40, rti) opM(0x41, eor_idpx) opA(0x42, wdm) opM(0x43, eor_sr)
|
||||
opX(0x44, mvp) opM(0x45, eor_dp) opM(0x46, lsr_dp) opM(0x47, eor_ildp)
|
||||
opM(0x48, pha) opM(0x49, eor_const) opM(0x4a, lsr_imm) opA(0x4b, phk)
|
||||
opA(0x4c, jmp_addr) opM(0x4d, eor_addr) opM(0x4e, lsr_addr) opM(0x4f, eor_long)
|
||||
|
||||
opA(0x50, bvc) opM(0x51, eor_idpy) opM(0x52, eor_idp) opM(0x53, eor_isry)
|
||||
opX(0x54, mvn) opM(0x55, eor_dpr) opM(0x56, lsr_dpx) opM(0x57, eor_ildpy)
|
||||
opA(0x58, cli) opM(0x59, eor_addry) opX(0x5a, phy) opA(0x5b, tcd)
|
||||
opA(0x5c, jmp_long) opM(0x5d, eor_addrx) opM(0x5e, lsr_addrx) opM(0x5f, eor_longx)
|
||||
|
||||
opA(0x60, rts) opM(0x61, adc_idpx) opE(0x62, per) opM(0x63, adc_sr)
|
||||
opM(0x64, stz_dp) opM(0x65, adc_dp) opM(0x66, ror_dp) opM(0x67, adc_ildp)
|
||||
opM(0x68, pla) opM(0x69, adc_const) opM(0x6a, ror_imm) opE(0x6b, rtl)
|
||||
opA(0x6c, jmp_iaddr) opM(0x6d, adc_addr) opM(0x6e, ror_addr) opM(0x6f, adc_long)
|
||||
|
||||
opA(0x70, bvs) opM(0x71, adc_idpy) opM(0x72, adc_idp) opM(0x73, adc_isry)
|
||||
opM(0x74, stz_dpr) opM(0x75, adc_dpr) opM(0x76, ror_dpx) opM(0x77, adc_ildpy)
|
||||
opA(0x78, sei) opM(0x79, adc_addry) opX(0x7a, ply) opA(0x7b, tdc)
|
||||
opA(0x7c, jmp_iaddrx) opM(0x7d, adc_addrx) opM(0x7e, ror_addrx) opM(0x7f, adc_longx)
|
||||
|
||||
opA(0x80, bra) opM(0x81, sta_idpx) opA(0x82, brl) opM(0x83, sta_sr)
|
||||
opX(0x84, sty_dp) opM(0x85, sta_dp) opX(0x86, stx_dp) opM(0x87, sta_ildp)
|
||||
opX(0x88, dey_imm) opM(0x89, bit_const) opM(0x8a, txa) opA(0x8b, phb)
|
||||
opX(0x8c, sty_addr) opM(0x8d, sta_addr) opX(0x8e, stx_addr) opM(0x8f, sta_long)
|
||||
|
||||
opA(0x90, bcc) opM(0x91, sta_idpy) opM(0x92, sta_idp) opM(0x93, sta_isry)
|
||||
opX(0x94, sty_dpr) opM(0x95, sta_dpr) opX(0x96, stx_dpr) opM(0x97, sta_ildpy)
|
||||
opM(0x98, tya) opM(0x99, sta_addry) opE(0x9a, txs) opX(0x9b, txy)
|
||||
opM(0x9c, stz_addr) opM(0x9d, sta_addrx) opM(0x9e, stz_addrx) opM(0x9f, sta_longx)
|
||||
|
||||
opX(0xa0, ldy_const) opM(0xa1, lda_idpx) opX(0xa2, ldx_const) opM(0xa3, lda_sr)
|
||||
opX(0xa4, ldy_dp) opM(0xa5, lda_dp) opX(0xa6, ldx_dp) opM(0xa7, lda_ildp)
|
||||
opX(0xa8, tay) opM(0xa9, lda_const) opX(0xaa, tax) opA(0xab, plb)
|
||||
opX(0xac, ldy_addr) opM(0xad, lda_addr) opX(0xae, ldx_addr) opM(0xaf, lda_long)
|
||||
|
||||
opA(0xb0, bcs) opM(0xb1, lda_idpy) opM(0xb2, lda_idp) opM(0xb3, lda_isry)
|
||||
opX(0xb4, ldy_dpr) opM(0xb5, lda_dpr) opX(0xb6, ldx_dpr) opM(0xb7, lda_ildpy)
|
||||
opA(0xb8, clv) opM(0xb9, lda_addry) opX(0xba, tsx) opX(0xbb, tyx)
|
||||
opX(0xbc, ldy_addrx) opM(0xbd, lda_addrx) opX(0xbe, ldx_addry) opM(0xbf, lda_longx)
|
||||
|
||||
opX(0xc0, cpy_const) opM(0xc1, cmp_idpx) opE(0xc2, rep) opM(0xc3, cmp_sr)
|
||||
opX(0xc4, cpy_dp) opM(0xc5, cmp_dp) opM(0xc6, dec_dp) opM(0xc7, cmp_ildp)
|
||||
opX(0xc8, iny_imm) opM(0xc9, cmp_const) opX(0xca, dex_imm) opA(0xcb, wai)
|
||||
opX(0xcc, cpy_addr) opM(0xcd, cmp_addr) opM(0xce, dec_addr) opM(0xcf, cmp_long)
|
||||
|
||||
opA(0xd0, bne) opM(0xd1, cmp_idpy) opM(0xd2, cmp_idp) opM(0xd3, cmp_isry)
|
||||
opE(0xd4, pei) opM(0xd5, cmp_dpr) opM(0xd6, dec_dpx) opM(0xd7, cmp_ildpy)
|
||||
opA(0xd8, cld) opM(0xd9, cmp_addry) opX(0xda, phx) opA(0xdb, stp)
|
||||
opA(0xdc, jmp_iladdr) opM(0xdd, cmp_addrx) opM(0xde, dec_addrx) opM(0xdf, cmp_longx)
|
||||
|
||||
opX(0xe0, cpx_const) opM(0xe1, sbc_idpx) opE(0xe2, sep) opM(0xe3, sbc_sr)
|
||||
opX(0xe4, cpx_dp) opM(0xe5, sbc_dp) opM(0xe6, inc_dp) opM(0xe7, sbc_ildp)
|
||||
opX(0xe8, inx_imm) opM(0xe9, sbc_const) opA(0xea, nop) opA(0xeb, xba)
|
||||
opX(0xec, cpx_addr) opM(0xed, sbc_addr) opM(0xee, inc_addr) opM(0xef, sbc_long)
|
||||
|
||||
opA(0xf0, beq) opM(0xf1, sbc_idpy) opM(0xf2, sbc_idp) opM(0xf3, sbc_isry)
|
||||
opE(0xf4, pea) opM(0xf5, sbc_dpr) opM(0xf6, inc_dpx) opM(0xf7, sbc_ildpy)
|
||||
opA(0xf8, sed) opM(0xf9, sbc_addry) opX(0xfa, plx) opA(0xfb, xce)
|
||||
opE(0xfc, jsr_iaddrx) opM(0xfd, sbc_addrx) opM(0xfe, inc_addrx) opM(0xff, sbc_longx)
|
||||
|
||||
#undef opA
|
||||
#undef opE
|
||||
#undef opM
|
||||
#undef opX
|
||||
}
|
||||
|
||||
void CPUcore::update_table() {
|
||||
if(regs.e) {
|
||||
opcode_table = &op_table[table_EM];
|
||||
} else if(regs.p.m) {
|
||||
if(regs.p.x) {
|
||||
opcode_table = &op_table[table_MX];
|
||||
} else {
|
||||
opcode_table = &op_table[table_Mx];
|
||||
}
|
||||
} else {
|
||||
if(regs.p.x) {
|
||||
opcode_table = &op_table[table_mX];
|
||||
} else {
|
||||
opcode_table = &op_table[table_mx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
219
src/cpu/core/opcode_write.bpp
Normal file
219
src/cpu/core/opcode_write.bpp
Normal file
@@ -0,0 +1,219 @@
|
||||
@macro op_store_addr(name, r)
|
||||
void {class}::op_{name}_addr_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
{lc}op_writedbr(aa.w, {r});
|
||||
}
|
||||
|
||||
void {class}::op_{name}_addr_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writedbr(aa.w + 0, {r} >> 0);
|
||||
{lc}op_writedbr(aa.w + 1, {r} >> 8);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_store_addrr(name, suffix, r, index)
|
||||
void {class}::op_{name}_addr{suffix}_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
{lc}op_writedbr(aa.w + {index}, {r});
|
||||
}
|
||||
|
||||
void {class}::op_{name}_addr{suffix}_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
op_writedbr(aa.w + {index} + 0, {r} >> 0);
|
||||
{lc}op_writedbr(aa.w + {index} + 1, {r} >> 8);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_store_longr(name, suffix, index)
|
||||
void {class}::op_{name}_long{suffix}_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
{lc}op_writelong(aa.d + {index}, regs.a.l);
|
||||
}
|
||||
|
||||
void {class}::op_{name}_long{suffix}_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
op_writelong(aa.d + {index} + 0, regs.a.l);
|
||||
{lc}op_writelong(aa.d + {index} + 1, regs.a.h);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_store_dp(name, r)
|
||||
void {class}::op_{name}_dp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
{lc}op_writedp(dp, {r});
|
||||
}
|
||||
|
||||
void {class}::op_{name}_dp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_writedp(dp + 0, {r} >> 0);
|
||||
{lc}op_writedp(dp + 1, {r} >> 8);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_store_dpr(name, r, index)
|
||||
void {class}::op_{name}_dpr_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
{lc}op_writedp(dp + regs.{index}.w, {r});
|
||||
}
|
||||
|
||||
void {class}::op_{name}_dpr_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
op_writedp(dp + regs.{index}.w + 0, {r} >> 0);
|
||||
{lc}op_writedp(dp + regs.{index}.w + 1, {r} >> 8);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_idp()
|
||||
void {class}::op_sta_idp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
{lc}op_writedbr(aa.w, regs.a.l);
|
||||
}
|
||||
|
||||
void {class}::op_sta_idp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_writedbr(aa.w + 0, regs.a.l);
|
||||
{lc}op_writedbr(aa.w + 1, regs.a.h);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_ildp()
|
||||
void {class}::op_sta_ildp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
{lc}op_writelong(aa.d, regs.a.l);
|
||||
}
|
||||
|
||||
void {class}::op_sta_ildp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
op_writelong(aa.d + 0, regs.a.l);
|
||||
{lc}op_writelong(aa.d + 1, regs.a.h);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_idpx()
|
||||
void {class}::op_sta_idpx_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
aa.l = op_readdp(dp + regs.x.w + 0);
|
||||
aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
{lc}op_writedbr(aa.w, regs.a.l);
|
||||
}
|
||||
|
||||
void {class}::op_sta_idpx_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
aa.l = op_readdp(dp + regs.x.w + 0);
|
||||
aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_writedbr(aa.w + 0, regs.a.l);
|
||||
{lc}op_writedbr(aa.w + 1, regs.a.h);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_idpy()
|
||||
void {class}::op_sta_idpy_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
{lc}op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
}
|
||||
|
||||
void {class}::op_sta_idpy_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
op_writedbr(aa.w + regs.y.w + 0, regs.a.l);
|
||||
{lc}op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_ildpy()
|
||||
void {class}::op_sta_ildpy_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
{lc}op_writelong(aa.d + regs.y.w, regs.a.l);
|
||||
}
|
||||
|
||||
void {class}::op_sta_ildpy_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
op_writelong(aa.d + regs.y.w + 0, regs.a.l);
|
||||
{lc}op_writelong(aa.d + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_sr()
|
||||
void {class}::op_sta_sr_b() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
{lc}op_writesp(sp, regs.a.l);
|
||||
}
|
||||
|
||||
void {class}::op_sta_sr_w() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
op_writesp(sp + 0, regs.a.l);
|
||||
{lc}op_writesp(sp + 1, regs.a.h);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_isry()
|
||||
void {class}::op_sta_isry_b() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
aa.l = op_readsp(sp + 0);
|
||||
aa.h = op_readsp(sp + 1);
|
||||
op_io();
|
||||
{lc}op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
}
|
||||
|
||||
void {class}::op_sta_isry_w() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
aa.l = op_readsp(sp + 0);
|
||||
aa.h = op_readsp(sp + 1);
|
||||
op_io();
|
||||
op_writedbr(aa.w + regs.y.w + 0, regs.a.l);
|
||||
{lc}op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
@endmacro
|
@@ -68,7 +68,12 @@ struct regs_t {
|
||||
reg24_t pc;
|
||||
reg16_t a, x, y, s, d;
|
||||
flag_t p;
|
||||
uint8_t db, mdr;
|
||||
uint8_t db;
|
||||
bool e;
|
||||
regs_t() : db(0), mdr(0), e(false) {}
|
||||
|
||||
bool irq; //IRQ pin (0 = low, 1 = trigger)
|
||||
bool wai; //raised during wai, cleared after interrupt triggered
|
||||
uint8_t mdr; //memory data register
|
||||
|
||||
regs_t() : db(0), e(false), irq(false), wai(false), mdr(0) {}
|
||||
};
|
@@ -1,11 +1,19 @@
|
||||
#include <../base.hpp>
|
||||
#define CPU_CPP
|
||||
|
||||
#include "dcpu.cpp"
|
||||
#define CPU_CPP
|
||||
namespace SNES {
|
||||
|
||||
void CPU::power() {
|
||||
cpu_version = config.cpu.version;
|
||||
}
|
||||
|
||||
void CPU::reset() {
|
||||
}
|
||||
|
||||
CPU::CPU() {
|
||||
cpu_version = 2;
|
||||
}
|
||||
|
||||
CPU::~CPU() {
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -13,61 +13,9 @@ public:
|
||||
virtual uint8 port_read(uint8 port) = 0;
|
||||
virtual void port_write(uint8 port, uint8 value) = 0;
|
||||
|
||||
#include "cpuregs.hpp"
|
||||
regs_t regs;
|
||||
|
||||
virtual void scanline() = 0;
|
||||
virtual void power() = 0;
|
||||
virtual void reset() = 0;
|
||||
|
||||
/*****
|
||||
* in opcode-based CPU emulators, the main emulation routine
|
||||
* will only be able to call the disassemble_opcode() function
|
||||
* on clean opcode edges. but with cycle-based CPU emulators,
|
||||
* the CPU may be in the middle of executing an opcode when the
|
||||
* emulator (e.g. debugger) wants to disassemble an opcode. this
|
||||
* would mean that important registers may not reflect what they
|
||||
* did at the start of the opcode (especially regs.pc), so in
|
||||
* cycle-based emulators, this function should be overridden to
|
||||
* reflect whether or not an opcode has only been partially
|
||||
* executed. if not, the debugger should abort attempts to skip,
|
||||
* disable, or disassemble the current opcode.
|
||||
*****/
|
||||
virtual bool in_opcode() { return false; }
|
||||
|
||||
/*****
|
||||
* opcode disassembler
|
||||
*****/
|
||||
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();
|
||||
virtual void power();
|
||||
virtual void reset();
|
||||
|
||||
CPU();
|
||||
virtual ~CPU();
|
||||
|
@@ -1,4 +0,0 @@
|
||||
g++ -c scpugen.cpp -I../../../lib
|
||||
g++ -c ../../../lib/nall/string.cpp -I../../../lib
|
||||
g++ -o scpugen scpugen.o string.o
|
||||
rm *.o
|
@@ -1 +0,0 @@
|
||||
rm scpugen
|
@@ -1,90 +0,0 @@
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
#include "opfn.cpp"
|
||||
|
||||
void sCPU::enter() {
|
||||
initialize:
|
||||
//initial latch values for $213c/$213d
|
||||
//[x]0035 : [y]0000 (53.0 -> 212) [lda $2137]
|
||||
//[x]0038 : [y]0000 (56.5 -> 226) [nop : lda $2137]
|
||||
add_clocks(186);
|
||||
|
||||
loop:
|
||||
if(status.interrupt_pending) {
|
||||
status.interrupt_pending = false;
|
||||
if(status.nmi_pending) {
|
||||
status.nmi_pending = false;
|
||||
status.interrupt_vector = (regs.e == false ? 0xffea : 0xfffa);
|
||||
} else if(status.irq_pending) {
|
||||
status.irq_pending = false;
|
||||
status.interrupt_vector = (regs.e == false ? 0xffee : 0xfffe);
|
||||
}
|
||||
op_irq();
|
||||
}
|
||||
|
||||
tracer.trace_cpuop(); //traces CPU opcode (only if tracer is enabled)
|
||||
|
||||
status.in_opcode = true;
|
||||
switch(op_readpc()) {
|
||||
#include "op_read.cpp"
|
||||
#include "op_write.cpp"
|
||||
#include "op_rmw.cpp"
|
||||
#include "op_pc.cpp"
|
||||
#include "op_misc.cpp"
|
||||
}
|
||||
status.in_opcode = false;
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
void sCPU::op_irq() {
|
||||
op_read(regs.pc.d);
|
||||
op_io();
|
||||
if(!regs.e) op_writestack(regs.pc.b);
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestack(regs.e ? (regs.p & ~0x10) : regs.p);
|
||||
rd.l = op_read(status.interrupt_vector + 0);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
rd.h = op_read(status.interrupt_vector + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
//immediate, 2-cycle opcodes with I/O cycle will become bus read
|
||||
//when an IRQ is to be triggered immediately after opcode completion
|
||||
//this affects the following opcodes:
|
||||
// clc, cld, cli, clv, sec, sed, sei,
|
||||
// tax, tay, txa, txy, tya, tyx,
|
||||
// tcd, tcs, tdc, tsc, tsx, txs,
|
||||
// inc, inx, iny, dec, dex, dey,
|
||||
// asl, lsr, rol, ror, nop, xce.
|
||||
alwaysinline void sCPU::op_io_irq() {
|
||||
if(status.interrupt_pending) {
|
||||
//IRQ pending, modify I/O cycle to bus read cycle, do not increment PC
|
||||
op_read(regs.pc.d);
|
||||
} else {
|
||||
op_io();
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_io_cond2() {
|
||||
if(regs.d.l != 0x00) {
|
||||
op_io();
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_io_cond4(uint16 x, uint16 y) {
|
||||
if(!regs.p.x || (x & 0xff00) != (y & 0xff00)) {
|
||||
op_io();
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_io_cond6(uint16 addr) {
|
||||
if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) {
|
||||
op_io();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,298 +0,0 @@
|
||||
nop(0xea) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
}
|
||||
|
||||
wdm(0x42) {
|
||||
1:last_cycle();
|
||||
op_readpc();
|
||||
}
|
||||
|
||||
xba(0xeb) {
|
||||
1:op_io();
|
||||
2:last_cycle();
|
||||
op_io();
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.a.h ^= regs.a.l;
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
mvn(0x54, ++),
|
||||
mvp(0x44, --) {
|
||||
1:dp = op_readpc();
|
||||
2:sp = op_readpc();
|
||||
3:regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
4:op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
5:op_io();
|
||||
if(regs.p.x) {
|
||||
regs.x.l $1;
|
||||
regs.y.l $1;
|
||||
} else {
|
||||
regs.x.w $1;
|
||||
regs.y.w $1;
|
||||
}
|
||||
6:last_cycle();
|
||||
op_io();
|
||||
if(regs.a.w--) regs.pc.w -= 3;
|
||||
}
|
||||
|
||||
brk(0x00, 0xfffe, 0xffff, 0xffe6, 0xffe7),
|
||||
cop(0x02, 0xfff4, 0xfff5, 0xffe4, 0xffe5) {
|
||||
1:op_readpc();
|
||||
2:if(!regs.e) op_writestack(regs.pc.b);
|
||||
3:op_writestack(regs.pc.h);
|
||||
4:op_writestack(regs.pc.l);
|
||||
5:op_writestack(regs.p);
|
||||
6:rd.l = op_readlong(regs.e ? $1 : $3);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
7:last_cycle();
|
||||
rd.h = op_readlong(regs.e ? $2 : $4);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
stp(0xdb) {
|
||||
1:op_io();
|
||||
2:last_cycle();
|
||||
while(true) op_io();
|
||||
}
|
||||
|
||||
wai(0xcb) {
|
||||
//last_cycle() will clear status.wai_lock once an NMI / IRQ edge is reached
|
||||
1:status.wai_lock = true;
|
||||
while(status.wai_lock) {
|
||||
last_cycle();
|
||||
op_io();
|
||||
}
|
||||
2:op_io();
|
||||
}
|
||||
|
||||
xce(0xfb) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = regs.e;
|
||||
regs.e = carry;
|
||||
if(regs.e) {
|
||||
regs.p |= 0x30;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
clc(0x18, regs.p.c = 0),
|
||||
cld(0xd8, regs.p.d = 0),
|
||||
cli(0x58, regs.p.i = 0),
|
||||
clv(0xb8, regs.p.v = 0),
|
||||
sec(0x38, regs.p.c = 1),
|
||||
sed(0xf8, regs.p.d = 1),
|
||||
sei(0x78, regs.p.i = 1) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
$1;
|
||||
}
|
||||
|
||||
rep(0xc2, &=~),
|
||||
sep(0xe2, |=) {
|
||||
1:rd.l = op_readpc();
|
||||
2:last_cycle();
|
||||
op_io();
|
||||
regs.p $1 rd.l;
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
tax(0xaa, regs.p.x, x, a),
|
||||
tay(0xa8, regs.p.x, y, a),
|
||||
txa(0x8a, regs.p.m, a, x),
|
||||
txy(0x9b, regs.p.x, y, x),
|
||||
tya(0x98, regs.p.m, a, y),
|
||||
tyx(0xbb, regs.p.x, x, y) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if($1) {
|
||||
regs.$2.l = regs.$3.l;
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
} else {
|
||||
regs.$2.w = regs.$3.w;
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
tcd(0x5b) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
regs.d.w = regs.a.w;
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
}
|
||||
|
||||
tcs(0x1b) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
regs.s.w = regs.a.w;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
tdc(0x7b) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
regs.a.w = regs.d.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
tsc(0x3b) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
regs.a.w = regs.s.w;
|
||||
if(regs.e) {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
tsx(0xba) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.s.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.s.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
txs(0x9a) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.e) {
|
||||
regs.s.l = regs.x.l;
|
||||
} else {
|
||||
regs.s.w = regs.x.w;
|
||||
}
|
||||
}
|
||||
|
||||
pha(0x48, regs.p.m, a),
|
||||
phx(0xda, regs.p.x, x),
|
||||
phy(0x5a, regs.p.x, y) {
|
||||
1:op_io();
|
||||
2:if(!$1)op_writestack(regs.$2.h);
|
||||
3:last_cycle();
|
||||
op_writestack(regs.$2.l);
|
||||
}
|
||||
|
||||
phd(0x0b) {
|
||||
1:op_io();
|
||||
2:op_writestackn(regs.d.h);
|
||||
3:last_cycle();
|
||||
op_writestackn(regs.d.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
phb(0x8b, regs.db),
|
||||
phk(0x4b, regs.pc.b),
|
||||
php(0x08, regs.p) {
|
||||
1:op_io();
|
||||
2:last_cycle();
|
||||
op_writestack($1);
|
||||
}
|
||||
|
||||
pla(0x68, regs.p.m, a),
|
||||
plx(0xfa, regs.p.x, x),
|
||||
ply(0x7a, regs.p.x, y) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:if($1)last_cycle();
|
||||
regs.$2.l = op_readstack();
|
||||
if($1) {
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
end;
|
||||
}
|
||||
4:last_cycle();
|
||||
regs.$2.h = op_readstack();
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
|
||||
pld(0x2b) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:regs.d.l = op_readstackn();
|
||||
4:last_cycle();
|
||||
regs.d.h = op_readstackn();
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
plb(0xab) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:last_cycle();
|
||||
regs.db = op_readstack();
|
||||
regs.p.n = !!(regs.db & 0x80);
|
||||
regs.p.z = (regs.db == 0);
|
||||
}
|
||||
|
||||
plp(0x28) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:last_cycle();
|
||||
regs.p = op_readstack();
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
pea(0xf4) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_writestackn(aa.h);
|
||||
4:last_cycle();
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
pei(0xd4) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:op_writestackn(aa.h);
|
||||
6:last_cycle();
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
per(0x62) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
rd.w = regs.pc.d + (int16)aa.w;
|
||||
4:op_writestackn(rd.h);
|
||||
5:last_cycle();
|
||||
op_writestackn(rd.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
@@ -1,539 +0,0 @@
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
//nop
|
||||
case 0xea: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
} break;
|
||||
|
||||
//wdm
|
||||
case 0x42: {
|
||||
last_cycle();
|
||||
op_readpc();
|
||||
} break;
|
||||
|
||||
//xba
|
||||
case 0xeb: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.a.h ^= regs.a.l;
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} break;
|
||||
|
||||
//mvn
|
||||
case 0x54: {
|
||||
dp = op_readpc();
|
||||
sp = op_readpc();
|
||||
regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
op_io();
|
||||
if(regs.p.x) {
|
||||
regs.x.l ++;
|
||||
regs.y.l ++;
|
||||
} else {
|
||||
regs.x.w ++;
|
||||
regs.y.w ++;
|
||||
}
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.a.w--) regs.pc.w -= 3;
|
||||
} break;
|
||||
|
||||
//mvp
|
||||
case 0x44: {
|
||||
dp = op_readpc();
|
||||
sp = op_readpc();
|
||||
regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
op_io();
|
||||
if(regs.p.x) {
|
||||
regs.x.l --;
|
||||
regs.y.l --;
|
||||
} else {
|
||||
regs.x.w --;
|
||||
regs.y.w --;
|
||||
}
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.a.w--) regs.pc.w -= 3;
|
||||
} break;
|
||||
|
||||
//brk
|
||||
case 0x00: {
|
||||
op_readpc();
|
||||
if(!regs.e) op_writestack(regs.pc.b);
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestack(regs.p);
|
||||
rd.l = op_readlong(regs.e ? 0xfffe : 0xffe6);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
last_cycle();
|
||||
rd.h = op_readlong(regs.e ? 0xffff : 0xffe7);
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
|
||||
//cop
|
||||
case 0x02: {
|
||||
op_readpc();
|
||||
if(!regs.e) op_writestack(regs.pc.b);
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestack(regs.p);
|
||||
rd.l = op_readlong(regs.e ? 0xfff4 : 0xffe4);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
last_cycle();
|
||||
rd.h = op_readlong(regs.e ? 0xfff5 : 0xffe5);
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
|
||||
//stp
|
||||
case 0xdb: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
while(true) op_io();
|
||||
} break;
|
||||
|
||||
//wai
|
||||
case 0xcb: {
|
||||
//last_cycle() will clear status.wai_lock once an NMI / IRQ edge is reached
|
||||
status.wai_lock = true;
|
||||
while(status.wai_lock) {
|
||||
last_cycle();
|
||||
op_io();
|
||||
}
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//xce
|
||||
case 0xfb: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = regs.e;
|
||||
regs.e = carry;
|
||||
if(regs.e) {
|
||||
regs.p |= 0x30;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
} break;
|
||||
|
||||
//clc
|
||||
case 0x18: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.c = 0;
|
||||
} break;
|
||||
|
||||
//cld
|
||||
case 0xd8: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.d = 0;
|
||||
} break;
|
||||
|
||||
//cli
|
||||
case 0x58: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.i = 0;
|
||||
} break;
|
||||
|
||||
//clv
|
||||
case 0xb8: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.v = 0;
|
||||
} break;
|
||||
|
||||
//sec
|
||||
case 0x38: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.c = 1;
|
||||
} break;
|
||||
|
||||
//sed
|
||||
case 0xf8: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.d = 1;
|
||||
} break;
|
||||
|
||||
//sei
|
||||
case 0x78: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.i = 1;
|
||||
} break;
|
||||
|
||||
//rep
|
||||
case 0xc2: {
|
||||
rd.l = op_readpc();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.p &=~ rd.l;
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
} break;
|
||||
|
||||
//sep
|
||||
case 0xe2: {
|
||||
rd.l = op_readpc();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.p |= rd.l;
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
} break;
|
||||
|
||||
//tax
|
||||
case 0xaa: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.a.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.a.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//tay
|
||||
case 0xa8: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.y.l = regs.a.l;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w = regs.a.w;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//txa
|
||||
case 0x8a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.a.l = regs.x.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w = regs.x.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//txy
|
||||
case 0x9b: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.y.l = regs.x.l;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w = regs.x.w;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//tya
|
||||
case 0x98: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.a.l = regs.y.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w = regs.y.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//tyx
|
||||
case 0xbb: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.y.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.y.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//tcd
|
||||
case 0x5b: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.d.w = regs.a.w;
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
} break;
|
||||
|
||||
//tcs
|
||||
case 0x1b: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.s.w = regs.a.w;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//tdc
|
||||
case 0x7b: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.a.w = regs.d.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
} break;
|
||||
|
||||
//tsc
|
||||
case 0x3b: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.a.w = regs.s.w;
|
||||
if(regs.e) {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//tsx
|
||||
case 0xba: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.s.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.s.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//txs
|
||||
case 0x9a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.e) {
|
||||
regs.s.l = regs.x.l;
|
||||
} else {
|
||||
regs.s.w = regs.x.w;
|
||||
}
|
||||
} break;
|
||||
|
||||
//pha
|
||||
case 0x48: {
|
||||
op_io();
|
||||
if(!regs.p.m)op_writestack(regs.a.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.a.l);
|
||||
} break;
|
||||
|
||||
//phx
|
||||
case 0xda: {
|
||||
op_io();
|
||||
if(!regs.p.x)op_writestack(regs.x.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.x.l);
|
||||
} break;
|
||||
|
||||
//phy
|
||||
case 0x5a: {
|
||||
op_io();
|
||||
if(!regs.p.x)op_writestack(regs.y.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.y.l);
|
||||
} break;
|
||||
|
||||
//phd
|
||||
case 0x0b: {
|
||||
op_io();
|
||||
op_writestackn(regs.d.h);
|
||||
last_cycle();
|
||||
op_writestackn(regs.d.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//phb
|
||||
case 0x8b: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_writestack(regs.db);
|
||||
} break;
|
||||
|
||||
//phk
|
||||
case 0x4b: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_writestack(regs.pc.b);
|
||||
} break;
|
||||
|
||||
//php
|
||||
case 0x08: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_writestack(regs.p);
|
||||
} break;
|
||||
|
||||
//pla
|
||||
case 0x68: {
|
||||
op_io();
|
||||
op_io();
|
||||
if(regs.p.m)last_cycle();
|
||||
regs.a.l = op_readstack();
|
||||
if(regs.p.m) {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
break;
|
||||
}
|
||||
last_cycle();
|
||||
regs.a.h = op_readstack();
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
} break;
|
||||
|
||||
//plx
|
||||
case 0xfa: {
|
||||
op_io();
|
||||
op_io();
|
||||
if(regs.p.x)last_cycle();
|
||||
regs.x.l = op_readstack();
|
||||
if(regs.p.x) {
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
break;
|
||||
}
|
||||
last_cycle();
|
||||
regs.x.h = op_readstack();
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
} break;
|
||||
|
||||
//ply
|
||||
case 0x7a: {
|
||||
op_io();
|
||||
op_io();
|
||||
if(regs.p.x)last_cycle();
|
||||
regs.y.l = op_readstack();
|
||||
if(regs.p.x) {
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
break;
|
||||
}
|
||||
last_cycle();
|
||||
regs.y.h = op_readstack();
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
} break;
|
||||
|
||||
//pld
|
||||
case 0x2b: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.d.l = op_readstackn();
|
||||
last_cycle();
|
||||
regs.d.h = op_readstackn();
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//plb
|
||||
case 0xab: {
|
||||
op_io();
|
||||
op_io();
|
||||
last_cycle();
|
||||
regs.db = op_readstack();
|
||||
regs.p.n = !!(regs.db & 0x80);
|
||||
regs.p.z = (regs.db == 0);
|
||||
} break;
|
||||
|
||||
//plp
|
||||
case 0x28: {
|
||||
op_io();
|
||||
op_io();
|
||||
last_cycle();
|
||||
regs.p = op_readstack();
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
} break;
|
||||
|
||||
//pea
|
||||
case 0xf4: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(aa.h);
|
||||
last_cycle();
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//pei
|
||||
case 0xd4: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_writestackn(aa.h);
|
||||
last_cycle();
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//per
|
||||
case 0x62: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.w = regs.pc.d + (int16)aa.w;
|
||||
op_writestackn(rd.h);
|
||||
last_cycle();
|
||||
op_writestackn(rd.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
#endif
|
@@ -1,163 +0,0 @@
|
||||
bcc(0x90, !regs.p.c),
|
||||
bcs(0xb0, regs.p.c),
|
||||
bne(0xd0, !regs.p.z),
|
||||
beq(0xf0, regs.p.z),
|
||||
bpl(0x10, !regs.p.n),
|
||||
bmi(0x30, regs.p.n),
|
||||
bvc(0x50, !regs.p.v),
|
||||
bvs(0x70, regs.p.v) {
|
||||
1:if(!$1) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if($1) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
end;
|
||||
}
|
||||
2:op_io_cond6(aa.w);
|
||||
3:last_cycle();
|
||||
op_io();
|
||||
}
|
||||
|
||||
bra(0x80) {
|
||||
1:rd.l = op_readpc();
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
2:op_io_cond6(aa.w);
|
||||
3:last_cycle();
|
||||
op_io();
|
||||
}
|
||||
|
||||
brl(0x82) {
|
||||
1:rd.l = op_readpc();
|
||||
2:rd.h = op_readpc();
|
||||
3:last_cycle();
|
||||
op_io();
|
||||
regs.pc.w = regs.pc.d + (int16)rd.w;
|
||||
}
|
||||
|
||||
jmp_addr(0x4c) {
|
||||
1:rd.l = op_readpc();
|
||||
2:last_cycle();
|
||||
rd.h = op_readpc();
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
jmp_long(0x5c) {
|
||||
1:rd.l = op_readpc();
|
||||
2:rd.h = op_readpc();
|
||||
3:last_cycle();
|
||||
rd.b = op_readpc();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
jmp_iaddr(0x6c) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:rd.l = op_readaddr(aa.w);
|
||||
4:last_cycle();
|
||||
rd.h = op_readaddr(aa.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
jmp_iaddrx(0x7c) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
4:rd.l = op_readpbr(aa.w + regs.x.w);
|
||||
5:last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
jmp_iladdr(0xdc) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:rd.l = op_readaddr(aa.w);
|
||||
4:rd.h = op_readaddr(aa.w + 1);
|
||||
5:last_cycle();
|
||||
rd.b = op_readaddr(aa.w + 2);
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
jsr_addr(0x20) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
4:regs.pc.w--;
|
||||
op_writestack(regs.pc.h);
|
||||
5:last_cycle();
|
||||
op_writestack(regs.pc.l);
|
||||
regs.pc.w = aa.w;
|
||||
}
|
||||
|
||||
jsr_long(0x22) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_writestackn(regs.pc.b);
|
||||
4:op_io();
|
||||
5:aa.b = op_readpc();
|
||||
6:regs.pc.w--;
|
||||
op_writestackn(regs.pc.h);
|
||||
7:last_cycle();
|
||||
op_writestackn(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
jsr_iaddrx(0xfc) {
|
||||
1:aa.l = op_readpc();
|
||||
2:op_writestackn(regs.pc.h);
|
||||
3:op_writestackn(regs.pc.l);
|
||||
4:aa.h = op_readpc();
|
||||
5:op_io();
|
||||
6:rd.l = op_readpbr(aa.w + regs.x.w);
|
||||
7:last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
rti(0x40) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:regs.p = op_readstack();
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
4:rd.l = op_readstack();
|
||||
5:if(regs.e) last_cycle();
|
||||
rd.h = op_readstack();
|
||||
if(regs.e) {
|
||||
regs.pc.w = rd.w;
|
||||
end;
|
||||
}
|
||||
6:last_cycle();
|
||||
rd.b = op_readstack();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
rts(0x60) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:rd.l = op_readstack();
|
||||
4:rd.h = op_readstack();
|
||||
5:last_cycle();
|
||||
op_io();
|
||||
regs.pc.w = rd.w;
|
||||
regs.pc.w++;
|
||||
}
|
||||
|
||||
rtl(0x6b) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:rd.l = op_readstackn();
|
||||
4:rd.h = op_readstackn();
|
||||
5:last_cycle();
|
||||
rd.b = op_readstackn();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
regs.pc.w++;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
@@ -1,279 +0,0 @@
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
//bcc
|
||||
case 0x90: {
|
||||
if(!!regs.p.c) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(!regs.p.c) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//bcs
|
||||
case 0xb0: {
|
||||
if(!regs.p.c) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.c) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//bne
|
||||
case 0xd0: {
|
||||
if(!!regs.p.z) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(!regs.p.z) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//beq
|
||||
case 0xf0: {
|
||||
if(!regs.p.z) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.z) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//bpl
|
||||
case 0x10: {
|
||||
if(!!regs.p.n) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(!regs.p.n) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//bmi
|
||||
case 0x30: {
|
||||
if(!regs.p.n) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.n) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//bvc
|
||||
case 0x50: {
|
||||
if(!!regs.p.v) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(!regs.p.v) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//bvs
|
||||
case 0x70: {
|
||||
if(!regs.p.v) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.v) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//bra
|
||||
case 0x80: {
|
||||
rd.l = op_readpc();
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//brl
|
||||
case 0x82: {
|
||||
rd.l = op_readpc();
|
||||
rd.h = op_readpc();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.pc.w = regs.pc.d + (int16)rd.w;
|
||||
} break;
|
||||
|
||||
//jmp_addr
|
||||
case 0x4c: {
|
||||
rd.l = op_readpc();
|
||||
last_cycle();
|
||||
rd.h = op_readpc();
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
|
||||
//jmp_long
|
||||
case 0x5c: {
|
||||
rd.l = op_readpc();
|
||||
rd.h = op_readpc();
|
||||
last_cycle();
|
||||
rd.b = op_readpc();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
} break;
|
||||
|
||||
//jmp_iaddr
|
||||
case 0x6c: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readaddr(aa.w);
|
||||
last_cycle();
|
||||
rd.h = op_readaddr(aa.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
|
||||
//jmp_iaddrx
|
||||
case 0x7c: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readpbr(aa.w + regs.x.w);
|
||||
last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
|
||||
//jmp_iladdr
|
||||
case 0xdc: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readaddr(aa.w);
|
||||
rd.h = op_readaddr(aa.w + 1);
|
||||
last_cycle();
|
||||
rd.b = op_readaddr(aa.w + 2);
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
} break;
|
||||
|
||||
//jsr_addr
|
||||
case 0x20: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
regs.pc.w--;
|
||||
op_writestack(regs.pc.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.pc.l);
|
||||
regs.pc.w = aa.w;
|
||||
} break;
|
||||
|
||||
//jsr_long
|
||||
case 0x22: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(regs.pc.b);
|
||||
op_io();
|
||||
aa.b = op_readpc();
|
||||
regs.pc.w--;
|
||||
op_writestackn(regs.pc.h);
|
||||
last_cycle();
|
||||
op_writestackn(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//jsr_iaddrx
|
||||
case 0xfc: {
|
||||
aa.l = op_readpc();
|
||||
op_writestackn(regs.pc.h);
|
||||
op_writestackn(regs.pc.l);
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readpbr(aa.w + regs.x.w);
|
||||
last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//rti
|
||||
case 0x40: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p = op_readstack();
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
rd.l = op_readstack();
|
||||
if(regs.e) last_cycle();
|
||||
rd.h = op_readstack();
|
||||
if(regs.e) {
|
||||
regs.pc.w = rd.w;
|
||||
break;
|
||||
}
|
||||
last_cycle();
|
||||
rd.b = op_readstack();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
} break;
|
||||
|
||||
//rts
|
||||
case 0x60: {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstack();
|
||||
rd.h = op_readstack();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.pc.w = rd.w;
|
||||
regs.pc.w++;
|
||||
} break;
|
||||
|
||||
//rtl
|
||||
case 0x6b: {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstackn();
|
||||
rd.h = op_readstackn();
|
||||
last_cycle();
|
||||
rd.b = op_readstackn();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
regs.pc.w++;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
#endif
|
@@ -1,317 +0,0 @@
|
||||
adc_const(0x69, adc, regs.p.m),
|
||||
and_const(0x29, and, regs.p.m),
|
||||
cmp_const(0xc9, cmp, regs.p.m),
|
||||
cpx_const(0xe0, cpx, regs.p.x),
|
||||
cpy_const(0xc0, cpy, regs.p.x),
|
||||
eor_const(0x49, eor, regs.p.m),
|
||||
lda_const(0xa9, lda, regs.p.m),
|
||||
ldx_const(0xa2, ldx, regs.p.x),
|
||||
ldy_const(0xa0, ldy, regs.p.x),
|
||||
ora_const(0x09, ora, regs.p.m),
|
||||
sbc_const(0xe9, sbc, regs.p.m) {
|
||||
1:if($2) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if($2) { op_$1_b(); end; }
|
||||
2:last_cycle();
|
||||
rd.h = op_readpc();
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_addr(0x6d, adc, regs.p.m),
|
||||
and_addr(0x2d, and, regs.p.m),
|
||||
bit_addr(0x2c, bit, regs.p.m),
|
||||
cmp_addr(0xcd, cmp, regs.p.m),
|
||||
cpx_addr(0xec, cpx, regs.p.x),
|
||||
cpy_addr(0xcc, cpy, regs.p.x),
|
||||
eor_addr(0x4d, eor, regs.p.m),
|
||||
lda_addr(0xad, lda, regs.p.m),
|
||||
ldx_addr(0xae, ldx, regs.p.x),
|
||||
ldy_addr(0xac, ldy, regs.p.x),
|
||||
ora_addr(0x0d, ora, regs.p.m),
|
||||
sbc_addr(0xed, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
4:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_addrx(0x7d, adc, regs.p.m),
|
||||
and_addrx(0x3d, and, regs.p.m),
|
||||
bit_addrx(0x3c, bit, regs.p.m),
|
||||
cmp_addrx(0xdd, cmp, regs.p.m),
|
||||
eor_addrx(0x5d, eor, regs.p.m),
|
||||
lda_addrx(0xbd, lda, regs.p.m),
|
||||
ldy_addrx(0xbc, ldy, regs.p.x),
|
||||
ora_addrx(0x1d, ora, regs.p.m),
|
||||
sbc_addrx(0xfd, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io_cond4(aa.w, aa.w + regs.x.w);
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_addry(0x79, adc, regs.p.m),
|
||||
and_addry(0x39, and, regs.p.m),
|
||||
cmp_addry(0xd9, cmp, regs.p.m),
|
||||
eor_addry(0x59, eor, regs.p.m),
|
||||
lda_addry(0xb9, lda, regs.p.m),
|
||||
ldx_addry(0xbe, ldx, regs.p.x),
|
||||
ora_addry(0x19, ora, regs.p.m),
|
||||
sbc_addry(0xf9, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_long(0x6f, adc, regs.p.m),
|
||||
and_long(0x2f, and, regs.p.m),
|
||||
cmp_long(0xcf, cmp, regs.p.m),
|
||||
eor_long(0x4f, eor, regs.p.m),
|
||||
lda_long(0xaf, lda, regs.p.m),
|
||||
ora_long(0x0f, ora, regs.p.m),
|
||||
sbc_long(0xef, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:aa.b = op_readpc();
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readlong(aa.d);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readlong(aa.d + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_longx(0x7f, adc, regs.p.m),
|
||||
and_longx(0x3f, and, regs.p.m),
|
||||
cmp_longx(0xdf, cmp, regs.p.m),
|
||||
eor_longx(0x5f, eor, regs.p.m),
|
||||
lda_longx(0xbf, lda, regs.p.m),
|
||||
ora_longx(0x1f, ora, regs.p.m),
|
||||
sbc_longx(0xff, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:aa.b = op_readpc();
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readlong(aa.d + regs.x.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readlong(aa.d + regs.x.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_dp(0x65, adc, regs.p.m),
|
||||
and_dp(0x25, and, regs.p.m),
|
||||
bit_dp(0x24, bit, regs.p.m),
|
||||
cmp_dp(0xc5, cmp, regs.p.m),
|
||||
cpx_dp(0xe4, cpx, regs.p.x),
|
||||
cpy_dp(0xc4, cpy, regs.p.x),
|
||||
eor_dp(0x45, eor, regs.p.m),
|
||||
lda_dp(0xa5, lda, regs.p.m),
|
||||
ldx_dp(0xa6, ldx, regs.p.x),
|
||||
ldy_dp(0xa4, ldy, regs.p.x),
|
||||
ora_dp(0x05, ora, regs.p.m),
|
||||
sbc_dp(0xe5, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:if($2) last_cycle();
|
||||
rd.l = op_readdp(dp);
|
||||
if($2) { op_$1_b(); end; }
|
||||
4:last_cycle();
|
||||
rd.h = op_readdp(dp + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_dpx(0x75, adc, regs.p.m),
|
||||
and_dpx(0x35, and, regs.p.m),
|
||||
bit_dpx(0x34, bit, regs.p.m),
|
||||
cmp_dpx(0xd5, cmp, regs.p.m),
|
||||
eor_dpx(0x55, eor, regs.p.m),
|
||||
lda_dpx(0xb5, lda, regs.p.m),
|
||||
ldy_dpx(0xb4, ldy, regs.p.x),
|
||||
ora_dpx(0x15, ora, regs.p.m),
|
||||
sbc_dpx(0xf5, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
ldx_dpy(0xb6, ldx, regs.p.x) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readdp(dp + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readdp(dp + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_idp(0x72, adc, regs.p.m),
|
||||
and_idp(0x32, and, regs.p.m),
|
||||
cmp_idp(0xd2, cmp, regs.p.m),
|
||||
eor_idp(0x52, eor, regs.p.m),
|
||||
lda_idp(0xb2, lda, regs.p.m),
|
||||
ora_idp(0x12, ora, regs.p.m),
|
||||
sbc_idp(0xf2, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
6:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_idpx(0x61, adc, regs.p.m),
|
||||
and_idpx(0x21, and, regs.p.m),
|
||||
cmp_idpx(0xc1, cmp, regs.p.m),
|
||||
eor_idpx(0x41, eor, regs.p.m),
|
||||
lda_idpx(0xa1, lda, regs.p.m),
|
||||
ora_idpx(0x01, ora, regs.p.m),
|
||||
sbc_idpx(0xe1, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:aa.l = op_readdp(dp + regs.x.w);
|
||||
5:aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
6:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_idpy(0x71, adc, regs.p.m),
|
||||
and_idpy(0x31, and, regs.p.m),
|
||||
cmp_idpy(0xd1, cmp, regs.p.m),
|
||||
eor_idpy(0x51, eor, regs.p.m),
|
||||
lda_idpy(0xb1, lda, regs.p.m),
|
||||
ora_idpy(0x11, ora, regs.p.m),
|
||||
sbc_idpy(0xf1, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
6:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_ildp(0x67, adc, regs.p.m),
|
||||
and_ildp(0x27, and, regs.p.m),
|
||||
cmp_ildp(0xc7, cmp, regs.p.m),
|
||||
eor_ildp(0x47, eor, regs.p.m),
|
||||
lda_ildp(0xa7, lda, regs.p.m),
|
||||
ora_ildp(0x07, ora, regs.p.m),
|
||||
sbc_ildp(0xe7, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:aa.b = op_readdp(dp + 2);
|
||||
6:if($2) last_cycle();
|
||||
rd.l = op_readlong(aa.d);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readlong(aa.d + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_ildpy(0x77, adc, regs.p.m),
|
||||
and_ildpy(0x37, and, regs.p.m),
|
||||
cmp_ildpy(0xd7, cmp, regs.p.m),
|
||||
eor_ildpy(0x57, eor, regs.p.m),
|
||||
lda_ildpy(0xb7, lda, regs.p.m),
|
||||
ora_ildpy(0x17, ora, regs.p.m),
|
||||
sbc_ildpy(0xf7, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:aa.b = op_readdp(dp + 2);
|
||||
6:if($2) last_cycle();
|
||||
rd.l = op_readlong(aa.d + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readlong(aa.d + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_sr(0x63, adc, regs.p.m),
|
||||
and_sr(0x23, and, regs.p.m),
|
||||
cmp_sr(0xc3, cmp, regs.p.m),
|
||||
eor_sr(0x43, eor, regs.p.m),
|
||||
lda_sr(0xa3, lda, regs.p.m),
|
||||
ora_sr(0x03, ora, regs.p.m),
|
||||
sbc_sr(0xe3, sbc, regs.p.m) {
|
||||
1:sp = op_readpc();
|
||||
2:op_io();
|
||||
3:if($2) last_cycle();
|
||||
rd.l = op_readsp(sp);
|
||||
if($2) { op_$1_b(); end; }
|
||||
4:last_cycle();
|
||||
rd.h = op_readsp(sp + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_isry(0x73, adc),
|
||||
and_isry(0x33, and),
|
||||
cmp_isry(0xd3, cmp),
|
||||
eor_isry(0x53, eor),
|
||||
lda_isry(0xb3, lda),
|
||||
ora_isry(0x13, ora),
|
||||
sbc_isry(0xf3, sbc) {
|
||||
1:sp = op_readpc();
|
||||
2:op_io();
|
||||
3:aa.l = op_readsp(sp);
|
||||
4:aa.h = op_readsp(sp + 1);
|
||||
5:op_io();
|
||||
6:if(regs.p.m) last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
if(regs.p.m) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
bit_const(0x89) {
|
||||
1:if(regs.p.m) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.m) {
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
end;
|
||||
}
|
||||
2:last_cycle();
|
||||
rd.h = op_readpc();
|
||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,181 +0,0 @@
|
||||
inc(0x1a, regs.p.m, a),
|
||||
inx(0xe8, regs.p.x, x),
|
||||
iny(0xc8, regs.p.x, y) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if($1) {
|
||||
regs.$2.l++;
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
} else {
|
||||
regs.$2.w++;
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
dec(0x3a, regs.p.m, a),
|
||||
dex(0xca, regs.p.x, x),
|
||||
dey(0x88, regs.p.x, y) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if($1) {
|
||||
regs.$2.l--;
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
} else {
|
||||
regs.$2.w--;
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
asl(0x0a) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
lsr(0x4a) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
rol(0x2a) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
uint16 c = regs.p.c;
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
ror(0x6a) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
uint16 c;
|
||||
if(regs.p.m) {
|
||||
c = regs.p.c ? 0x80 : 0;
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
c = regs.p.c ? 0x8000 : 0;
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
inc_addr(0xee, inc),
|
||||
dec_addr(0xce, dec),
|
||||
asl_addr(0x0e, asl),
|
||||
lsr_addr(0x4e, lsr),
|
||||
rol_addr(0x2e, rol),
|
||||
ror_addr(0x6e, ror),
|
||||
trb_addr(0x1c, trb),
|
||||
tsb_addr(0x0c, tsb) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:rd.l = op_readdbr(aa.w);
|
||||
4:if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
5:op_io();
|
||||
if(regs.p.m) { op_$1_b(); }
|
||||
else { op_$1_w();
|
||||
6:op_writedbr(aa.w + 1, rd.h); }
|
||||
7:last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
}
|
||||
|
||||
inc_addrx(0xfe, inc),
|
||||
dec_addrx(0xde, dec),
|
||||
asl_addrx(0x1e, asl),
|
||||
lsr_addrx(0x5e, lsr),
|
||||
rol_addrx(0x3e, rol),
|
||||
ror_addrx(0x7e, ror) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
4:rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
5:if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
6:op_io();
|
||||
if(regs.p.m) { op_$1_b(); }
|
||||
else { op_$1_w();
|
||||
7:op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
8:last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
}
|
||||
|
||||
inc_dp(0xe6, inc),
|
||||
dec_dp(0xc6, dec),
|
||||
asl_dp(0x06, asl),
|
||||
lsr_dp(0x46, lsr),
|
||||
rol_dp(0x26, rol),
|
||||
ror_dp(0x66, ror),
|
||||
trb_dp(0x14, trb),
|
||||
tsb_dp(0x04, tsb) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:rd.l = op_readdp(dp);
|
||||
4:if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
5:op_io();
|
||||
if(regs.p.m) { op_$1_b(); }
|
||||
else { op_$1_w();
|
||||
6:op_writedp(dp + 1, rd.h); }
|
||||
7:last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
}
|
||||
|
||||
inc_dpx(0xf6, inc),
|
||||
dec_dpx(0xd6, dec),
|
||||
asl_dpx(0x16, asl),
|
||||
lsr_dpx(0x56, lsr),
|
||||
rol_dpx(0x36, rol),
|
||||
ror_dpx(0x76, ror) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:rd.l = op_readdp(dp + regs.x.w);
|
||||
5:if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
6:op_io();
|
||||
if(regs.p.m) { op_$1_b(); }
|
||||
else { op_$1_w();
|
||||
7:op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
8:last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
}
|
@@ -1,573 +0,0 @@
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
//inc
|
||||
case 0x1a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.a.l++;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w++;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//inx
|
||||
case 0xe8: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l++;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w++;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//iny
|
||||
case 0xc8: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.y.l++;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w++;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//dec
|
||||
case 0x3a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.a.l--;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w--;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//dex
|
||||
case 0xca: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l--;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w--;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//dey
|
||||
case 0x88: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.y.l--;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w--;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//asl
|
||||
case 0x0a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//lsr
|
||||
case 0x4a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//rol
|
||||
case 0x2a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
uint16 c = regs.p.c;
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//ror
|
||||
case 0x6a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
uint16 c;
|
||||
if(regs.p.m) {
|
||||
c = regs.p.c ? 0x80 : 0;
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
c = regs.p.c ? 0x8000 : 0;
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//inc_addr
|
||||
case 0xee: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_inc_b(); }
|
||||
else { op_inc_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
|
||||
//dec_addr
|
||||
case 0xce: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_dec_b(); }
|
||||
else { op_dec_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
|
||||
//asl_addr
|
||||
case 0x0e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_asl_b(); }
|
||||
else { op_asl_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
|
||||
//lsr_addr
|
||||
case 0x4e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_lsr_b(); }
|
||||
else { op_lsr_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
|
||||
//rol_addr
|
||||
case 0x2e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_rol_b(); }
|
||||
else { op_rol_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
|
||||
//ror_addr
|
||||
case 0x6e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_ror_b(); }
|
||||
else { op_ror_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
|
||||
//trb_addr
|
||||
case 0x1c: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_trb_b(); }
|
||||
else { op_trb_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
|
||||
//tsb_addr
|
||||
case 0x0c: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_tsb_b(); }
|
||||
else { op_tsb_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
|
||||
//inc_addrx
|
||||
case 0xfe: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_inc_b(); }
|
||||
else { op_inc_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//dec_addrx
|
||||
case 0xde: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_dec_b(); }
|
||||
else { op_dec_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//asl_addrx
|
||||
case 0x1e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_asl_b(); }
|
||||
else { op_asl_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//lsr_addrx
|
||||
case 0x5e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_lsr_b(); }
|
||||
else { op_lsr_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//rol_addrx
|
||||
case 0x3e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_rol_b(); }
|
||||
else { op_rol_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//ror_addrx
|
||||
case 0x7e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_ror_b(); }
|
||||
else { op_ror_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//inc_dp
|
||||
case 0xe6: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_inc_b(); }
|
||||
else { op_inc_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
|
||||
//dec_dp
|
||||
case 0xc6: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_dec_b(); }
|
||||
else { op_dec_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
|
||||
//asl_dp
|
||||
case 0x06: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_asl_b(); }
|
||||
else { op_asl_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
|
||||
//lsr_dp
|
||||
case 0x46: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_lsr_b(); }
|
||||
else { op_lsr_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
|
||||
//rol_dp
|
||||
case 0x26: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_rol_b(); }
|
||||
else { op_rol_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
|
||||
//ror_dp
|
||||
case 0x66: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_ror_b(); }
|
||||
else { op_ror_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
|
||||
//trb_dp
|
||||
case 0x14: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_trb_b(); }
|
||||
else { op_trb_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
|
||||
//tsb_dp
|
||||
case 0x04: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_tsb_b(); }
|
||||
else { op_tsb_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
|
||||
//inc_dpx
|
||||
case 0xf6: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_inc_b(); }
|
||||
else { op_inc_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//dec_dpx
|
||||
case 0xd6: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_dec_b(); }
|
||||
else { op_dec_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//asl_dpx
|
||||
case 0x16: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_asl_b(); }
|
||||
else { op_asl_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//lsr_dpx
|
||||
case 0x56: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_lsr_b(); }
|
||||
else { op_lsr_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//rol_dpx
|
||||
case 0x36: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_rol_b(); }
|
||||
else { op_rol_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//ror_dpx
|
||||
case 0x76: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_ror_b(); }
|
||||
else { op_ror_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
#endif
|
@@ -1,181 +0,0 @@
|
||||
sta_addr(0x8d, regs.p.m, regs.a.w),
|
||||
stx_addr(0x8e, regs.p.x, regs.x.w),
|
||||
sty_addr(0x8c, regs.p.x, regs.y.w),
|
||||
stz_addr(0x9c, regs.p.m, 0x0000) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:if($1) last_cycle();
|
||||
op_writedbr(aa.w, $2);
|
||||
if($1) end;
|
||||
4:last_cycle();
|
||||
op_writedbr(aa.w + 1, $2 >> 8);
|
||||
}
|
||||
|
||||
sta_addrx(0x9d, regs.p.m, regs.a.w),
|
||||
stz_addrx(0x9e, regs.p.m, 0x0000) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
4:if($1) last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, $2);
|
||||
if($1) end;
|
||||
5:last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w + 1, $2 >> 8);
|
||||
}
|
||||
|
||||
sta_addry(0x99) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
4:if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
5:last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_long(0x8f) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:aa.b = op_readpc();
|
||||
4:if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
5:last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_longx(0x9f) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:aa.b = op_readpc();
|
||||
4:if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d + regs.x.w, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
5:last_cycle();
|
||||
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_dp(0x85, regs.p.m, regs.a.w),
|
||||
stx_dp(0x86, regs.p.x, regs.x.w),
|
||||
sty_dp(0x84, regs.p.x, regs.y.w),
|
||||
stz_dp(0x64, regs.p.m, 0x0000) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:if($1) last_cycle();
|
||||
op_writedp(dp, $2);
|
||||
if($1) end;
|
||||
4:last_cycle();
|
||||
op_writedp(dp + 1, $2 >> 8);
|
||||
}
|
||||
|
||||
sta_dpx(0x95, regs.p.m, regs.a.w),
|
||||
sty_dpx(0x94, regs.p.x, regs.y.w),
|
||||
stz_dpx(0x74, regs.p.m, 0x0000) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:if($1) last_cycle();
|
||||
op_writedp(dp + regs.x.w, $2);
|
||||
if($1) end;
|
||||
5:last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, $2 >> 8);
|
||||
}
|
||||
|
||||
stx_dpy(0x96) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:if(regs.p.x) last_cycle();
|
||||
op_writedp(dp + regs.y.w, regs.x.l);
|
||||
if(regs.p.x) end;
|
||||
5:last_cycle();
|
||||
op_writedp(dp + regs.y.w + 1, regs.x.h);
|
||||
}
|
||||
|
||||
sta_idp(0x92) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
6:last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_ildp(0x87) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:aa.b = op_readdp(dp + 2);
|
||||
6:if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
7:last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_idpx(0x81) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:aa.l = op_readdp(dp + regs.x.w);
|
||||
5:aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
6:if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
7:last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_idpy(0x91) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:op_io();
|
||||
6:if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
7:last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_ildpy(0x97) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:aa.b = op_readdp(dp + 2);
|
||||
6:if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d + regs.y.w, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
7:last_cycle();
|
||||
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_sr(0x83) {
|
||||
1:sp = op_readpc();
|
||||
2:op_io();
|
||||
3:if(regs.p.m) last_cycle();
|
||||
op_writesp(sp, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
4:last_cycle();
|
||||
op_writesp(sp + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_isry(0x93) {
|
||||
1:sp = op_readpc();
|
||||
2:op_io();
|
||||
3:aa.l = op_readsp(sp);
|
||||
4:aa.h = op_readsp(sp + 1);
|
||||
5:op_io();
|
||||
6:if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
7:last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
@@ -1,293 +0,0 @@
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
//sta_addr
|
||||
case 0x8d: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w, regs.a.w);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.w >> 8);
|
||||
} break;
|
||||
|
||||
//stx_addr
|
||||
case 0x8e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
if(regs.p.x) last_cycle();
|
||||
op_writedbr(aa.w, regs.x.w);
|
||||
if(regs.p.x) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.x.w >> 8);
|
||||
} break;
|
||||
|
||||
//sty_addr
|
||||
case 0x8c: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
if(regs.p.x) last_cycle();
|
||||
op_writedbr(aa.w, regs.y.w);
|
||||
if(regs.p.x) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.y.w >> 8);
|
||||
} break;
|
||||
|
||||
//stz_addr
|
||||
case 0x9c: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w, 0x0000);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, 0x0000 >> 8);
|
||||
} break;
|
||||
|
||||
//sta_addrx
|
||||
case 0x9d: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, regs.a.w);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w + 1, regs.a.w >> 8);
|
||||
} break;
|
||||
|
||||
//stz_addrx
|
||||
case 0x9e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, 0x0000);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w + 1, 0x0000 >> 8);
|
||||
} break;
|
||||
|
||||
//sta_addry
|
||||
case 0x99: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
//sta_long
|
||||
case 0x8f: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
//sta_longx
|
||||
case 0x9f: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d + regs.x.w, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
//sta_dp
|
||||
case 0x85: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedp(dp, regs.a.w);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, regs.a.w >> 8);
|
||||
} break;
|
||||
|
||||
//stx_dp
|
||||
case 0x86: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
if(regs.p.x) last_cycle();
|
||||
op_writedp(dp, regs.x.w);
|
||||
if(regs.p.x) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, regs.x.w >> 8);
|
||||
} break;
|
||||
|
||||
//sty_dp
|
||||
case 0x84: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
if(regs.p.x) last_cycle();
|
||||
op_writedp(dp, regs.y.w);
|
||||
if(regs.p.x) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, regs.y.w >> 8);
|
||||
} break;
|
||||
|
||||
//stz_dp
|
||||
case 0x64: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedp(dp, 0x0000);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, 0x0000 >> 8);
|
||||
} break;
|
||||
|
||||
//sta_dpx
|
||||
case 0x95: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedp(dp + regs.x.w, regs.a.w);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, regs.a.w >> 8);
|
||||
} break;
|
||||
|
||||
//sty_dpx
|
||||
case 0x94: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
if(regs.p.x) last_cycle();
|
||||
op_writedp(dp + regs.x.w, regs.y.w);
|
||||
if(regs.p.x) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, regs.y.w >> 8);
|
||||
} break;
|
||||
|
||||
//stz_dpx
|
||||
case 0x74: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedp(dp + regs.x.w, 0x0000);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, 0x0000 >> 8);
|
||||
} break;
|
||||
|
||||
//stx_dpy
|
||||
case 0x96: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
if(regs.p.x) last_cycle();
|
||||
op_writedp(dp + regs.y.w, regs.x.l);
|
||||
if(regs.p.x) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.y.w + 1, regs.x.h);
|
||||
} break;
|
||||
|
||||
//sta_idp
|
||||
case 0x92: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
//sta_ildp
|
||||
case 0x87: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
//sta_idpx
|
||||
case 0x81: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
aa.l = op_readdp(dp + regs.x.w);
|
||||
aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
//sta_idpy
|
||||
case 0x91: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
//sta_ildpy
|
||||
case 0x97: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d + regs.y.w, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
//sta_sr
|
||||
case 0x83: {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writesp(sp, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writesp(sp + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
//sta_isry
|
||||
case 0x93: {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
aa.l = op_readsp(sp);
|
||||
aa.h = op_readsp(sp + 1);
|
||||
op_io();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
#endif
|
@@ -1,12 +0,0 @@
|
||||
#define CLASS_NAME "sCPU"
|
||||
#include <tool/opgen_switch.cpp>
|
||||
|
||||
int main() {
|
||||
generate("op_read.cpp", "op_read.b");
|
||||
generate("op_write.cpp", "op_write.b");
|
||||
generate("op_rmw.cpp", "op_rmw.b");
|
||||
generate("op_pc.cpp", "op_pc.b");
|
||||
generate("op_misc.cpp", "op_misc.b");
|
||||
|
||||
return 0;
|
||||
}
|
@@ -3,6 +3,8 @@
|
||||
void sCPU::dma_add_clocks(unsigned clocks) {
|
||||
status.dma_clocks += clocks;
|
||||
add_clocks(clocks);
|
||||
scheduler.sync_cpucop();
|
||||
scheduler.sync_cpuppu();
|
||||
}
|
||||
|
||||
bool sCPU::dma_addr_valid(uint32 abus) {
|
||||
|
@@ -1,13 +1,5 @@
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
/*****
|
||||
* These 3 functions control bus timing for the CPU.
|
||||
* cpu_io is an I/O cycle, and always 6 clock cycles long.
|
||||
* mem_read / mem_write indicate memory access bus cycles.
|
||||
* they are either 6, 8, or 12 bus cycles long, depending
|
||||
* both on location and the $420d.d0 FastROM enable bit.
|
||||
*****/
|
||||
|
||||
void sCPU::op_io() {
|
||||
status.clock_count = 6;
|
||||
precycle_edge();
|
||||
@@ -16,9 +8,10 @@ void sCPU::op_io() {
|
||||
}
|
||||
|
||||
uint8 sCPU::op_read(uint32 addr) {
|
||||
status.clock_count = bus.speed(addr);
|
||||
status.clock_count = speed(addr);
|
||||
precycle_edge();
|
||||
add_clocks(status.clock_count - 4);
|
||||
scheduler.sync_cpucop();
|
||||
regs.mdr = bus.read(addr);
|
||||
add_clocks(4);
|
||||
cycle_edge();
|
||||
@@ -26,100 +19,23 @@ uint8 sCPU::op_read(uint32 addr) {
|
||||
}
|
||||
|
||||
void sCPU::op_write(uint32 addr, uint8 data) {
|
||||
status.clock_count = bus.speed(addr);
|
||||
status.clock_count = speed(addr);
|
||||
precycle_edge();
|
||||
add_clocks(status.clock_count);
|
||||
regs.mdr = data;
|
||||
bus.write(addr, regs.mdr);
|
||||
scheduler.sync_cpucop();
|
||||
bus.write(addr, regs.mdr = data);
|
||||
cycle_edge();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
alwaysinline uint8 sCPU::op_readpc() {
|
||||
return op_read((regs.pc.b << 16) + regs.pc.w++);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readstack() {
|
||||
if(regs.e) {
|
||||
regs.s.l++;
|
||||
} else {
|
||||
regs.s.w++;
|
||||
unsigned sCPU::speed(unsigned addr) const {
|
||||
if(addr & 0x408000) {
|
||||
if(addr & 0x800000) return status.rom_speed;
|
||||
return 8;
|
||||
}
|
||||
return op_read(regs.s.w);
|
||||
if((addr + 0x6000) & 0x4000) return 8;
|
||||
if((addr - 0x4000) & 0x7e00) return 6;
|
||||
return 12;
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readstackn() {
|
||||
return op_read(++regs.s.w);
|
||||
}
|
||||
#endif
|
||||
|
||||
alwaysinline uint8 sCPU::op_readaddr(uint32 addr) {
|
||||
return op_read(addr & 0xffff);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readlong(uint32 addr) {
|
||||
return op_read(addr & 0xffffff);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readdbr(uint32 addr) {
|
||||
return op_read(((regs.db << 16) + addr) & 0xffffff);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readpbr(uint32 addr) {
|
||||
return op_read((regs.pc.b << 16) + (addr & 0xffff));
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readdp(uint32 addr) {
|
||||
if(regs.e && regs.d.l == 0x00) {
|
||||
return op_read((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff));
|
||||
} else {
|
||||
return op_read((regs.d + (addr & 0xffff)) & 0xffff);
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readsp(uint32 addr) {
|
||||
return op_read((regs.s + (addr & 0xffff)) & 0xffff);
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writestack(uint8 data) {
|
||||
op_write(regs.s.w, data);
|
||||
if(regs.e) {
|
||||
regs.s.l--;
|
||||
} else {
|
||||
regs.s.w--;
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writestackn(uint8 data) {
|
||||
op_write(regs.s.w--, data);
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writeaddr(uint32 addr, uint8 data) {
|
||||
op_write(addr & 0xffff, data);
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writelong(uint32 addr, uint8 data) {
|
||||
op_write(addr & 0xffffff, data);
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writedbr(uint32 addr, uint8 data) {
|
||||
op_write(((regs.db << 16) + addr) & 0xffffff, data);
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writepbr(uint32 addr, uint8 data) {
|
||||
op_write((regs.pc.b << 16) + (addr & 0xffff), data);
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writedp(uint32 addr, uint8 data) {
|
||||
if(regs.e && regs.d.l == 0x00) {
|
||||
op_write((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff), data);
|
||||
} else {
|
||||
op_write((regs.d + (addr & 0xffff)) & 0xffff, data);
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writesp(uint32 addr, uint8 data) {
|
||||
op_write((regs.s + (addr & 0xffff)) & 0xffff, data);
|
||||
}
|
||||
|
||||
#endif //ifdef SCPU_CPP
|
||||
|
@@ -1,35 +1,16 @@
|
||||
/*****
|
||||
* CPU<>APU communication ports
|
||||
*****/
|
||||
uint8 apu_port[4];
|
||||
uint8 port_read(uint8 port) { return apu_port[port & 3]; }
|
||||
void port_write(uint8 port, uint8 data) { apu_port[port & 3] = data; }
|
||||
//============================
|
||||
//CPU<>APU communication ports
|
||||
//============================
|
||||
|
||||
/*****
|
||||
* core CPU bus functions
|
||||
*****/
|
||||
void op_io();
|
||||
uint8 op_read(uint32 addr);
|
||||
void op_write(uint32 addr, uint8 data);
|
||||
uint8 apu_port[4];
|
||||
uint8 port_read(uint8 port) { return apu_port[port & 3]; }
|
||||
void port_write(uint8 port, uint8 data) { apu_port[port & 3] = data; }
|
||||
|
||||
/*****
|
||||
* helper memory addressing functions used by CPU core
|
||||
*****/
|
||||
uint8 op_readpc ();
|
||||
uint8 op_readstack ();
|
||||
uint8 op_readstackn();
|
||||
uint8 op_readaddr (uint32 addr);
|
||||
uint8 op_readlong (uint32 addr);
|
||||
uint8 op_readdbr (uint32 addr);
|
||||
uint8 op_readpbr (uint32 addr);
|
||||
uint8 op_readdp (uint32 addr);
|
||||
uint8 op_readsp (uint32 addr);
|
||||
//======================
|
||||
//core CPU bus functions
|
||||
//======================
|
||||
|
||||
void op_writestack (uint8 data);
|
||||
void op_writestackn(uint8 data);
|
||||
void op_writeaddr (uint32 addr, uint8 data);
|
||||
void op_writelong (uint32 addr, uint8 data);
|
||||
void op_writedbr (uint32 addr, uint8 data);
|
||||
void op_writepbr (uint32 addr, uint8 data);
|
||||
void op_writedp (uint32 addr, uint8 data);
|
||||
void op_writesp (uint32 addr, uint8 data);
|
||||
void op_io();
|
||||
uint8 op_read(uint32 addr);
|
||||
void op_write(uint32 addr, uint8 data);
|
||||
alwaysinline unsigned speed(unsigned addr) const;
|
||||
|
@@ -42,7 +42,7 @@ void sCPU::mmio_w4016(uint8 data) {
|
||||
status.joypad_strobe_latch = !!(data & 1);
|
||||
|
||||
if(status.joypad_strobe_latch == 1) {
|
||||
snes.input.poll();
|
||||
input.poll();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ void sCPU::mmio_w4016(uint8 data) {
|
||||
//realtime or buffered status of joypadN.b
|
||||
uint8 sCPU::mmio_r4016() {
|
||||
uint8 r = regs.mdr & 0xfc;
|
||||
r |= snes.input.port_read(0) & 3;
|
||||
r |= input.port_read(0) & 3;
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ uint8 sCPU::mmio_r4016() {
|
||||
//1-0 = Joypad serial data
|
||||
uint8 sCPU::mmio_r4017() {
|
||||
uint8 r = (regs.mdr & 0xe0) | 0x1c;
|
||||
r |= snes.input.port_read(1) & 3;
|
||||
r |= input.port_read(1) & 3;
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ void sCPU::mmio_w4203(uint8 data) {
|
||||
status.r4216 = status.mul_a * status.mul_b;
|
||||
|
||||
status.alu_lock = true;
|
||||
event.enqueue(snes.config.cpu.alu_mul_delay, EventAluLockRelease);
|
||||
event.enqueue(config.cpu.alu_mul_delay, EventAluLockRelease);
|
||||
}
|
||||
|
||||
//WRDIVL
|
||||
@@ -113,7 +113,7 @@ void sCPU::mmio_w4206(uint8 data) {
|
||||
status.r4216 = (status.div_b) ? status.div_a % status.div_b : status.div_a;
|
||||
|
||||
status.alu_lock = true;
|
||||
event.enqueue(snes.config.cpu.alu_div_delay, EventAluLockRelease);
|
||||
event.enqueue(config.cpu.alu_div_delay, EventAluLockRelease);
|
||||
}
|
||||
|
||||
//HTIMEL
|
||||
@@ -157,7 +157,7 @@ void sCPU::mmio_w420c(uint8 data) {
|
||||
|
||||
//MEMSEL
|
||||
void sCPU::mmio_w420d(uint8 data) {
|
||||
bus.set_speed(data & 1);
|
||||
status.rom_speed = (data & 1 ? 6 : 8);
|
||||
}
|
||||
|
||||
//RDNMI
|
||||
@@ -402,6 +402,9 @@ void sCPU::mmio_reset() {
|
||||
status.hirq_pos = 0x01ff;
|
||||
status.virq_pos = 0x01ff;
|
||||
|
||||
//$420d
|
||||
status.rom_speed = 8;
|
||||
|
||||
//$4214-$4217
|
||||
status.r4214 = 0x0000;
|
||||
status.r4216 = 0x0000;
|
||||
|
@@ -1,16 +1,57 @@
|
||||
#include <../base.hpp>
|
||||
#define SCPU_CPP
|
||||
|
||||
#include <nall/priorityqueue.hpp>
|
||||
|
||||
#define SCPU_CPP
|
||||
namespace SNES {
|
||||
|
||||
priority_queue<unsigned> event(512, bind(&sCPU::queue_event, &cpu));
|
||||
|
||||
#include "core/core.cpp"
|
||||
#include "dma/dma.cpp"
|
||||
#include "memory/memory.cpp"
|
||||
#include "mmio/mmio.cpp"
|
||||
#include "timing/timing.cpp"
|
||||
|
||||
void sCPU::enter() {
|
||||
regs.pc.l = bus.read(0xfffc);
|
||||
regs.pc.h = bus.read(0xfffd);
|
||||
add_clocks(186);
|
||||
|
||||
while(true) {
|
||||
if(status.interrupt_pending) {
|
||||
status.interrupt_pending = false;
|
||||
if(status.nmi_pending) {
|
||||
status.nmi_pending = false;
|
||||
status.interrupt_vector = (regs.e == false ? 0xffea : 0xfffa);
|
||||
} else if(status.irq_pending) {
|
||||
status.irq_pending = false;
|
||||
status.interrupt_vector = (regs.e == false ? 0xffee : 0xfffe);
|
||||
}
|
||||
op_irq();
|
||||
}
|
||||
|
||||
tracer.trace_cpuop(); //traces CPU opcode (only if tracer is enabled)
|
||||
(this->*opcode_table[op_readpc()])();
|
||||
}
|
||||
}
|
||||
|
||||
void sCPU::op_irq() {
|
||||
op_read(regs.pc.d);
|
||||
op_io();
|
||||
if(!regs.e) op_writestack(regs.pc.b);
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestack(regs.e ? (regs.p & ~0x10) : regs.p);
|
||||
rd.l = op_read(status.interrupt_vector + 0);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
rd.h = op_read(status.interrupt_vector + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
void sCPU::power() {
|
||||
CPU::power();
|
||||
|
||||
regs.a = regs.x = regs.y = 0x0000;
|
||||
regs.s = 0x01ff;
|
||||
|
||||
@@ -22,11 +63,10 @@ void sCPU::power() {
|
||||
}
|
||||
|
||||
void sCPU::reset() {
|
||||
regs.pc.d = 0x000000;
|
||||
regs.pc.l = bus.read(0xfffc);
|
||||
regs.pc.h = bus.read(0xfffd);
|
||||
CPU::reset();
|
||||
|
||||
//note: some registers are not fully reset by SNES
|
||||
regs.pc = 0x000000;
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
regs.s.h = 0x01;
|
||||
@@ -35,8 +75,9 @@ void sCPU::reset() {
|
||||
regs.p = 0x34;
|
||||
regs.e = 1;
|
||||
regs.mdr = 0x00;
|
||||
regs.wai = false;
|
||||
update_table();
|
||||
|
||||
status.wai_lock = false;
|
||||
status.interrupt_pending = false;
|
||||
status.interrupt_vector = 0xfffc; //reset vector address
|
||||
|
||||
@@ -55,3 +96,5 @@ sCPU::sCPU() {
|
||||
|
||||
sCPU::~sCPU() {
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -1,8 +1,9 @@
|
||||
class sCPU : public CPU {
|
||||
class sCPU : public CPU, public CPUcore {
|
||||
public:
|
||||
void enter();
|
||||
void op_irq();
|
||||
bool interrupt_pending() { return status.interrupt_pending; }
|
||||
|
||||
#include "core/core.hpp"
|
||||
#include "dma/dma.hpp"
|
||||
#include "memory/memory.hpp"
|
||||
#include "mmio/mmio.hpp"
|
||||
@@ -11,11 +12,6 @@ public:
|
||||
enum DmaState { DmaInactive, DmaRun, DmaCpuSync };
|
||||
|
||||
struct {
|
||||
//core
|
||||
uint8 opcode;
|
||||
bool in_opcode;
|
||||
|
||||
bool wai_lock;
|
||||
bool interrupt_pending;
|
||||
uint16 interrupt_vector;
|
||||
|
||||
@@ -75,6 +71,9 @@ public:
|
||||
//$4207-$420a
|
||||
uint16 hirq_pos, virq_pos;
|
||||
|
||||
//$420d
|
||||
unsigned rom_speed;
|
||||
|
||||
//$4214-$4217
|
||||
uint16 r4214;
|
||||
uint16 r4216;
|
||||
|
@@ -93,14 +93,14 @@ bool sCPU::timeup() {
|
||||
bool sCPU::nmi_test() {
|
||||
if(!status.nmi_transition) return false;
|
||||
status.nmi_transition = false;
|
||||
status.wai_lock = false;
|
||||
regs.wai = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sCPU::irq_test() {
|
||||
if(!status.irq_transition) return false;
|
||||
if(!status.irq_transition && !regs.irq) return false;
|
||||
status.irq_transition = false;
|
||||
status.wai_lock = false;
|
||||
regs.wai = false;
|
||||
return !regs.p.i;
|
||||
}
|
||||
|
||||
|
@@ -3,8 +3,8 @@
|
||||
void sCPU::run_auto_joypad_poll() {
|
||||
uint16 joy1 = 0, joy2 = 0, joy3 = 0, joy4 = 0;
|
||||
for(unsigned i = 0; i < 16; i++) {
|
||||
uint8 port0 = snes.input.port_read(0);
|
||||
uint8 port1 = snes.input.port_read(1);
|
||||
uint8 port0 = input.port_read(0);
|
||||
uint8 port1 = input.port_read(1);
|
||||
|
||||
joy1 |= (port0 & 1) ? (0x8000 >> i) : 0;
|
||||
joy2 |= (port1 & 1) ? (0x8000 >> i) : 0;
|
||||
|
@@ -13,19 +13,25 @@ void sCPU::add_clocks(unsigned clocks) {
|
||||
unsigned ticks = clocks >> 1;
|
||||
while(ticks--) {
|
||||
ppu.tick();
|
||||
if((ppu.hcounter() & 2) == 0) {
|
||||
snes.input.tick();
|
||||
} else {
|
||||
if(ppu.hcounter() & 2) {
|
||||
input.tick();
|
||||
poll_interrupts();
|
||||
}
|
||||
}
|
||||
scheduler.addclocks_cpu(clocks);
|
||||
}
|
||||
|
||||
//called by ppu.tick() when Hcounter=0
|
||||
void sCPU::scanline() {
|
||||
status.dma_counter = (status.dma_counter + status.line_clocks) & 7;
|
||||
status.line_clocks = ppu.lineclocks();
|
||||
|
||||
//forcefully sync S-CPU to other processors, in case chips are not communicating
|
||||
scheduler.sync_cpuppu();
|
||||
scheduler.sync_cpucop();
|
||||
scheduler.sync_cpusmp();
|
||||
system.scanline();
|
||||
|
||||
if(ppu.vcounter() == 0) {
|
||||
//hdma init triggers once every frame
|
||||
event.enqueue(cpu_version == 1 ? 12 + 8 - dma_counter() : 12 + dma_counter(), EventHdmaInit);
|
||||
@@ -41,7 +47,7 @@ void sCPU::scanline() {
|
||||
}
|
||||
|
||||
if(status.auto_joypad_poll == true && ppu.vcounter() == (ppu.overscan() == false ? 227 : 242)) {
|
||||
snes.input.poll();
|
||||
input.poll();
|
||||
run_auto_joypad_poll();
|
||||
}
|
||||
}
|
||||
|
8
src/data/bsnes.desktop
Normal file
8
src/data/bsnes.desktop
Normal file
@@ -0,0 +1,8 @@
|
||||
[Desktop Entry]
|
||||
Name=bsnes
|
||||
Comment=SNES emulator
|
||||
Exec=bsnes
|
||||
Icon=bsnes
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=Game;Emulator;
|
File diff suppressed because it is too large
Load Diff
81
src/data/documentation.html
Normal file
81
src/data/documentation.html
Normal file
@@ -0,0 +1,81 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
|
||||
<h1>bsnes™ Usage Documentation</h1><br>
|
||||
|
||||
bsnes is a Super Nintendo / Super Famicom emulator that strives to provide
|
||||
the most faithful emulation experience possible. It focuses on accuracy and
|
||||
clean code; over speed and features.
|
||||
<hr>
|
||||
|
||||
<h2><u>Modes of Operation</u></h2><br>
|
||||
|
||||
bsnes is capable of running both in its default multi-user mode, as well as
|
||||
in single-user mode.<br>
|
||||
<br>
|
||||
|
||||
In multi-user mode, configuration data is stored inside the user's home
|
||||
directory. On Windows, this is located at "%APPDATA%/.bsnes". On other operating
|
||||
systems, this is located at "~/.bsnes".<br>
|
||||
<br>
|
||||
|
||||
To enable single-user mode, create a blank "bsnes.cfg" file inside the same
|
||||
folder as the bsnes executable. bsnes will then use this file to store
|
||||
configuration data.
|
||||
<hr>
|
||||
|
||||
<h2><u>Supported Filetypes</u></h2><br>
|
||||
|
||||
<b>SFC, SMC, SWC, FIG:</b> SNES cartridge — ROM image.<br>
|
||||
<b>BS:</b> Satellaview BS-X flash cartridge — EEPROM image.<br>
|
||||
<b>ST:</b> Sufami Turbo cartridge — ROM image.<br>
|
||||
<b>SRM, PSR:</b> non-volatile memory, often used to save game data — (P)SRAM image.<br>
|
||||
<b>RTC:</b> real-time clock non-volatile memory.<br>
|
||||
<b>UPS:</b> patch data, used to dynamically modify cartridge of same base filename upon load.<br>
|
||||
<b>CHT:</b> plain-text list of "Game Genie" / "Pro Action Replay" codes.
|
||||
<hr>
|
||||
|
||||
<h2><u>Known Limitations</u></h2><br>
|
||||
|
||||
<b>Cartridge co-processors:</b> certain cartridges contain special co-processor chips to enhance
|
||||
their functionality. Some of these are either partially or completely unsupported. A message box
|
||||
warning will pop up when attempting to load such a cartridge.<br>
|
||||
<br>
|
||||
|
||||
<b>Satellaview BS-X emulation:</b> this hardware is only partially supported. As a result,
|
||||
most BS-X software will not function correctly.<br>
|
||||
<br>
|
||||
|
||||
<b>Savestates:</b> due to the design of bsnes, it is not plausible to
|
||||
implement support for savestate and/or rewind functionality.<br>
|
||||
<br>
|
||||
|
||||
<b>Netplay:</b> internet multiplay is not currently supported nor planned.
|
||||
<hr>
|
||||
|
||||
<h2><u>Contributors</u></h2>
|
||||
• Andreas Naive<br>
|
||||
• anomie<br>
|
||||
• Derrick Sobodash<br>
|
||||
• DMV27<br>
|
||||
• FirebrandX<br>
|
||||
• FitzRoy<br>
|
||||
• GIGO<br>
|
||||
• Jonas Quinn<br>
|
||||
• kode54<br>
|
||||
• krom<br>
|
||||
• Matthew Callis<br>
|
||||
• Nach<br>
|
||||
• neviksti<br>
|
||||
• Overload<br>
|
||||
• RedDwarf<br>
|
||||
• Richard Bannister<br>
|
||||
• Shay Green<br>
|
||||
• tetsuo55<br>
|
||||
• TRAC<br>
|
||||
• zones<br>
|
||||
|
||||
</body>
|
||||
</html>
|
@@ -1,41 +0,0 @@
|
||||
static char enc_icon48[] = {
|
||||
"_gAB8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB8AHw"
|
||||
"AfD_AfAB8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB"
|
||||
"8AHwAfD_AfAB8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHw"
|
||||
"AfAB8AHwAfD_AfAB8AHwAfAB8AHwAfABAAD_qgAD_p8VOwD_oRaI_qEWthD-oBbL"
|
||||
"CADE_qEAFaP_oBZm_p38GBU28AHwAfAB8AHwAfBfAfAB8AFQuBCoAMe0AP4twAD_"
|
||||
"BPAEIPAkAIX_-JkZCkLwAfAB8AHwAfBHAfAB8HSB_wABtABvPQQA-7DwBPAEECwA"
|
||||
"0P74oBIbTvAB8AHwAfAB8EcB8AHweEGgFWwkAv0HqPAE8MSwFdX-oRr-E1LwAfAB"
|
||||
"8AHwAfAB8Lzg6KEUMRAC96DwBPAE8P3EIKXAEVrwAfAB8AHwAfDzAfDAsBa3mPAE"
|
||||
"8ATwwED_uAE4E1rwAfAB8AHwAfAB8PG8YKIVJDjyBPAE8ATA-KAWoF7wAfAB8AHw"
|
||||
"AfB7AfD4gmmQ8ATwBPDM4-Z_XvAB8AHwAfAB8AHwwICPH_wSePQE8ATwBMClDxEB"
|
||||
"YNBERP8PPz_-oEw-Pv56CACMCACCgggAXT8__yD2BA808wHwAfDAkKMSDv6AmxwS"
|
||||
"_qQYH8QC6kjIAJTUAOug8ATwhOFDRABYUDw8_hWsAI9QPj7_8KwA_wTw_oL6BAC1"
|
||||
"PT3-MpbwjwHwAfAB8AxmpRkUFAOOkxjzBPAEoJ8PEEAQdZQAOrwA47TwBPAoAPh9"
|
||||
"yAB0hvAB8AHwAfBcsha6XFwC-KzwBPDsAOQ0EHWQAD0EAPSs8ATwBMCAn4LwAfAB"
|
||||
"8AHwXLUVakz4gwTwKACbQkL-F0wBTuac8ATwiPH-_AQATh-C8AHwAfAB8ExifwAC"
|
||||
"DcAAtbTwfKT8_qETejSAAJOc8ATwBPAUY9p9CAAIhvAB8AHwAfCEYZ4MGDWE8YCn"
|
||||
"nEs8_3oRgAD1lPAE8ATwBKBVh4LwAQAUCwDNACQEAKBNAMwAaggAewgAoH8AywBz"
|
||||
"CABbCABgNwDIAA458Nxp2IO88Hwhzf-ZEQ-0A15XjPAE8ATwhOGlfaDOVAA1oACY"
|
||||
"sADhCAD9jQgA_wTwBEDMAPQEAHq7NABjCAAcq2QRvPAW9sUMXHwAiIzwBPAE8MDg"
|
||||
"otZxIMsAGYQArQQATv6s8ATwzPAA4wQAUVcKAGQmYAR9MILpBAB3sP-qKgbgUPwC"
|
||||
"mwQAevuAAP6U8ATwBPDAYO3QANEAHIQA3JjwBPCrBPAEoPwEAGyAQVRwAeCV_qIX"
|
||||
"WPQWZNJ8AKoQgAQbSAI2hABtzAC6xAgA_aDwBPCIxOc4Ab6mjPAE8ATwBPAEAPYE"
|
||||
"AK9YZwHwAfA2QwLAAEgEAK7dqPAE8MCAx8AA5Ijw_wTwBPAE8ExCFPQB8AHwAQDQ"
|
||||
"Q0P-E5QAw6zwBPD1wECLcAC2iPAE8ATwBPD1BAD70AMqmvAB8AHwATDQODj-EpgA"
|
||||
"1LDwxPbFBAAxcCDNAOyM8ATwewTwBOCGkvAB8AHwIOM8t-AzuPC8g66UasQwyJDw"
|
||||
"VwTwBPAEIPHEBG4KAAJBDcYKAP7-LAQAT1UEAGUEAHAEAGoEAFd1BAA5BAASJAAY"
|
||||
"-8Qg_gaytPB8Yeg7O_8eUTGgvwAEyABUUAK3XZAA9aTw6OJsFdgIAIOQAM8AG_11"
|
||||
"_guUAKpgCAC1BADvDAD_BPAxBED-_vgIAEoA_nzDBAD4o0BA_lO88Lwgjuy4FPLw"
|
||||
"AYDPABCYAKpCoABtBACKBACbEACKngQAk4wnzQBXoCd3qBe5plgh4azwBPDM8P76"
|
||||
"9QQAiwwA1CjgGeQSvMD6yAQAKbHwAfAB8AHwvMC9RBH-nPAE8ATwBKDAxCFVVDXu"
|
||||
"sADzCAC9dEgEX3nwAfAB8AHwvMAxBAD8X4zwBPAE8ATwTAB-3Ewh_bQADHHwAfAB"
|
||||
"8AHwAfDAYL50iPAE8ATwBPDAQMRl8L8B8AHwAfAB8AHwcABMiPDvBPAE8ATwwECc"
|
||||
"ZfAB8AHwrwHwAfAB8HQAAnQAsIzw9wTwBPC84OQIABy1AfAB8O8B8AHwAfDs1ZUI"
|
||||
"8wTwBPD1vGDHBAAkXfAB8AHwAfCnAfAB8Mjw_zCEAJ8EAK7rpPAE8CgA9wQAvAQA"
|
||||
"_lQQAJC1AfAB8AHwAfAB8FcB8MjwkBE6BABsBACPVQQApAQArwQAqQQAl_UgAHgI"
|
||||
"AEsEANQsAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB8AHwAfD_AfAB"
|
||||
"8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB8AHwAfD_"
|
||||
"AfAB8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB8AHw"
|
||||
"AfD_AfAB8AHwAfAB8AHwAfAB8A8B8AHwAfABsA"
|
||||
};
|
BIN
src/data/joypad.png
Normal file
BIN
src/data/joypad.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 100 KiB |
87
src/data/license.html
Normal file
87
src/data/license.html
Normal file
@@ -0,0 +1,87 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
|
||||
<h1>bsnes™ Reference License</h1><br>
|
||||
<b>Copyright © 2004–2009 byuu<br>
|
||||
All rights reserved</b>
|
||||
<hr>
|
||||
|
||||
<h2><u>1. Definitions</u></h2><br>
|
||||
|
||||
The terms "reproduce", "reproduction", "distribute" and "distribution" have the
|
||||
same meaning here as under U.S. copyright law.<br><br>
|
||||
|
||||
"The software" means this software package as a whole, including, but not
|
||||
limited to, this license, binaries, source code, documentation, and data.<br><br>
|
||||
|
||||
"You" means the licensee of the software.<br><br>
|
||||
|
||||
"The licensor" means the copyright holder of the software, byuu.
|
||||
<hr>
|
||||
|
||||
<h2><u>2. Grant of Rights</u></h2><br>
|
||||
|
||||
Subject to the terms of this license, the licensor grants you a
|
||||
non-transferable, non-exclusive, worldwide, royalty-free copyright license to
|
||||
reproduce the software for non-commercial use only, provided the software
|
||||
remains unmodified, and there is no charge for the software itself, nor for the
|
||||
medium upon which the software is distributed. The reproduction of modified or
|
||||
derivative works of the software is strictly prohibited without the express
|
||||
consent of the licensor.
|
||||
<hr>
|
||||
|
||||
<h2><u>3. Limitations</u></h2><br>
|
||||
|
||||
This license does not grant you any rights to use the licensor's name, logo or
|
||||
trademarks.<br>
|
||||
<br>
|
||||
|
||||
The software is provided "as is", and any express or implied warranties,
|
||||
including, but not limited to, the implied warranties of merchantability and
|
||||
fitness for a particular purpose are disclaimed. In no event shall the licensor
|
||||
be liable for any direct, indirect, incidental, special, exemplary, or
|
||||
consequential damages (including, but not limited to, procurement of sbustitute
|
||||
goods or services; loss of use, data, or profits; or business interruption)
|
||||
however caused and on any theory of liability, whether in contract, strict
|
||||
liability, or tort (including negligence or otherwise) arising in any way out of
|
||||
the use of the software, even if advised of the possibility of such damage.<br>
|
||||
<br>
|
||||
|
||||
In the event that this license is determined to be invalid or unenforceable, the
|
||||
Grant of Rights will become null and void, and no rights shall be granted to the
|
||||
licensee, within the scope of U.S. copyright law.
|
||||
<hr>
|
||||
|
||||
<h2><u>4. Exemptions</u></h2><br>
|
||||
|
||||
The software includes the work of other copyrights holders, which is licensed
|
||||
under different agreements, and exempt from this license. Below is a complete
|
||||
list of all such software, and their respective copyright holders and licenses.
|
||||
Note that explicit permission has been granted to the licensor to use included
|
||||
software which is ordinarily not compatible with this license, such as the GPL.
|
||||
<br>
|
||||
|
||||
<table border="1" cellpadding="3">
|
||||
<tr><td><b>Name</b></td><td><b>License</b></td><td><b>Author(s)</b></td></tr>
|
||||
|
||||
<tr><td>Cx4 emulator</td><td></td><td>anomie, Kris Bleakley, Nach, zsKnight</td></tr>
|
||||
<tr><td>DSP-1 emulator</td><td></td><td>Andreas Naive, John Weidman, Kris Bleakley, neviksti</td></tr>
|
||||
<tr><td>DSP-2 emulator</td><td></td><td>Kris Bleakley</td></tr>
|
||||
<tr><td>DSP-3 emulator</td><td></td><td>John Weidman, Kris Bleakley, Lancer, z80 gaiden</td></tr>
|
||||
<tr><td>DSP-4 emulator</td><td></td><td>Dreamer Nom, John Weidman, Kris Bleakley, Nach, z80 gaiden</td></tr>
|
||||
<tr><td>S-DD1 decompressor</td><td>Public Domain</td><td>Andreas Naive</td></tr>
|
||||
<tr><td>S-DSP emulator</td><td>LGPL 2.1</td><td>Shay Green</td></tr>
|
||||
<tr><td>SPC7110 decompressor</td><td>Public Domain</td><td>neviksti</td></tr>
|
||||
<tr><td>ST-0010 emulator</td><td></td><td>Feather, John Weidman, Kris Bleakley, Matthew Kendora</td></tr>
|
||||
|
||||
<tr><td>Qt toolkit</td><td>LGPL 2.1</td><td>Nokia</td></tr>
|
||||
<tr><td>HQ2x filter</td><td>LGPL 2.1</td><td>MaxST</td></tr>
|
||||
<tr><td>JMA decompressor</td><td>GPL 2</td><td>NSRT team</td></tr>
|
||||
<tr><td>NTSC filter</td><td>LGPL 2.1</td><td>Shay Green</td></tr>
|
||||
<tr><td>zlib decompressor</td><td>zlib license</td><td>zlib team</td></tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
BIN
src/data/logo.png
Normal file
BIN
src/data/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user