o switch to v46

This commit is contained in:
David Voswinkel 2009-05-12 22:17:42 +02:00
parent 7a878eab39
commit 8e877d38d4
217 changed files with 1440 additions and 31284 deletions

View File

@ -1,141 +1,92 @@
include lib/nall/Makefile.string include lib/nall/Makefile
prefix = /usr/local
ui = ui_qt ui = ui_qt
platform=x
compiler=gcc
enable_gzip=false
################ ################
### compiler ### ### compiler ###
################ ################
platform=mac c := $(compiler)
compiler=gcc cpp := $(subst cc,++,$(compiler))
enable_gzip=false flags := -ggdb -O3 -fomit-frame-pointer -Ilib \
-I/Developer/SDKs/Qt/include \
-I/Developer/SDKs/Qt/include/QtCore \
-I/Developer/SDKs/Qt/include/QtGui \
-I/System/Library/Frameworks/OpenGL.framework/Versions/A/Headers \
-I/System/Library/Frameworks/AGL.framework/Headers \
-I/Developer/SDKs/Qt/include/QtOpenGL -I/usr/X11R6/include
link :=
ifneq ($(findstring gcc,$(compiler)),) # GCC family # profile-guided instrumentation:
flags = -O2 -fomit-frame-pointer -Ilib # flags += -fprofile-generate
libcoflags := $(flags) -static # link += -lgcov
c = $(compiler)
cpp = $(subst cc,++,$(compiler)) # profile-guided optimization:
obj = o #flags += -fprofile-use
rule = -c $< -o $@
link = ################
mkbin = -o$1 ### platform ###
mkdef = -D$1 ################
mkincpath = -I$1
mklib = -l$1 ifeq ($(platform),x)
mklibpath = -L$1 ruby := video.glx video.xv video.sdl
# profile-guided optimization: ruby += audio.alsa audio.openal audio.oss audio.pulseaudio audio.ao
#flags += -fprofile-generate ruby += input.sdl input.x
#link += -lgcov else ifeq ($(platform),win)
#flags += -fprofile-use ruby := video.direct3d video.wgl video.directdraw video.gdi
flags += -g -ggdb -export-symbols ruby += audio.directsound
else ifeq ($(compiler),cl) # Visual C++ ruby += input.rawinput input.directinput
flags = /nologo /wd4355 /wd4805 /wd4996 /Ox /GL /EHsc /Ilib
libcoflags = $(flags) link += -mwindows
c = cl # link += -mconsole
cpp = cl link += -luuid -lkernel32 -luser32 -lgdi32 -lshell32
obj = obj # statically link Qt for Windows build
rule = /c $< /Fo$@ link += -enable-stdcall-fixup -Wl,-s -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
link = /link
mkbin = /Fe$1
mkdef = /D$1
mkincpath = /I$1
mklib = $1.lib
mklibpath = /L$1
else else
unknown_compiler: help; unknown_platform: help;
endif
##########
### os ###
##########
ifeq ($(platform),mac) #Mac
ruby = video.glx video.xv video.sdl audio.alsa audio.openal audio.oss audio.pulseaudio audio.ao input.sdl input.x
mkbin = -o $1
delete = rm -f $1
link += -L/opt/local/lib \
-lSDL -framework,Cocoa \
-lX11 \
-lm \
-framework Foundation\
-framework Cocoa \
-framework AGL \
-framework OpenAL\
-framework ApplicationServices \
-framework Foundation\
-framework OpenGL\
-framework GLUT \
-lz \
-lgl \
-lao
flags +=-I/opt/local/include \
-I/System/Library/Frameworks/OpenAL.framework/Versions/A/Headers/\
-DVIDEO_SDL \
-DINPUT_SDL \
-DVIDEO_GLX \
-DAUDIO_AO \
-DAUDIO_OPENAL
endif
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
delete = rm -f $1
else ifeq ($(platform),win) # Windows
mingw_link_flags = -mwindows
# mingw_links_flags = -mconsole
# enable static linking to Qt for Windows build
mingw_link_flags += -enable-stdcall-fixup -Wl,-s -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
ruby = video.direct3d video.wgl video.directdraw video.gdi audio.directsound input.rawinput input.directinput
delete = $(if $(findstring i586-mingw-gcc,$(compiler)),rm -f $1,del $(subst /,\,$1))
link += $(if $(findstring mingw,$(compiler)),$(mingw_link_flags))
link += $(call mklib,uuid)
link += $(call mklib,kernel32)
link += $(call mklib,user32)
link += $(call mklib,gdi32)
link += $(call mklib,shell32)
endif endif
############ ############
### ruby ### ### ruby ###
############ ############
rubyflags = $(if $(findstring .sdl,$(ruby)),`sdl-config --cflags`) rubyflags = $(call ifhas,.sdl,$(ruby),`sdl-config --cflags`)
#link += $(if $(findstring .sdl,$(ruby)),`sdl-config --libs`)
#link += $(if $(findstring video.direct3d,$(ruby)),$(call mklib,d3d9)) link += $(call ifhas,.sdl,$(ruby),`sdl-config --libs`)
#link += $(if $(findstring video.directdraw,$(ruby)),$(call mklib,ddraw)) link += $(call ifhas,video.direct3d,$(ruby),-ld3d9)
#link += $(if $(findstring video.glx,$(ruby)),$(call mklib,GL)) link += $(call ifhas,video.directdraw,$(ruby),-lddraw)
#link += $(if $(findstring video.wgl,$(ruby)),$(call mklib,opengl32)) link += $(call ifhas,video.glx,$(ruby),-lGL)
#link += $(if $(findstring video.xv,$(ruby)),$(call mklib,Xv)) link += $(call ifhas,video.wgl,$(ruby),-lopengl32)
#link += $(if $(findstring audio.alsa,$(ruby)),$(call mklib,asound)) link += $(call ifhas,video.xv,$(ruby),-lXv)
#link += $(if $(findstring audio.ao,$(ruby)),$(call mklib,ao)) link += $(call ifhas,audio.alsa,$(ruby),-lasound)
#link += $(if $(findstring audio.directsound,$(ruby)),$(call mklib,dsound)) link += $(call ifhas,audio.ao,$(ruby),-lao)
#link += $(if $(findstring audio.openal,$(ruby)),$(if $(call streq,$(platform),x),$(call mklib,openal),$(call mklib,openal32))) link += $(call ifhas,audio.directsound,$(ruby),-ldsound)
#link += $(if $(findstring audio.pulseaudio,$(ruby)),$(call mklib,pulse-simple)) link += $(call ifhas,audio.openal,$(ruby),$(if $(call streq,$(platform),x),-lopenal,-lopenal32))
#link += $(if $(findstring input.directinput,$(ruby)),$(call mklib,dinput8) $(call mklib,dxguid)) link += $(call ifhas,audio.pulseaudio,$(ruby),-lpulse-simple)
#link += $(if $(findstring input.rawinput,$(ruby)),$(call mklib,xinput) $(call mklib,dinput8) $(call mklib,dxguid)) link += $(call ifhas,input.directinput,$(ruby),-ldinput8 -ldxguid)
link += $(call ifhas,input.rawinput,$(ruby),-lxinput -ldinput8 -ldxguid)
#################### ####################
### core objects ### ### core objects ###
#################### ####################
objects = libco ruby libfilter string \ objects = libco ruby libreader libfilter string \
reader cart cheat \ system cartridge cheat \
memory smemory cpu scpu smp ssmp sdsp ppu bppu snes \ memory smemory cpu cpucore scpu smp smpcore ssmp sdsp ppu bppu \
bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010 sgb sa1 bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010
ifeq ($(enable_gzip),true) ifeq ($(enable_gzip),true)
#objects += adler32 compress crc32 deflate gzio inffast inflate inftrees ioapi trees unzip zip zutil objects += adler32 compress crc32 deflate gzio inffast inflate inftrees ioapi trees unzip zip zutil
#flags += $(call mkdef,GZIP_SUPPORT) flags += -DGZIP_SUPPORT
endif endif
ifeq ($(enable_jma),true) ifeq ($(enable_jma),true)
#objects += jma jcrc32 lzmadec 7zlzma iiostrm inbyte lzma winout objects += jma jcrc32 lzmadec 7zlzma iiostrm inbyte lzma winout
#flags += $(call mkdef,JMA_SUPPORT) flags += -DJMA_SUPPORT
endif endif
###################### ######################
@ -145,135 +96,139 @@ endif
compile = \ compile = \
$(strip \ $(strip \
$(if $(filter %.c,$<), \ $(if $(filter %.c,$<), \
$(c) $(flags) $1 $(rule), \ $(c) $(flags) $1 -c $< -o $@, \
$(if $(filter %.cpp,$<), \ $(if $(filter %.cpp,$<), \
$(cpp) $(flags) $1 $(rule) \ $(cpp) $(flags) $1 -c $< -o $@ \
) \ ) \
) \ ) \
) )
%.$(obj): $<; $(call compile) %.o: $<; $(call compile)
all: build; all: build;
include $(ui)/Makefile include $(ui)/Makefile
objects := $(patsubst %,obj/%.o,$(objects))
objects := $(patsubst %,obj/%.$(obj),$(objects)) rubydef := $(foreach c,$(subst .,_,$(call strupper,$(ruby))),-D$c)
#rubydef := $(foreach c,$(subst .,_,$(call strupper,$(ruby))),$(call mkdef,$c)) #-DVIDEO_GLX -DVIDEO_XV -DVIDEO_SDL -DAUDIO_ALSA -DAUDIO_OPENAL -DAUDIO_OSS -DAUDIO_PULSEAUDIO -DAUDIO_AO -DINPUT_SDL -DINPUT_X
rubydef =-DVIDEO_SDL -DINPUT_SDL
################# #################
### libraries ### ### 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)) $(call compile,$(rubydef) $(rubyflags))
obj/libco.$(obj): lib/libco/libco.c lib/libco/* obj/libco.o: lib/libco/libco.c lib/libco/*
$(c) $(libcoflags) $(rule) $(c) -O3 -fomit-frame-pointer -static -Ilib -c $< -o $@
obj/libfilter.$(obj): lib/libfilter/libfilter.cpp lib/libfilter/* obj/libreader.o: lib/libreader/libreader.cpp lib/libreader/*
obj/string.$(obj): lib/nall/string.cpp lib/nall/* obj/libfilter.o: lib/libfilter/libfilter.cpp lib/libfilter/*
obj/string.o: lib/nall/string.cpp lib/nall/*
################# #################
### utilities ### ### utilities ###
################# #################
obj/reader.$(obj): reader/reader.cpp reader/* obj/cartridge.o: cartridge/cartridge.cpp cartridge/*
obj/cart.$(obj) : cart/cart.cpp cart/* obj/cheat.o : cheat/cheat.cpp cheat/*
obj/cheat.$(obj) : cheat/cheat.cpp cheat/*
############## ##############
### memory ### ### memory ###
############## ##############
obj/memory.$(obj) : memory/memory.cpp memory/* obj/memory.o : memory/memory.cpp memory/*
obj/smemory.$(obj): memory/smemory/smemory.cpp memory/smemory/* memory/smemory/mapper/* obj/smemory.o: memory/smemory/smemory.cpp $(call rwildcard,memory/smemory/)
########### ###########
### cpu ### ### cpu ###
########### ###########
obj/cpu.$(obj) : cpu/cpu.cpp cpu/* obj/cpu.o : 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/cpucore.o: cpu/core/core.cpp $(call rwildcard,cpu/core/)
obj/scpu.o : cpu/scpu/scpu.cpp $(call rwildcard,cpu/scpu/)
########### ###########
### smp ### ### smp ###
########### ###########
obj/smp.$(obj) : smp/smp.cpp smp/* obj/smp.o : smp/smp.cpp smp/*
obj/ssmp.$(obj): smp/ssmp/ssmp.cpp smp/ssmp/* smp/ssmp/core/* smp/ssmp/memory/* smp/ssmp/timing/* obj/smpcore.o: smp/core/core.cpp $(call rwildcard,smp/core/)
obj/ssmp.o : smp/ssmp/ssmp.cpp $(call rwildcard,smp/ssmp/)
########### ###########
### dsp ### ### dsp ###
########### ###########
obj/adsp.$(obj): dsp/adsp/adsp.cpp dsp/adsp/* obj/adsp.o: dsp/adsp/adsp.cpp dsp/adsp/*
obj/sdsp.$(obj): dsp/sdsp/sdsp.cpp dsp/sdsp/* obj/sdsp.o: dsp/sdsp/sdsp.cpp dsp/sdsp/*
########### ###########
### ppu ### ### ppu ###
########### ###########
obj/ppu.$(obj) : ppu/ppu.cpp ppu/* obj/ppu.o : ppu/ppu.cpp ppu/*
obj/bppu.$(obj): ppu/bppu/bppu.cpp ppu/bppu/* 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 ### ### special chips ###
##################### #####################
obj/bsx.$(obj) : chip/bsx/bsx.cpp chip/bsx/* obj/sgb.o : chip/sgb/sgb.cpp $(call rwildcard,chip/sgb/)
obj/srtc.$(obj) : chip/srtc/srtc.cpp chip/srtc/* obj/sa1.o : chip/sa1/sa1.cpp $(call rwildcard,chip/sa1/)
obj/sdd1.$(obj) : chip/sdd1/sdd1.cpp chip/sdd1/* obj/bsx.o : chip/bsx/bsx.cpp chip/bsx/*
obj/spc7110.$(obj): chip/spc7110/spc7110.cpp chip/spc7110/* obj/srtc.o : chip/srtc/srtc.cpp chip/srtc/*
obj/cx4.$(obj) : chip/cx4/cx4.cpp chip/cx4/* obj/sdd1.o : chip/sdd1/sdd1.cpp chip/sdd1/*
obj/dsp1.$(obj) : chip/dsp1/dsp1.cpp chip/dsp1/* obj/spc7110.o: chip/spc7110/spc7110.cpp chip/spc7110/*
obj/dsp2.$(obj) : chip/dsp2/dsp2.cpp chip/dsp2/* obj/cx4.o : chip/cx4/cx4.cpp chip/cx4/*
obj/dsp3.$(obj) : chip/dsp3/dsp3.cpp chip/dsp3/* obj/dsp1.o : chip/dsp1/dsp1.cpp chip/dsp1/*
obj/dsp4.$(obj) : chip/dsp4/dsp4.cpp chip/dsp4/* obj/dsp2.o : chip/dsp2/dsp2.cpp chip/dsp2/*
obj/obc1.$(obj) : chip/obc1/obc1.cpp chip/obc1/* obj/dsp3.o : chip/dsp3/dsp3.cpp chip/dsp3/*
obj/st010.$(obj) : chip/st010/st010.cpp chip/st010/* 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 ### ### zlib ###
############ ############
obj/adler32.$(obj) : reader/zlib/adler32.c reader/zlib/* obj/adler32.o : lib/zlib/adler32.c lib/zlib/*
obj/compress.$(obj): reader/zlib/compress.c reader/zlib/* obj/compress.o: lib/zlib/compress.c lib/zlib/*
obj/crc32.$(obj) : reader/zlib/crc32.c reader/zlib/* obj/crc32.o : lib/zlib/crc32.c lib/zlib/*
obj/deflate.$(obj) : reader/zlib/deflate.c reader/zlib/* obj/deflate.o : lib/zlib/deflate.c lib/zlib/*
obj/gzio.$(obj) : reader/zlib/gzio.c reader/zlib/* obj/gzio.o : lib/zlib/gzio.c lib/zlib/*
obj/inffast.$(obj) : reader/zlib/inffast.c reader/zlib/* obj/inffast.o : lib/zlib/inffast.c lib/zlib/*
obj/inflate.$(obj) : reader/zlib/inflate.c reader/zlib/* obj/inflate.o : lib/zlib/inflate.c lib/zlib/*
obj/inftrees.$(obj): reader/zlib/inftrees.c reader/zlib/* obj/inftrees.o: lib/zlib/inftrees.c lib/zlib/*
obj/ioapi.$(obj) : reader/zlib/ioapi.c reader/zlib/* obj/ioapi.o : lib/zlib/ioapi.c lib/zlib/*
obj/trees.$(obj) : reader/zlib/trees.c reader/zlib/* obj/trees.o : lib/zlib/trees.c lib/zlib/*
obj/unzip.$(obj) : reader/zlib/unzip.c reader/zlib/* obj/unzip.o : lib/zlib/unzip.c lib/zlib/*
obj/zip.$(obj) : reader/zlib/zip.c reader/zlib/* obj/zip.o : lib/zlib/zip.c lib/zlib/*
obj/zutil.$(obj) : reader/zlib/zutil.c reader/zlib/* obj/zutil.o : lib/zlib/zutil.c lib/zlib/*
########### ##############
### jma ### ### libjma ###
########### ##############
obj/jma.$(obj) : reader/jma/jma.cpp reader/jma/* obj/jma.o : lib/libjma/jma.cpp lib/libjma/*
obj/jcrc32.$(obj) : reader/jma/jcrc32.cpp reader/jma/* obj/jcrc32.o : lib/libjma/jcrc32.cpp lib/libjma/*
obj/lzmadec.$(obj): reader/jma/lzmadec.cpp reader/jma/* obj/lzmadec.o: lib/libjma/lzmadec.cpp lib/libjma/*
obj/7zlzma.$(obj) : reader/jma/7zlzma.cpp reader/jma/* obj/7zlzma.o : lib/libjma/7zlzma.cpp lib/libjma/*
obj/iiostrm.$(obj): reader/jma/iiostrm.cpp reader/jma/* obj/iiostrm.o: lib/libjma/iiostrm.cpp lib/libjma/*
obj/inbyte.$(obj) : reader/jma/inbyte.cpp reader/jma/* obj/inbyte.o : lib/libjma/inbyte.cpp lib/libjma/*
obj/lzma.$(obj) : reader/jma/lzma.cpp reader/jma/* obj/lzma.o : lib/libjma/lzma.cpp lib/libjma/*
obj/winout.$(obj) : reader/jma/winout.cpp reader/jma/* obj/winout.o : lib/libjma/winout.cpp lib/libjma/*
############### ###############
### targets ### ### targets ###
############### ###############
build: ui_build $(objects) build: ui_build $(objects)
g++ $(call mkbin,bsnes) $(objects) $(link) $(strip g++ -o bsnes $(objects) $(link))
install: install:
install -D -m 755 ../bsnes $(DESTDIR)$(prefix)/bin/bsnes install -D -m 755 ../bsnes $(DESTDIR)$(prefix)/bin/bsnes
@ -281,7 +236,7 @@ install:
install -D -m 644 data/bsnes.desktop $(DESTDIR)$(prefix)/share/applications/bsnes.desktop install -D -m 644 data/bsnes.desktop $(DESTDIR)$(prefix)/share/applications/bsnes.desktop
clean: ui_clean clean: ui_clean
-@$(call delete,obj/*.$(obj)) -@$(call delete,obj/*.o)
-@$(call delete,*.res) -@$(call delete,*.res)
-@$(call delete,*.pgd) -@$(call delete,*.pgd)
-@$(call delete,*.pgc) -@$(call delete,*.pgc)
@ -300,7 +255,6 @@ help:
@echo " gcc - GCC compiler" @echo " gcc - GCC compiler"
@echo " mingw32-gcc - MinGW compiler" @echo " mingw32-gcc - MinGW compiler"
@echo " i586-mingw32-gcc - MinGW cross compiler" @echo " i586-mingw32-gcc - MinGW cross compiler"
@echo " cl - Visual C++"
@echo "" @echo ""
@echo "Available options:" @echo "Available options:"
@echo " enable_gzip=[true|false] - Enable ZIP / GZ support (default=false)" @echo " enable_gzip=[true|false] - Enable ZIP / GZ support (default=false)"
@ -308,3 +262,4 @@ help:
@echo "" @echo ""
@echo "Example: $(MAKE) platform=x compiler=gcc enable_gzip=true" @echo "Example: $(MAKE) platform=x compiler=gcc enable_gzip=true"
@echo "" @echo ""

View File

View File

@ -1,4 +1,4 @@
#define BSNES_VERSION "0.042" #define BSNES_VERSION "0.046"
#define BSNES_TITLE "bsnes v" BSNES_VERSION #define BSNES_TITLE "bsnes v" BSNES_VERSION
#define BUSCORE sBus #define BUSCORE sBus
@ -9,12 +9,7 @@
//S-DSP can be encapsulated into a state machine using #define magic //S-DSP can be encapsulated into a state machine using #define magic
//this avoids ~2.048m co_switch() calls per second (~5% speedup) //this avoids ~2.048m co_switch() calls per second (~5% speedup)
#define USE_STATE_MACHINE #define DSP_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
//game genie + pro action replay code support (~2% speed hit) //game genie + pro action replay code support (~2% speed hit)
#define CHEAT_SYSTEM #define CHEAT_SYSTEM
@ -25,8 +20,9 @@
#include <nall/array.hpp> #include <nall/array.hpp>
#include <nall/bit.hpp> #include <nall/bit.hpp>
#include <nall/detect.hpp> #include <nall/detect.hpp>
#include <nall/dl.hpp>
#include <nall/endian.hpp> #include <nall/endian.hpp>
#include <nall/file.hpp> #include <nall/function.hpp>
#include <nall/moduloarray.hpp> #include <nall/moduloarray.hpp>
#include <nall/new.hpp> #include <nall/new.hpp>
#include <nall/platform.hpp> #include <nall/platform.hpp>
@ -40,10 +36,9 @@ using namespace nall;
typedef int8_t int8; typedef int8_t int8;
typedef int16_t int16; typedef int16_t int16;
typedef int32_t int32; typedef int32_t int32;
typedef int64_t int64;
typedef uint8_t uint8; typedef uint8_t uint8;
typedef uint16_t uint16; typedef uint16_t uint16;
typedef uint32_t uint32; typedef uint32_t uint32;
typedef uint64_t uint64;
#include "interface.hpp" #include "interface.hpp"

View File

@ -1,234 +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_file.cpp"
#include "cart_header.cpp"
#include "cart_loader.cpp"
namespace memory {
MappedRAM cartrom, cartram, cartrtc;
MappedRAM bscram;
MappedRAM stArom, stAram;
MappedRAM stBrom, stBram;
};
Cartridge cartridge;
void Cartridge::load_begin(Mode cartridge_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;
set(loaded, false);
set(bsx_flash_loaded, false);
set(patched, false);
set(mode, cartridge_mode);
}
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);
string cheat_file = get_filename(cart.filename, "cht", snes.config.path.cheat);
if(file::exists(cheat_file)) {
cheat.clear();
cheat.load(cheat_file);
}
bus.load_cart();
set(loaded, true);
}
void Cartridge::unload() {
if(loaded() == false) return;
bus.unload_cart();
switch(mode()) {
case ModeNormal: unload_normal(); break;
case ModeBsxSlotted: unload_bsx_slotted(); break;
case ModeBsx: unload_bsx(); break;
case ModeSufamiTurbo: unload_sufami_turbo(); 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; }
string cheat_file = get_filename(cart.filename, "cht", snes.config.path.cheat);
if(cheat.count() > 0 || file::exists(cheat_file)) {
cheat.save(cheat_file);
cheat.clear();
}
set(loaded, false);
}
Cartridge::Cartridge() {
set(loaded, false);
}
Cartridge::~Cartridge() {
if(loaded() == true) 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();
}
//=======
//utility
//=======
//ensure file path is absolute (eg resolve relative paths)
string Cartridge::filepath(const char *filename, const char *pathname) {
//if no pathname, return filename as-is
string file(filename);
file.replace("\\", "/");
string path = (!pathname || !*pathname) ? (const char*)snes.config.path.current : pathname;
//ensure path ends with trailing '/'
path.replace("\\", "/");
if(!strend(path, "/")) path.append("/");
//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;
part.split("/", file);
return path << part[part.size() - 1];
}
//remove directory information and file extension ("/foo/bar.ext" -> "bar")
string Cartridge::basename(const char *filename) {
string name(filename);
//remove extension
for(signed i = strlen(name) - 1; i >= 0; i--) {
if(name[i] == '.') {
name[i] = 0;
break;
}
}
//remove directory information
for(signed i = strlen(name) - 1; i >= 0; i--) {
if(name[i] == '/' || name[i] == '\\') {
i++;
char *output = name();
while(true) {
*output++ = name[i];
if(!name[i]) break;
i++;
}
break;
}
}
return name;
}
//remove filename and return path only ("/foo/bar.ext" -> "/foo/bar/")
string Cartridge::basepath(const char *filename) {
string path(filename);
path.replace("\\", "/");
//remove filename
for(signed i = strlen(path) - 1; i >= 0; i--) {
if(path[i] == '/') {
path[i] = 0;
break;
}
}
if(!strend(path, "/")) path.append("/");
return path;
}

View File

@ -1,178 +0,0 @@
class Cartridge : public property {
public:
enum Mode {
ModeNormal,
ModeBsxSlotted,
ModeBsx,
ModeSufamiTurbo,
};
enum Type {
TypeNormal,
TypeBsxSlotted,
TypeBsxBios,
TypeBsx,
TypeSufamiTurboBios,
TypeSufamiTurbo,
TypeUnknown,
};
enum Region {
NTSC,
PAL,
};
enum MemoryMapper {
LoROM,
HiROM,
ExLoROM,
ExHiROM,
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<bool> bsx_flash_loaded; //is a BS-X flash cart connected?
property_t<bool> patched; //has a UPS patch been applied?
property_t<string> name; //display name (filename sans path and extension)
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
bool load_normal (const char *base);
bool load_bsx_slotted (const char *base, const char *slot = "");
bool load_bsx (const char *base, const char *slot = "");
bool load_sufami_turbo(const char *base, const char *slotA = "", const char *slotB = "");
void unload();
//utility functions
static string filepath(const char *filename, const char *pathname); //"./bar.ext" -> "/foo/bar.ext"
static string basename(const char *filename); //"/foo/bar.ext" -> "bar"
static string basepath(const char *filename); //"/foo/bar.ext" -> "/foo/bar/"
//this function will load 'filename', decompress it if needed, and determine what type of
//image file 'filename' refers to (eg normal cart, BS-X flash cart, Sufami Turbo cart, etc.)
//warning: this operation is very expensive, use sparingly!
Type detect_image_type(const char *filename) const;
Cartridge();
~Cartridge();
private:
void load_begin(Mode);
void load_end();
void unload_normal();
void unload_bsx_slotted();
void unload_bsx();
void unload_sufami_turbo();
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&);
bool load_image(const char *filename, uint8_t *&data, unsigned &size, bool &patched) const;
bool load_ram (const char *filename, uint8_t *&data, unsigned size, uint8_t init_value) const;
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) const;
bool save_file(const char *fn, uint8 *data, unsigned size) const;
bool apply_patch(const uint8_t *pdata, unsigned psize, uint8_t *&data, unsigned &size) const;
string modify_extension(const char *filename, const char *extension) const;
string get_filename(const char *source, const char *extension, const char *path) const;
struct {
string filename;
uint8_t *rom, *ram, *rtc;
unsigned rom_size, ram_size, rtc_size;
} cart;
struct {
string filename;
uint8_t *ram;
unsigned ram_size;
} bs;
struct {
string filename;
uint8_t *rom, *ram;
unsigned rom_size, ram_size;
} stA, stB;
};
namespace memory {
extern MappedRAM cartrom, cartram, cartrtc;
extern MappedRAM bscram;
extern MappedRAM stArom, stAram;
extern MappedRAM stBrom, stBram;
};
extern Cartridge cartridge;

View File

@ -1,109 +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
string Cartridge::modify_extension(const char *filename_, const char *extension) const {
string filename = filename_;
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;
return filename << "." << extension;
}
string Cartridge::get_filename(const char *source, const char *extension, const char *path) const {
return filepath(modify_extension(source, extension), path);
}
bool Cartridge::load_file(const char *fn, uint8 *&data, unsigned &size, CompressionMode compression) const {
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) const {
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) const {
file fp;
if(!fp.open(fn, file::mode_write)) return false;
fp.write(data, size);
fp.close();
return true;
}
#endif

View File

@ -1,272 +0,0 @@
#ifdef CART_CPP
void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size) const {
info.reset();
unsigned index = find_header(data, size);
//=======================
//detect BS-X flash carts
//=======================
if(data[index + 0x13] == 0x00 || data[index + 0x13] == 0xff) {
if(data[index + 0x14] == 0x00) {
const uint8_t n15 = data[index + 0x15];
if(n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc) {
if(data[index + 0x1a] == 0x33 || data[index + 0x1a] == 0xff) {
info.type = TypeBsx;
info.mapper = BSXROM;
info.region = NTSC; //BS-X only released in Japan
return;
}
}
}
}
//=========================
//detect Sufami Turbo carts
//=========================
if(!memcmp(data, "BANDAI SFC-ADX", 14)) {
if(!memcmp(data + 16, "SFC-ADX BACKUP", 14)) {
info.type = TypeSufamiTurboBios;
} else {
info.type = TypeSufamiTurbo;
}
info.mapper = STROM;
info.region = NTSC; //Sufami Turbo only released in Japan
return; //RAM size handled internally by load_cart_st();
}
//=====================
//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.bsx_slot = true;
}
}
}
}
if(info.bsx_slot == true) {
if(!memcmp(data + index, "Satellaview BS-X ", 21)) {
//BS-X base cart
info.type = TypeBsxBios;
info.mapper = BSXROM;
info.region = NTSC; //BS-X only released in Japan
return; //RAM size handled internally by load_cart_bsx() -> BSXCart class
} else {
info.type = TypeBsxSlotted;
info.mapper = (index == 0x7fc0 ? BSCLoROM : BSCHiROM);
}
} else {
//standard cart
info.type = TypeNormal;
if(index == 0x7fc0 && size >= 0x401000) {
info.mapper = ExLoROM;
} else if(index == 0x7fc0 && mapper == 0x32) {
info.mapper = ExLoROM;
} else if(index == 0x7fc0) {
info.mapper = LoROM;
} else if(index == 0xffc0) {
info.mapper = HiROM;
} else { //index == 0x40ffc0
info.mapper = ExHiROM;
}
}
if(mapper == 0x20 && (rom_type == 0x13 || rom_type == 0x14 || rom_type == 0x15 || rom_type == 0x1a)) {
info.superfx = true;
}
if(mapper == 0x23 && (rom_type == 0x34 || rom_type == 0x35)) {
info.sa1 = true;
}
if(mapper == 0x35 && rom_type == 0x55) {
info.srtc = true;
}
if(mapper == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
info.sdd1 = true;
}
if(mapper == 0x3a && (rom_type == 0xf5 || rom_type == 0xf9)) {
info.spc7110 = true;
info.spc7110rtc = (rom_type == 0xf9);
info.mapper = SPC7110ROM;
}
if(mapper == 0x20 && rom_type == 0xf3) {
info.cx4 = true;
}
if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) {
info.dsp1 = true;
}
if(mapper == 0x30 && rom_type == 0x05 && company != 0xb2) {
info.dsp1 = true;
}
if(mapper == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) {
info.dsp1 = true;
}
if(info.dsp1 == true) {
if((mapper & 0x2f) == 0x20 && size <= 0x100000) {
info.dsp1_mapper = DSP1LoROM1MB;
} else if((mapper & 0x2f) == 0x20) {
info.dsp1_mapper = DSP1LoROM2MB;
} else if((mapper & 0x2f) == 0x21) {
info.dsp1_mapper = DSP1HiROM;
}
}
if(mapper == 0x20 && rom_type == 0x05) {
info.dsp2 = true;
}
if(mapper == 0x30 && rom_type == 0x05 && company == 0xb2) {
info.dsp3 = true;
}
if(mapper == 0x30 && rom_type == 0x03) {
info.dsp4 = true;
}
if(mapper == 0x30 && rom_type == 0x25) {
info.obc1 = true;
}
if(mapper == 0x30 && rom_type == 0xf6 && rom_size >= 10) {
info.st010 = true;
}
if(mapper == 0x30 && rom_type == 0xf6 && rom_size < 10) {
info.st011 = true;
}
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) 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);
if(score_ex) score_ex += 4; //favor ExHiROM on images > 32mbits
if(score_lo >= score_hi && score_lo >= score_ex) {
return 0x007fc0;
} else if(score_hi >= score_ex) {
return 0x00ffc0;
} else {
return 0x40ffc0;
}
}
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;
uint16 resetvector = data[addr + ResetVector] | (data[addr + ResetVector + 1] << 8);
uint16 checksum = data[addr + Checksum ] | (data[addr + Checksum + 1] << 8);
uint16 complement = data[addr + Complement ] | (data[addr + Complement + 1] << 8);
uint8 resetop = data[(addr & ~0x7fff) | (resetvector & 0x7fff)]; //first opcode executed upon reset
uint8 mapper = data[addr + Mapper] & ~0x10; //mask off irrelevent FastROM-capable bit
//$00:[000-7fff] contains uninitialized RAM and MMIO.
//reset vector must point to ROM at $00:[8000-ffff] to be considered valid.
if(resetvector < 0x8000) return 0;
//some images duplicate the header in multiple locations, and others have completely
//invalid header information that cannot be relied upon.
//below code will analyze the first opcode executed at the specified reset vector to
//determine the probability that this is the correct header.
//most likely opcodes
if(resetop == 0x78 //sei
|| resetop == 0x18 //clc (clc; xce)
|| resetop == 0x38 //sec (sec; xce)
|| resetop == 0x9c //stz $nnnn (stz $4200)
|| resetop == 0x4c //jmp $nnnn
|| resetop == 0x5c //jml $nnnnnn
) score += 8;
//plausible opcodes
if(resetop == 0xc2 //rep #$nn
|| resetop == 0xe2 //sep #$nn
|| resetop == 0xad //lda $nnnn
|| resetop == 0xae //ldx $nnnn
|| resetop == 0xac //ldy $nnnn
|| resetop == 0xaf //lda $nnnnnn
|| resetop == 0xa9 //lda #$nn
|| resetop == 0xa2 //ldx #$nn
|| resetop == 0xa0 //ldy #$nn
|| resetop == 0x20 //jsr $nnnn
|| resetop == 0x22 //jsl $nnnnnn
) score += 4;
//implausible opcodes
if(resetop == 0x40 //rti
|| resetop == 0x60 //rts
|| resetop == 0x6b //rtl
|| resetop == 0xcd //cmp $nnnn
|| resetop == 0xec //cpx $nnnn
|| resetop == 0xcc //cpy $nnnn
) score -= 4;
//least likely opcodes
if(resetop == 0x00 //brk #$nn
|| resetop == 0x02 //cop #$nn
|| resetop == 0xdb //stp
|| resetop == 0x42 //wdm
|| resetop == 0xff //sbc $nnnnnn,x
) score -= 8;
//at times, both the header and reset vector's first opcode will match ...
//fallback and rely on info validity in these cases to determine more likely header.
//a valid checksum is the biggest indicator of a valid header.
if((checksum + complement) == 0xffff && (checksum != 0) && (complement != 0)) score += 4;
if(addr == 0x007fc0 && mapper == 0x20) score += 2; //0x20 is usually LoROM
if(addr == 0x00ffc0 && mapper == 0x21) score += 2; //0x21 is usually HiROM
if(addr == 0x007fc0 && mapper == 0x22) score += 2; //0x22 is usually ExLoROM
if(addr == 0x40ffc0 && mapper == 0x25) score += 2; //0x25 is usually ExHiROM
if(data[addr + Company] == 0x33) score += 2; //0x33 indicates extended header
if(data[addr + RomType] < 0x08) score++;
if(data[addr + RomSize] < 0x10) score++;
if(data[addr + RamSize] < 0x08) score++;
if(data[addr + CartRegion] < 14) score++;
if(score < 0) score = 0;
return score;
}
#endif

View File

@ -1,244 +0,0 @@
#ifdef CART_CPP
//================
//Normal cartridge
//================
bool Cartridge::load_normal(const char *base) {
uint8_t *data;
unsigned size;
bool patch_applied;
cart.filename = base;
load_begin(ModeNormal);
if(load_image(base, data, size, patch_applied) == false) return false;
snes.config.path.current = basepath(cart.filename);
if(patch_applied) set(patched, true);
cartinfo_t cartinfo;
read_header(cartinfo, cart.rom = data, cart.rom_size = size);
set_cartinfo(cartinfo);
if(cartinfo.ram_size > 0) {
load_ram(get_filename(base, "srm", snes.config.path.save), cart.ram, cart.ram_size = cartinfo.ram_size, 0xff);
}
if(cartinfo.srtc || cartinfo.spc7110rtc) {
load_ram(get_filename(base, "rtc", snes.config.path.save), cart.rtc, cart.rtc_size = 20, 0x00);
}
load_end();
set(name, basename(base));
return true;
}
void Cartridge::unload_normal() {
if(cart.ram) save_file(get_filename(cart.filename, "srm", snes.config.path.save), cart.ram, cart.ram_size);
if(cart.rtc) save_file(get_filename(cart.filename, "rtc", snes.config.path.save), cart.rtc, cart.rtc_size);
}
//======================
//BS-X slotted cartridge
//======================
bool Cartridge::load_bsx_slotted(const char *base, const char *slot) {
uint8_t *data;
unsigned size;
bool patch_applied;
cart.filename = base;
bs.filename = slot;
load_begin(ModeBsxSlotted);
if(load_image(base, data, size, patch_applied) == false) return false;
snes.config.path.current = basepath(cart.filename);
if(patch_applied) set(patched, true);
cartinfo_t cartinfo;
read_header(cartinfo, cart.rom = data, cart.rom_size = size);
set_cartinfo(cartinfo);
if(load_image(slot, data, size, patch_applied) == true) {
set(bsx_flash_loaded, true);
if(patch_applied) set(patched, true);
bs.ram = data;
bs.ram_size = size;
}
if(cartinfo.ram_size > 0) {
load_ram(get_filename(base, "srm", snes.config.path.save), cart.ram, cart.ram_size = cartinfo.ram_size, 0xff);
}
load_end();
string filename = basename(base);
if(*slot) filename << " + " << basename(slot);
set(name, filename);
return true;
}
void Cartridge::unload_bsx_slotted() {
if(cart.ram) save_file(get_filename(cart.filename, "srm", snes.config.path.save), cart.ram, cart.ram_size);
}
//====================
//BS-X flash cartridge
//====================
bool Cartridge::load_bsx(const char *base, const char *slot) {
uint8_t *data;
unsigned size;
bool patch_applied;
cart.filename = base;
bs.filename = slot;
load_begin(ModeBsx);
if(load_image(base, data, size, patch_applied) == false) return false;
snes.config.path.current = basepath(cart.filename);
if(patch_applied) set(patched, true);
cartinfo_t cartinfo;
read_header(cartinfo, cart.rom = data, cart.rom_size = size);
set_cartinfo(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_filename(base, "srm", snes.config.path.save), data, size, CompressionNone) == true) {
memcpy(bsxcart.sram.handle (), data, min(bsxcart.sram.size (), size));
delete[] data;
}
if(load_file(get_filename(base, "psr", snes.config.path.save), data, size, CompressionNone) == true) {
memcpy(bsxcart.psram.handle(), data, min(bsxcart.psram.size(), size));
delete[] data;
}
if(load_image(slot, data, size, patch_applied) == true) {
set(bsx_flash_loaded, true);
if(patch_applied) set(patched, true);
bs.ram = data;
bs.ram_size = size;
}
load_end();
set(name, !*slot ? basename(base) : basename(slot));
return true;
}
void Cartridge::unload_bsx() {
save_file(get_filename(cart.filename, "srm", snes.config.path.save), bsxcart.sram.handle (), bsxcart.sram.size ());
save_file(get_filename(cart.filename, "psr", snes.config.path.save), bsxcart.psram.handle(), bsxcart.psram.size());
}
//============================
//Sufami Turbo flash cartridge
//============================
bool Cartridge::load_sufami_turbo(const char *base, const char *slotA, const char *slotB) {
uint8_t *data;
unsigned size;
bool patch_applied;
cart.filename = base;
stA.filename = slotA;
stB.filename = slotB;
load_begin(ModeSufamiTurbo);
if(load_image(base, data, size, patch_applied) == false) return false;
snes.config.path.current = basepath(cart.filename);
if(patch_applied) set(patched, true);
cartinfo_t cartinfo;
read_header(cartinfo, cart.rom = data, cart.rom_size = size);
set_cartinfo(cartinfo);
if(load_image(slotA, data, size, patch_applied) == true) {
if(patch_applied) set(patched, true);
stA.rom = new(zeromemory) uint8_t[stA.rom_size = 0x100000];
memcpy(stA.rom, data, min(size, stA.rom_size));
delete[] data;
load_ram(get_filename(slotA, "srm", snes.config.path.save), stA.ram, stA.ram_size = 0x020000, 0xff);
}
if(load_image(slotB, data, size, patch_applied) == true) {
if(patch_applied) set(patched, true);
stB.rom = new(zeromemory) uint8_t[stB.rom_size = 0x100000];
memcpy(stB.rom, data, min(size, stB.rom_size));
delete[] data;
load_ram(get_filename(slotB, "srm", snes.config.path.save), stB.ram, stB.ram_size = 0x020000, 0xff);
}
load_end();
string filename;
if(!*slotA && !*slotB) filename << basename(base);
else if( *slotA && !*slotB) filename << basename(slotA);
else if(!*slotA && *slotB) filename << basename(slotB);
else filename << basename(slotA) << " + " << basename(slotB);
set(name, filename);
return true;
}
void Cartridge::unload_sufami_turbo() {
if(stA.ram) save_file(get_filename(stA.filename, "srm", snes.config.path.save), stA.ram, stA.ram_size);
if(stB.ram) save_file(get_filename(stB.filename, "srm", snes.config.path.save), stB.ram, stB.ram_size);
}
//=================
//utility functions
//=================
Cartridge::Type Cartridge::detect_image_type(const char *filename) const {
uint8_t *data;
unsigned size;
bool patch_applied;
if(!load_image(filename, data, size, patch_applied)) return TypeUnknown;
cartinfo_t info;
read_header(info, data, size);
delete[] data;
return info.type;
}
bool Cartridge::load_image(const char *filename, uint8_t *&data, unsigned &size, bool &patched) const {
if(!filename || !*filename) return false;
if(!load_file(filename, data, size, CompressionAuto)) return false;
if((size & 0x7fff) == 512) {
//remove 512-byte header
memmove(data, data + 512, size -= 512);
}
uint8_t *pdata;
unsigned psize;
if(load_file(get_filename(filename, "ups", snes.config.path.patch), pdata, psize, CompressionInspect) == true) {
apply_patch(pdata, psize, data, size);
delete[] pdata;
patched = true;
} else {
patched = false;
}
return true;
}
bool Cartridge::load_ram(const char *filename, uint8_t *&data, unsigned size, uint8_t init) const {
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

View File

@ -1,3 +1,3 @@
::@mingw32-make platform=win compiler=mingw32-gcc @mingw32-make
@mingw32-make platform=win compiler=mingw32-gcc enable_gzip=true enable_jma=true ::@mingw32-make enable_gzip=true enable_jma=true
@pause @pause

View File

@ -1,2 +0,0 @@
make platform=x compiler=gcc
#make platform=x compiler=gcc enable_gzip=true enable_jma=true

View File

@ -1,5 +1,8 @@
#include <../base.hpp> #include <../base.hpp>
#define CHEAT_CPP
namespace SNES {
Cheat cheat; Cheat cheat;
Cheat::cheat_t& Cheat::cheat_t::operator=(const Cheat::cheat_t& source) { Cheat::cheat_t& Cheat::cheat_t::operator=(const Cheat::cheat_t& source) {
@ -178,9 +181,7 @@ void Cheat::disable(unsigned i) {
//... //...
//=============================== //===============================
bool Cheat::load(const char *fn) { void Cheat::load(string data) {
string data;
if(!data.readfile(fn)) return false;
data.replace("\r\n", "\n"); data.replace("\r\n", "\n");
data.qreplace(" ", ""); data.qreplace(" ", "");
@ -193,21 +194,16 @@ bool Cheat::load(const char *fn) {
trim(part[0], "\""); trim(part[0], "\"");
add(part[1] == "enabled", /* code = */ part[2], /* desc = */ part[0]); add(part[1] == "enabled", /* code = */ part[2], /* desc = */ part[0]);
} }
return true;
} }
bool Cheat::save(const char *fn) const { string Cheat::save() const {
file fp; string data;
if(!fp.open(fn, file::mode_write)) return false;
for(unsigned i = 0; i < code.size(); i++) { for(unsigned i = 0; i < code.size(); i++) {
fp.print(string() data << "\"" << code[i].desc << "\", "
<< "\"" << code[i].desc << "\", " << (code[i].enabled ? "enabled, " : "disabled, ")
<< (code[i].enabled ? "enabled, " : "disabled, ") << code[i].code << "\r\n";
<< code[i].code << "\r\n");
} }
fp.close(); return data;
return true;
} }
void Cheat::clear() { void Cheat::clear() {
@ -390,3 +386,6 @@ string& Cheat::decode_description(string &desc) const {
desc.replace("\\n", "\n"); desc.replace("\\n", "\n");
return desc; return desc;
} }
};

View File

@ -38,8 +38,8 @@ public:
void enable(unsigned i); void enable(unsigned i);
void disable(unsigned i); void disable(unsigned i);
bool load(const char *fn); void load(string data);
bool save(const char *fn) const; string save() const;
void clear(); void clear();
Cheat(); Cheat();

View File

@ -1,8 +1,10 @@
#include <../base.hpp> #include <../base.hpp>
#include <../cart/cart.hpp>
#define BSX_CPP
#include "bsx.hpp" #define BSX_CPP
namespace SNES {
#include "bsx_base.cpp" #include "bsx_base.cpp"
#include "bsx_cart.cpp" #include "bsx_cart.cpp"
#include "bsx_flash.cpp" #include "bsx_flash.cpp"
};

View File

@ -32,16 +32,10 @@ public:
uint8 mmio_read(unsigned addr); uint8 mmio_read(unsigned addr);
void mmio_write(unsigned addr, uint8 data); void mmio_write(unsigned addr, uint8 data);
MappedRAM sram;
MappedRAM psram;
BSXCart(); BSXCart();
~BSXCart(); ~BSXCart();
private: private:
uint8 *sram_data; //256kbit SRAM
uint8 *psram_data; // 4mbit PSRAM
struct { struct {
uint8 r[16]; uint8 r[16];
} regs; } regs;

View File

@ -1,5 +1,7 @@
#ifdef BSX_CPP #ifdef BSX_CPP
BSXBase bsxbase;
void BSXBase::init() { void BSXBase::init() {
} }
@ -135,3 +137,4 @@ void BSXBase::mmio_write(unsigned addr, uint8 data) {
} }
#endif #endif

View File

@ -1,5 +1,7 @@
#ifdef BSX_CPP #ifdef BSX_CPP
BSXCart bsxcart;
void BSXCart::init() { void BSXCart::init() {
} }
@ -20,7 +22,7 @@ void BSXCart::reset() {
} }
void BSXCart::update_memory_map() { 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) { if((regs.r[0x02] & 0x80) == 0x00) {
//LoROM mapping //LoROM mapping
@ -35,16 +37,16 @@ void BSXCart::update_memory_map() {
} }
if(regs.r[0x03] & 0x80) { if(regs.r[0x03] & 0x80) {
bus.map(Bus::MapLinear, 0x60, 0x6f, 0x0000, 0xffff, psram); bus.map(Bus::MapLinear, 0x60, 0x6f, 0x0000, 0xffff, memory::bsxpram);
//bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, psram); //bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, memory::bsxpram);
} }
if((regs.r[0x05] & 0x80) == 0x00) { 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) { 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) { if(regs.r[0x07] & 0x80) {
@ -55,8 +57,8 @@ void BSXCart::update_memory_map() {
bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom); bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom);
} }
bus.map(Bus::MapShadow, 0x20, 0x3f, 0x6000, 0x7fff, psram); bus.map(Bus::MapShadow, 0x20, 0x3f, 0x6000, 0x7fff, memory::bsxpram);
bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, psram); bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, memory::bsxpram);
} }
uint8 BSXCart::mmio_read(unsigned addr) { uint8 BSXCart::mmio_read(unsigned addr) {
@ -66,7 +68,7 @@ uint8 BSXCart::mmio_read(unsigned addr) {
} }
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM 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; return 0x00;
@ -81,21 +83,15 @@ void BSXCart::mmio_write(unsigned addr, uint8 data) {
} }
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM 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() { 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() { BSXCart::~BSXCart() {
delete[] sram_data;
delete[] psram_data;
} }
#endif #endif

View File

@ -1,5 +1,7 @@
#ifdef BSX_CPP #ifdef BSX_CPP
BSXFlash bsxflash;
void BSXFlash::init() {} void BSXFlash::init() {}
void BSXFlash::enable() {} void BSXFlash::enable() {}
@ -15,10 +17,11 @@ void BSXFlash::reset() {
regs.flash_enable = false; regs.flash_enable = false;
regs.read_enable = false; regs.read_enable = false;
regs.write_enable = false; regs.write_enable = false;
memory::bsxflash.write_protect(!regs.write_enable);
} }
unsigned BSXFlash::size() const { unsigned BSXFlash::size() const {
return memory::bscram.size(); return memory::bsxflash.size();
} }
uint8 BSXFlash::read(unsigned addr) { uint8 BSXFlash::read(unsigned addr) {
@ -45,7 +48,7 @@ uint8 BSXFlash::read(unsigned addr) {
} }
} }
return memory::bscram.read(addr); return memory::bsxflash.read(addr);
} }
void BSXFlash::write(unsigned addr, uint8 data) { void BSXFlash::write(unsigned addr, uint8 data) {
@ -64,11 +67,11 @@ void BSXFlash::write(unsigned addr, uint8 data) {
regs.write_new = data; regs.write_new = data;
if(regs.write_enable && regs.write_old == regs.write_new) { if(regs.write_enable && regs.write_old == regs.write_new) {
return memory::bscram.write(addr, data); return memory::bsxflash.write(addr, data);
} }
} else { } else {
if(regs.write_enable) { 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.read_enable = false;
regs.write_enable = false; regs.write_enable = false;
} }
memory::bsxflash.write_protect(!regs.write_enable);
} }
} }
#endif #endif

View File

@ -1,3 +1,5 @@
#include "sgb/sgb.hpp"
#include "sa1/sa1.hpp"
#include "bsx/bsx.hpp" #include "bsx/bsx.hpp"
#include "srtc/srtc.hpp" #include "srtc/srtc.hpp"
#include "sdd1/sdd1.hpp" #include "sdd1/sdd1.hpp"

View File

@ -6,9 +6,12 @@
*/ */
#include <../base.hpp> #include <../base.hpp>
#define CX4_CPP
#include "cx4.hpp" #define CX4_CPP
namespace SNES {
Cx4 cx4;
#include "cx4data.cpp" #include "cx4data.cpp"
#include "cx4fn.cpp" #include "cx4fn.cpp"
#include "cx4oam.cpp" #include "cx4oam.cpp"
@ -30,8 +33,8 @@ uint16 addr = 0x0080 + (r * 3);
} }
void Cx4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) { void Cx4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) {
int64 rx = x & 0xffffff; int64_t rx = x & 0xffffff;
int64 ry = y & 0xffffff; int64_t ry = y & 0xffffff;
if(rx & 0x800000)rx |= ~0x7fffff; if(rx & 0x800000)rx |= ~0x7fffff;
if(ry & 0x800000)ry |= ~0x7fffff; if(ry & 0x800000)ry |= ~0x7fffff;
@ -195,3 +198,5 @@ void Cx4::reset() {
memset(ram, 0, 0x0c00); memset(ram, 0, 0x0c00);
memset(reg, 0, 0x0100); memset(reg, 0, 0x0100);
} }
};

View File

@ -1,8 +1,10 @@
#include <../base.hpp> #include <../base.hpp>
#include <../cart/cart.hpp>
#define DSP1_CPP
#include "dsp1.hpp" #define DSP1_CPP
namespace SNES {
DSP1 dsp1;
#include "dsp1emu.cpp" #include "dsp1emu.cpp"
void DSP1::init() {} void DSP1::init() {}
@ -57,3 +59,5 @@ void DSP1::write(unsigned addr, uint8 data) {
dsp1.setDr(data); dsp1.setDr(data);
} }
} }
};

View File

@ -1,7 +1,10 @@
#include <../base.hpp> #include <../base.hpp>
#define DSP2_CPP
#include "dsp2.hpp" #define DSP2_CPP
namespace SNES {
DSP2 dsp2;
#include "dsp2_op.cpp" #include "dsp2_op.cpp"
void DSP2::init() {} void DSP2::init() {}
@ -134,3 +137,5 @@ void DSP2::write(unsigned addr, uint8 data) {
DSP2::DSP2() {} DSP2::DSP2() {}
DSP2::~DSP2() {} DSP2::~DSP2() {}
};

View File

@ -1,7 +1,10 @@
#include <../base.hpp> #include <../base.hpp>
#define DSP3_CPP
#include "dsp3.hpp" #define DSP3_CPP
namespace SNES {
DSP3 dsp3;
namespace DSP3i { namespace DSP3i {
#define bool8 uint8 #define bool8 uint8
#include "dsp3emu.c" #include "dsp3emu.c"
@ -33,3 +36,5 @@ void DSP3::write(unsigned addr, uint8 data) {
DSP3i::dsp3_byte = data; DSP3i::dsp3_byte = data;
DSP3i::DSP3SetByte(); DSP3i::DSP3SetByte();
} }
};

View File

@ -1,7 +1,10 @@
#include <../base.hpp> #include <../base.hpp>
#define DSP4_CPP
#include "dsp4.hpp" #define DSP4_CPP
namespace SNES {
DSP4 dsp4;
namespace DSP4i { namespace DSP4i {
inline uint16 READ_WORD(uint8 *addr) { inline uint16 READ_WORD(uint8 *addr) {
return (addr[0]) + (addr[1] << 8); return (addr[0]) + (addr[1] << 8);
@ -53,3 +56,5 @@ void DSP4::write(unsigned addr, uint8 data) {
DSP4i::DSP4SetByte(); DSP4i::DSP4SetByte();
} }
} }
};

View File

@ -1,6 +1,9 @@
#include <../base.hpp> #include <../base.hpp>
#include <../cart/cart.hpp>
#include "obc1.hpp" #define OBC1_CPP
namespace SNES {
OBC1 obc1;
void OBC1::init() {} void OBC1::init() {}
void OBC1::enable() {} void OBC1::enable() {}
@ -21,7 +24,7 @@ uint8 OBC1::read(unsigned addr) {
addr &= 0x1fff; addr &= 0x1fff;
if((addr & 0x1ff8) != 0x1ff0) return ram_read(addr); if((addr & 0x1ff8) != 0x1ff0) return ram_read(addr);
switch(addr) { default: //never used, avoids compiler warning switch(addr) { default: //never used, avoids compiler warning
case 0x1ff0: return ram_read(status.baseptr + (status.address << 2) + 0); case 0x1ff0: return ram_read(status.baseptr + (status.address << 2) + 0);
case 0x1ff1: return ram_read(status.baseptr + (status.address << 2) + 1); case 0x1ff1: return ram_read(status.baseptr + (status.address << 2) + 1);
case 0x1ff2: return ram_read(status.baseptr + (status.address << 2) + 2); case 0x1ff2: return ram_read(status.baseptr + (status.address << 2) + 2);
@ -70,3 +73,6 @@ void OBC1::ram_write(unsigned addr, uint8 data) {
OBC1::OBC1() {} OBC1::OBC1() {}
OBC1::~OBC1() {} OBC1::~OBC1() {}
};

View File

@ -1,8 +1,10 @@
#include <../base.hpp> #include <../base.hpp>
#include <../cart/cart.hpp>
#define SDD1_CPP
#include "sdd1.hpp" #define SDD1_CPP
namespace SNES {
SDD1 sdd1;
#include "sdd1emu.cpp" #include "sdd1emu.cpp"
void SDD1::init() {} void SDD1::init() {}
@ -11,7 +13,7 @@ void SDD1::enable() {
//hook S-CPU DMA MMIO registers to gather information for struct dma[]; //hook S-CPU DMA MMIO registers to gather information for struct dma[];
//buffer address and transfer size information for use in SDD1::read() //buffer address and transfer size information for use in SDD1::read()
for(unsigned i = 0x4300; i <= 0x437f; i++) { 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); memory::mmio.map(i, *this);
} }
@ -156,3 +158,5 @@ SDD1::SDD1() {
SDD1::~SDD1() { SDD1::~SDD1() {
delete[] buffer.data; delete[] buffer.data;
} }
};

View File

@ -1,8 +1,10 @@
#include <../base.hpp> #include <../base.hpp>
#include <../cart/cart.hpp>
#define SPC7110_CPP
#include "spc7110.hpp" #define SPC7110_CPP
namespace SNES {
SPC7110 spc7110;
#include "decomp.cpp" #include "decomp.cpp"
const unsigned SPC7110::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; const unsigned SPC7110::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
@ -670,3 +672,6 @@ void SPC7110::write(unsigned addr, uint8 data) {
SPC7110::SPC7110() { SPC7110::SPC7110() {
} }
};

View File

@ -1,6 +1,9 @@
#include <../base.hpp> #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 }; 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() { SRTC::SRTC() {
} }
};

View File

@ -1,7 +1,10 @@
#include <../base.hpp> #include <../base.hpp>
#define ST010_CPP
#include "st010.hpp" #define ST010_CPP
namespace SNES {
ST010 st010;
#include "st010_data.hpp" #include "st010_data.hpp"
#include "st010_op.cpp" #include "st010_op.cpp"
@ -85,3 +88,5 @@ void ST010::write(unsigned addr, uint8 data) {
ram[0x0021] &= ~0x80; ram[0x0021] &= ~0x80;
} }
} }
};

View File

@ -1 +1 @@
@mingw32-make platform=win compiler=mingw32-gcc clean @mingw32-make clean

View File

@ -1 +0,0 @@
make platform=x compiler=gcc clean

View File

@ -1,10 +1,10 @@
#include <../base.hpp> #include <../base.hpp>
#define CPU_CPP
#include "dcpu.cpp" #define CPU_CPP
namespace SNES {
void CPU::power() { void CPU::power() {
cpu_version = snes.config.cpu.version; cpu_version = config.cpu.version;
} }
void CPU::reset() { void CPU::reset() {
@ -15,3 +15,5 @@ CPU::CPU() {
CPU::~CPU() { CPU::~CPU() {
} }
};

View File

@ -13,62 +13,10 @@ public:
virtual uint8 port_read(uint8 port) = 0; virtual uint8 port_read(uint8 port) = 0;
virtual void port_write(uint8 port, uint8 value) = 0; virtual void port_write(uint8 port, uint8 value) = 0;
#include "cpuregs.hpp"
regs_t regs;
virtual void scanline() = 0; virtual void scanline() = 0;
virtual void power(); virtual void power();
virtual void reset(); virtual void reset();
/*****
* 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();
CPU(); CPU();
virtual ~CPU(); virtual ~CPU();
}; };

View File

@ -1,74 +0,0 @@
struct flag_t {
bool n, v, m, x, d, i, z, c;
inline operator unsigned() const {
return (n << 7) + (v << 6) + (m << 5) + (x << 4)
+ (d << 3) + (i << 2) + (z << 1) + (c << 0);
}
inline unsigned operator=(uint8_t data) {
n = data & 0x80; v = data & 0x40; m = data & 0x20; x = data & 0x10;
d = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01;
return data;
}
inline unsigned operator|=(unsigned data) { return operator=(operator unsigned() | data); }
inline unsigned operator^=(unsigned data) { return operator=(operator unsigned() ^ data); }
inline unsigned operator&=(unsigned data) { return operator=(operator unsigned() & data); }
flag_t() : n(0), v(0), m(0), x(0), d(0), i(0), z(0), c(0) {}
};
struct reg16_t {
union {
uint16 w;
struct { uint8 order_lsb2(l, h); };
};
inline operator unsigned() const { return w; }
inline unsigned operator = (unsigned i) { return w = i; }
inline unsigned operator |= (unsigned i) { return w |= i; }
inline unsigned operator ^= (unsigned i) { return w ^= i; }
inline unsigned operator &= (unsigned i) { return w &= i; }
inline unsigned operator <<= (unsigned i) { return w <<= i; }
inline unsigned operator >>= (unsigned i) { return w >>= i; }
inline unsigned operator += (unsigned i) { return w += i; }
inline unsigned operator -= (unsigned i) { return w -= i; }
inline unsigned operator *= (unsigned i) { return w *= i; }
inline unsigned operator /= (unsigned i) { return w /= i; }
inline unsigned operator %= (unsigned i) { return w %= i; }
reg16_t() : w(0) {}
};
struct reg24_t {
union {
uint32 d;
struct { uint16 order_lsb2(w, wh); };
struct { uint8 order_lsb4(l, h, b, bh); };
};
inline operator unsigned() const { return d; }
inline unsigned operator = (unsigned i) { return d = uclip<24>(i); }
inline unsigned operator |= (unsigned i) { return d = uclip<24>(d | i); }
inline unsigned operator ^= (unsigned i) { return d = uclip<24>(d ^ i); }
inline unsigned operator &= (unsigned i) { return d = uclip<24>(d & i); }
inline unsigned operator <<= (unsigned i) { return d = uclip<24>(d << i); }
inline unsigned operator >>= (unsigned i) { return d = uclip<24>(d >> i); }
inline unsigned operator += (unsigned i) { return d = uclip<24>(d + i); }
inline unsigned operator -= (unsigned i) { return d = uclip<24>(d - i); }
inline unsigned operator *= (unsigned i) { return d = uclip<24>(d * i); }
inline unsigned operator /= (unsigned i) { return d = uclip<24>(d / i); }
inline unsigned operator %= (unsigned i) { return d = uclip<24>(d % i); }
reg24_t() : d(0) {}
};
struct regs_t {
reg24_t pc;
reg16_t a, x, y, s, d;
flag_t p;
uint8_t db, mdr;
bool e;
regs_t() : db(0), mdr(0), e(false) {}
};

View File

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

View File

@ -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

View File

@ -1 +0,0 @@
rm scpugen

View File

@ -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

View File

@ -1,54 +0,0 @@
reg24_t aa, rd;
uint8_t dp, sp;
void op_irq();
inline bool in_opcode() { return status.in_opcode; }
//op_read
void op_adc_b();
void op_adc_w();
void op_and_b();
void op_and_w();
void op_bit_b();
void op_bit_w();
void op_cmp_b();
void op_cmp_w();
void op_cpx_b();
void op_cpx_w();
void op_cpy_b();
void op_cpy_w();
void op_eor_b();
void op_eor_w();
void op_lda_b();
void op_lda_w();
void op_ldx_b();
void op_ldx_w();
void op_ldy_b();
void op_ldy_w();
void op_ora_b();
void op_ora_w();
void op_sbc_b();
void op_sbc_w();
//op_rmw
void op_inc_b();
void op_inc_w();
void op_dec_b();
void op_dec_w();
void op_asl_b();
void op_asl_w();
void op_lsr_b();
void op_lsr_w();
void op_rol_b();
void op_rol_w();
void op_ror_b();
void op_ror_w();
void op_trb_b();
void op_trb_w();
void op_tsb_b();
void op_tsb_w();
void op_io_irq();
void op_io_cond2();
void op_io_cond4(uint16 x, uint16 y);
void op_io_cond6(uint16 addr);

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -1,371 +0,0 @@
#ifdef SCPU_CPP
//op_read
inline void sCPU::op_adc_b() {
int r;
if(regs.p.d) {
uint8 n0 = (regs.a.l ) & 15;
uint8 n1 = (regs.a.l >> 4) & 15;
n0 += (rd.l & 15) + regs.p.c;
if(n0 > 9) {
n0 = (n0 - 10) & 15;
n1++;
}
n1 += ((rd.l >> 4) & 15);
if(n1 > 9) {
n1 = (n1 - 10) & 15;
regs.p.c = 1;
} else {
regs.p.c = 0;
}
r = (n1 << 4) | n0;
} else {
r = regs.a.l + rd.l + regs.p.c;
regs.p.c = r > 0xff;
}
regs.p.n = r & 0x80;
regs.p.v = ~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80;
regs.p.z = (uint8)r == 0;
regs.a.l = r;
}
inline void sCPU::op_adc_w() {
int r;
if(regs.p.d) {
uint8 n0 = (regs.a.w ) & 15;
uint8 n1 = (regs.a.w >> 4) & 15;
uint8 n2 = (regs.a.w >> 8) & 15;
uint8 n3 = (regs.a.w >> 12) & 15;
n0 += (rd.w & 15) + regs.p.c;
if(n0 > 9) {
n0 = (n0 - 10) & 15;
n1++;
}
n1 += ((rd.w >> 4) & 15);
if(n1 > 9) {
n1 = (n1 - 10) & 15;
n2++;
}
n2 += ((rd.w >> 8) & 15);
if(n2 > 9) {
n2 = (n2 - 10) & 15;
n3++;
}
n3 += ((rd.w >> 12) & 15);
if(n3 > 9) {
n3 = (n3 - 10) & 15;
regs.p.c = 1;
} else {
regs.p.c = 0;
}
r = (n3 << 12) | (n2 << 8) | (n1 << 4) | n0;
} else {
r = regs.a.w + rd.w + regs.p.c;
regs.p.c = r > 0xffff;
}
regs.p.n = r & 0x8000;
regs.p.v = ~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000;
regs.p.z = (uint16)r == 0;
regs.a.w = r;
}
inline void sCPU::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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
int r;
if(regs.p.d) {
uint8 n0 = (regs.a.l ) & 15;
uint8 n1 = (regs.a.l >> 4) & 15;
n0 -= ((rd.l ) & 15) + !regs.p.c;
n1 -= ((rd.l >> 4) & 15);
if(n0 > 9) {
n0 += 10;
n1--;
}
if(n1 > 9) {
n1 += 10;
regs.p.c = 0;
} else {
regs.p.c = 1;
}
r = (n1 << 4) | (n0);
} else {
r = regs.a.l - rd.l - !regs.p.c;
regs.p.c = r >= 0;
}
regs.p.n = r & 0x80;
regs.p.v = (regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80;
regs.p.z = (uint8)r == 0;
regs.a.l = r;
}
inline void sCPU::op_sbc_w() {
int r;
if(regs.p.d) {
uint8 n0 = (regs.a.w ) & 15;
uint8 n1 = (regs.a.w >> 4) & 15;
uint8 n2 = (regs.a.w >> 8) & 15;
uint8 n3 = (regs.a.w >> 12) & 15;
n0 -= ((rd.w ) & 15) + !regs.p.c;
n1 -= ((rd.w >> 4) & 15);
n2 -= ((rd.w >> 8) & 15);
n3 -= ((rd.w >> 12) & 15);
if(n0 > 9) {
n0 += 10;
n1--;
}
if(n1 > 9) {
n1 += 10;
n2--;
}
if(n2 > 9) {
n2 += 10;
n3--;
}
if(n3 > 9) {
n3 += 10;
regs.p.c = 0;
} else {
regs.p.c = 1;
}
r = (n3 << 12) | (n2 << 8) | (n1 << 4) | (n0);
} else {
r = regs.a.w - rd.w - !regs.p.c;
regs.p.c = r >= 0;
}
regs.p.n = r & 0x8000;
regs.p.v = (regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000;
regs.p.z = (uint16)r == 0;
regs.a.w = r;
}
//op_rmw
inline void sCPU::op_inc_b() {
rd.l++;
regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0;
}
inline void sCPU::op_inc_w() {
rd.w++;
regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0;
}
inline void sCPU::op_dec_b() {
rd.l--;
regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0;
}
inline void sCPU::op_dec_w() {
rd.w--;
regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0;
}
inline void sCPU::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() {
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() {
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() {
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() {
unsigned carry = (unsigned)regs.p.c;
regs.p.c = rd.l & 0x80;
rd.l = (rd.l << 1) | carry;
regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0;
}
inline void sCPU::op_rol_w() {
unsigned carry = (unsigned)regs.p.c;
regs.p.c = rd.w & 0x8000;
rd.w = (rd.w << 1) | carry;
regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0;
}
inline void sCPU::op_ror_b() {
unsigned carry = (unsigned)regs.p.c << 7;
regs.p.c = rd.l & 1;
rd.l = carry | (rd.l >> 1);
regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0;
}
inline void sCPU::op_ror_w() {
unsigned carry = (unsigned)regs.p.c << 15;
regs.p.c = rd.w & 1;
rd.w = carry | (rd.w >> 1);
regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0;
}
inline void sCPU::op_trb_b() {
regs.p.z = (rd.l & regs.a.l) == 0;
rd.l &= ~regs.a.l;
}
inline void sCPU::op_trb_w() {
regs.p.z = (rd.w & regs.a.w) == 0;
rd.w &= ~regs.a.w;
}
inline void sCPU::op_tsb_b() {
regs.p.z = (rd.l & regs.a.l) == 0;
rd.l |= regs.a.l;
}
inline void sCPU::op_tsb_w() {
regs.p.z = (rd.w & regs.a.w) == 0;
rd.w |= regs.a.w;
}
#endif //ifdef SCPU_CPP

View File

@ -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;
}

View File

@ -3,6 +3,8 @@
void sCPU::dma_add_clocks(unsigned clocks) { void sCPU::dma_add_clocks(unsigned clocks) {
status.dma_clocks += clocks; status.dma_clocks += clocks;
add_clocks(clocks); add_clocks(clocks);
scheduler.sync_cpucop();
scheduler.sync_cpuppu();
} }
bool sCPU::dma_addr_valid(uint32 abus) { bool sCPU::dma_addr_valid(uint32 abus) {

View File

@ -1,13 +1,5 @@
#ifdef SCPU_CPP #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() { void sCPU::op_io() {
status.clock_count = 6; status.clock_count = 6;
precycle_edge(); precycle_edge();
@ -16,9 +8,10 @@ void sCPU::op_io() {
} }
uint8 sCPU::op_read(uint32 addr) { uint8 sCPU::op_read(uint32 addr) {
status.clock_count = bus.speed(addr); status.clock_count = speed(addr);
precycle_edge(); precycle_edge();
add_clocks(status.clock_count - 4); add_clocks(status.clock_count - 4);
scheduler.sync_cpucop();
regs.mdr = bus.read(addr); regs.mdr = bus.read(addr);
add_clocks(4); add_clocks(4);
cycle_edge(); cycle_edge();
@ -26,100 +19,23 @@ uint8 sCPU::op_read(uint32 addr) {
} }
void sCPU::op_write(uint32 addr, uint8 data) { void sCPU::op_write(uint32 addr, uint8 data) {
status.clock_count = bus.speed(addr); status.clock_count = speed(addr);
precycle_edge(); precycle_edge();
add_clocks(status.clock_count); add_clocks(status.clock_count);
regs.mdr = data; scheduler.sync_cpucop();
bus.write(addr, regs.mdr); bus.write(addr, regs.mdr = data);
cycle_edge(); cycle_edge();
} }
// unsigned sCPU::speed(unsigned addr) const {
if(addr & 0x408000) {
alwaysinline uint8 sCPU::op_readpc() { if(addr & 0x800000) return status.rom_speed;
return op_read((regs.pc.b << 16) + regs.pc.w++); return 8;
}
alwaysinline uint8 sCPU::op_readstack() {
if(regs.e) {
regs.s.l++;
} else {
regs.s.w++;
} }
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() { #endif
return op_read(++regs.s.w);
}
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

View File

@ -1,35 +1,16 @@
/***** //============================
* CPU<>APU communication ports //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; }
/***** uint8 apu_port[4];
* core CPU bus functions uint8 port_read(uint8 port) { return apu_port[port & 3]; }
*****/ void port_write(uint8 port, uint8 data) { apu_port[port & 3] = data; }
void op_io();
uint8 op_read(uint32 addr);
void op_write(uint32 addr, uint8 data);
/***** //======================
* helper memory addressing functions used by CPU core //core CPU bus functions
*****/ //======================
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);
void op_writestack (uint8 data); void op_io();
void op_writestackn(uint8 data); uint8 op_read(uint32 addr);
void op_writeaddr (uint32 addr, uint8 data); void op_write(uint32 addr, uint8 data);
void op_writelong (uint32 addr, uint8 data); alwaysinline unsigned speed(unsigned addr) const;
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);

View File

@ -42,7 +42,7 @@ void sCPU::mmio_w4016(uint8 data) {
status.joypad_strobe_latch = !!(data & 1); status.joypad_strobe_latch = !!(data & 1);
if(status.joypad_strobe_latch == 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 //realtime or buffered status of joypadN.b
uint8 sCPU::mmio_r4016() { uint8 sCPU::mmio_r4016() {
uint8 r = regs.mdr & 0xfc; uint8 r = regs.mdr & 0xfc;
r |= snes.input.port_read(0) & 3; r |= input.port_read(0) & 3;
return r; return r;
} }
@ -64,7 +64,7 @@ uint8 sCPU::mmio_r4016() {
//1-0 = Joypad serial data //1-0 = Joypad serial data
uint8 sCPU::mmio_r4017() { uint8 sCPU::mmio_r4017() {
uint8 r = (regs.mdr & 0xe0) | 0x1c; uint8 r = (regs.mdr & 0xe0) | 0x1c;
r |= snes.input.port_read(1) & 3; r |= input.port_read(1) & 3;
return r; return r;
} }
@ -93,7 +93,7 @@ void sCPU::mmio_w4203(uint8 data) {
status.r4216 = status.mul_a * status.mul_b; status.r4216 = status.mul_a * status.mul_b;
status.alu_lock = true; status.alu_lock = true;
event.enqueue(snes.config.cpu.alu_mul_delay, EventAluLockRelease); event.enqueue(config.cpu.alu_mul_delay, EventAluLockRelease);
} }
//WRDIVL //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.r4216 = (status.div_b) ? status.div_a % status.div_b : status.div_a;
status.alu_lock = true; status.alu_lock = true;
event.enqueue(snes.config.cpu.alu_div_delay, EventAluLockRelease); event.enqueue(config.cpu.alu_div_delay, EventAluLockRelease);
} }
//HTIMEL //HTIMEL
@ -157,7 +157,7 @@ void sCPU::mmio_w420c(uint8 data) {
//MEMSEL //MEMSEL
void sCPU::mmio_w420d(uint8 data) { void sCPU::mmio_w420d(uint8 data) {
bus.set_speed(data & 1); status.rom_speed = (data & 1 ? 6 : 8);
} }
//RDNMI //RDNMI
@ -402,6 +402,9 @@ void sCPU::mmio_reset() {
status.hirq_pos = 0x01ff; status.hirq_pos = 0x01ff;
status.virq_pos = 0x01ff; status.virq_pos = 0x01ff;
//$420d
status.rom_speed = 8;
//$4214-$4217 //$4214-$4217
status.r4214 = 0x0000; status.r4214 = 0x0000;
status.r4216 = 0x0000; status.r4216 = 0x0000;

View File

@ -1,15 +1,54 @@
#include <../base.hpp> #include <../base.hpp>
#define SCPU_CPP
#include <nall/priorityqueue.hpp> #include <nall/priorityqueue.hpp>
#define SCPU_CPP
namespace SNES {
priority_queue<unsigned> event(512, bind(&sCPU::queue_event, &cpu)); priority_queue<unsigned> event(512, bind(&sCPU::queue_event, &cpu));
#include "core/core.cpp"
#include "dma/dma.cpp" #include "dma/dma.cpp"
#include "memory/memory.cpp" #include "memory/memory.cpp"
#include "mmio/mmio.cpp" #include "mmio/mmio.cpp"
#include "timing/timing.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() { void sCPU::power() {
CPU::power(); CPU::power();
@ -26,11 +65,8 @@ void sCPU::power() {
void sCPU::reset() { void sCPU::reset() {
CPU::reset(); CPU::reset();
regs.pc.d = 0x000000;
regs.pc.l = bus.read(0xfffc);
regs.pc.h = bus.read(0xfffd);
//note: some registers are not fully reset by SNES //note: some registers are not fully reset by SNES
regs.pc = 0x000000;
regs.x.h = 0x00; regs.x.h = 0x00;
regs.y.h = 0x00; regs.y.h = 0x00;
regs.s.h = 0x01; regs.s.h = 0x01;
@ -39,8 +75,9 @@ void sCPU::reset() {
regs.p = 0x34; regs.p = 0x34;
regs.e = 1; regs.e = 1;
regs.mdr = 0x00; regs.mdr = 0x00;
regs.wai = false;
update_table();
status.wai_lock = false;
status.interrupt_pending = false; status.interrupt_pending = false;
status.interrupt_vector = 0xfffc; //reset vector address status.interrupt_vector = 0xfffc; //reset vector address
@ -59,3 +96,5 @@ sCPU::sCPU() {
sCPU::~sCPU() { sCPU::~sCPU() {
} }
};

View File

@ -1,8 +1,9 @@
class sCPU : public CPU { class sCPU : public CPU, public CPUcore {
public: public:
void enter(); void enter();
void op_irq();
bool interrupt_pending() { return status.interrupt_pending; }
#include "core/core.hpp"
#include "dma/dma.hpp" #include "dma/dma.hpp"
#include "memory/memory.hpp" #include "memory/memory.hpp"
#include "mmio/mmio.hpp" #include "mmio/mmio.hpp"
@ -11,11 +12,6 @@ public:
enum DmaState { DmaInactive, DmaRun, DmaCpuSync }; enum DmaState { DmaInactive, DmaRun, DmaCpuSync };
struct { struct {
//core
uint8 opcode;
bool in_opcode;
bool wai_lock;
bool interrupt_pending; bool interrupt_pending;
uint16 interrupt_vector; uint16 interrupt_vector;
@ -75,6 +71,9 @@ public:
//$4207-$420a //$4207-$420a
uint16 hirq_pos, virq_pos; uint16 hirq_pos, virq_pos;
//$420d
unsigned rom_speed;
//$4214-$4217 //$4214-$4217
uint16 r4214; uint16 r4214;
uint16 r4216; uint16 r4216;

View File

@ -93,14 +93,14 @@ bool sCPU::timeup() {
bool sCPU::nmi_test() { bool sCPU::nmi_test() {
if(!status.nmi_transition) return false; if(!status.nmi_transition) return false;
status.nmi_transition = false; status.nmi_transition = false;
status.wai_lock = false; regs.wai = false;
return true; return true;
} }
bool sCPU::irq_test() { bool sCPU::irq_test() {
if(!status.irq_transition) return false; if(!status.irq_transition && !regs.irq) return false;
status.irq_transition = false; status.irq_transition = false;
status.wai_lock = false; regs.wai = false;
return !regs.p.i; return !regs.p.i;
} }

View File

@ -3,8 +3,8 @@
void sCPU::run_auto_joypad_poll() { void sCPU::run_auto_joypad_poll() {
uint16 joy1 = 0, joy2 = 0, joy3 = 0, joy4 = 0; uint16 joy1 = 0, joy2 = 0, joy3 = 0, joy4 = 0;
for(unsigned i = 0; i < 16; i++) { for(unsigned i = 0; i < 16; i++) {
uint8 port0 = snes.input.port_read(0); uint8 port0 = input.port_read(0);
uint8 port1 = snes.input.port_read(1); uint8 port1 = input.port_read(1);
joy1 |= (port0 & 1) ? (0x8000 >> i) : 0; joy1 |= (port0 & 1) ? (0x8000 >> i) : 0;
joy2 |= (port1 & 1) ? (0x8000 >> i) : 0; joy2 |= (port1 & 1) ? (0x8000 >> i) : 0;

View File

@ -13,19 +13,25 @@ void sCPU::add_clocks(unsigned clocks) {
unsigned ticks = clocks >> 1; unsigned ticks = clocks >> 1;
while(ticks--) { while(ticks--) {
ppu.tick(); ppu.tick();
if((ppu.hcounter() & 2) == 0) { if(ppu.hcounter() & 2) {
snes.input.tick(); input.tick();
} else {
poll_interrupts(); poll_interrupts();
} }
} }
scheduler.addclocks_cpu(clocks); scheduler.addclocks_cpu(clocks);
} }
//called by ppu.tick() when Hcounter=0
void sCPU::scanline() { void sCPU::scanline() {
status.dma_counter = (status.dma_counter + status.line_clocks) & 7; status.dma_counter = (status.dma_counter + status.line_clocks) & 7;
status.line_clocks = ppu.lineclocks(); 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) { if(ppu.vcounter() == 0) {
//hdma init triggers once every frame //hdma init triggers once every frame
event.enqueue(cpu_version == 1 ? 12 + 8 - dma_counter() : 12 + dma_counter(), EventHdmaInit); 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)) { if(status.auto_joypad_poll == true && ppu.vcounter() == (ppu.overscan() == false ? 227 : 242)) {
snes.input.poll(); input.poll();
run_auto_joypad_poll(); run_auto_joypad_poll();
} }
} }

View File

@ -1,5 +1,7 @@
#include <../base.hpp> #include <../base.hpp>
#define ADSP_CPP #define ADSP_CPP
namespaec SNES {
#include "adsp_tables.cpp" #include "adsp_tables.cpp"
@ -580,9 +582,13 @@ int32 fir_samplel, fir_sampler;
msampler = sclamp<16>(msampler); msampler = sclamp<16>(msampler);
} }
snes.audio.update(msamplel, msampler); audio.sample(msamplel, msampler);
scheduler.addclocks_dsp(32 * 3 * 8); scheduler.addclocks_dsp(32 * 3 * 8);
scheduler.sync_dspsmp();
} }
aDSP::aDSP() {} aDSP::aDSP() {}
aDSP::~aDSP() {} aDSP::~aDSP() {}
};

View File

@ -106,7 +106,7 @@ void sDSP::echo_27() {
} }
//output sample to DAC //output sample to DAC
snes.audio.update(outl, outr); audio.sample(outl, outr);
} }
void sDSP::echo_28() { void sDSP::echo_28() {

View File

@ -1,21 +1,21 @@
/* /*
S-DSP emulator S-DSP emulator
license: LGPLv2
Note: this is basically a C++ cothreaded implementation of Shay Green's (blargg's) S-DSP emulator. Note: this is basically a C++ cothreaded implementation of Shay Green's (blargg's) S-DSP emulator.
The actual algorithms, timing information, tables, variable names, etc were all from him. The actual algorithms, timing information, tables, variable names, etc were all from him.
*/ */
#include <../base.hpp> #include <../base.hpp>
#define SDSP_CPP #define SDSP_CPP
namespace SNES {
#define REG(n) state.regs[r_##n] #define REG(n) state.regs[r_##n]
#define VREG(n) state.regs[v.vidx + v_##n] #define VREG(n) state.regs[v.vidx + v_##n]
#if !defined(USE_STATE_MACHINE) #if !defined(DSP_STATE_MACHINE)
#define phase_start() while(true) { #define phase_start() while(true) {
#define phase(n) #define phase(n)
#define tick() scheduler.addclocks_dsp(3 * 8) #define tick() scheduler.addclocks_dsp(3 * 8); scheduler.sync_dspsmp()
#define phase_end() } #define phase_end() }
#else #else
#define phase_start() switch(phase_index) { #define phase_start() switch(phase_index) {
@ -324,3 +324,6 @@ sDSP::sDSP() {
sDSP::~sDSP() { sDSP::~sDSP() {
} }
};

View File

@ -1,24 +1,31 @@
#include "cheat/cheat.hpp" namespace SNES {
#include "cheat/cheat.hpp"
#include "memory/memory.hpp" #include "memory/memory.hpp"
#include "memory/smemory/smemory.hpp" #include "memory/smemory/smemory.hpp"
#include "cpu/cpu.hpp" #include "cpu/cpu.hpp"
#include "cpu/scpu/scpu.hpp" #include "cpu/core/core.hpp"
#include "cpu/scpu/scpu.hpp"
#include "ppu/ppu.hpp" #include "smp/smp.hpp"
#include "ppu/bppu/bppu.hpp" #include "smp/core/core.hpp"
#include "smp/ssmp/ssmp.hpp"
#include "smp/smp.hpp" #include "ppu/ppu.hpp"
#include "smp/ssmp/ssmp.hpp" #include "ppu/bppu/bppu.hpp"
#include "dsp/dsp.hpp" #include "dsp/dsp.hpp"
#include "dsp/sdsp/sdsp.hpp" #include "dsp/sdsp/sdsp.hpp"
extern BUSCORE bus; extern BUSCORE bus;
extern CPUCORE cpu; extern CPUCORE cpu;
extern SMPCORE smp; extern SMPCORE smp;
extern DSPCORE dsp; extern DSPCORE dsp;
extern PPUCORE ppu; extern PPUCORE ppu;
#include "system/system.hpp"
#include "chip/chip.hpp"
#include "cartridge/cartridge.hpp"
};
#include "snes/snes.hpp"

View File

@ -1,63 +0,0 @@
# Makefile.string
# author: byuu
# license: public domain
[A-Z] = A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
[a-z] = a b c d e f g h i j k l m n o p q r s t u v w x y z
[0-9] = 0 1 2 3 4 5 6 7 8 9
[markup] = ` ~ ! @ \# $$ % ^ & * ( ) - _ = + [ { ] } \ | ; : ' " , < . > / ?
[all] = $([A-Z]) $([a-z]) $([0-9]) $([markup])
[space] :=
[space] +=
#####
# function strtr(source, from, to)
#####
strtr = \
$(eval __temp := $1) \
$(strip \
$(foreach c, \
$(join $(addsuffix :,$2),$3), \
$(eval __temp := \
$(subst $(word 1,$(subst :, ,$c)),$(word 2,$(subst :, ,$c)),$(__temp)) \
) \
) \
$(__temp) \
)
#####
# function strupper(source)
#####
strupper = $(call strtr,$1,$([a-z]),$([A-Z]))
#####
# function strlower(source)
#####
strlower = $(call strtr,$1,$([A-Z]),$([a-z]))
#####
# function strlen(source)
#####
strlen = \
$(eval __temp := $(subst $([space]),_,$1)) \
$(words \
$(strip \
$(foreach c, \
$([all]), \
$(eval __temp := \
$(subst $c,$c ,$(__temp)) \
) \
) \
$(__temp) \
) \
)
#####
# function streq(source)
#####
streq = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),,1)
#####
# function strne(source)
#####
strne = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),1,)

View File

@ -130,6 +130,21 @@ namespace nall {
return false; return false;
} }
static unsigned size(const char *fn) {
#if !defined(_WIN32)
FILE *fp = fopen(fn, "rb");
#else
FILE *fp = _wfopen(utf16_t(fn), L"rb");
#endif
unsigned filesize = 0;
if(fp) {
fseek(fp, 0, SEEK_END);
filesize = ftell(fp);
fclose(fp);
}
return filesize;
}
bool open() { bool open() {
return fp; return fp;
} }

View File

@ -135,6 +135,11 @@ namespace nall {
function() { data.fn_call = 0; } function() { data.fn_call = 0; }
function(void *fn) {
data.fn_call = &fn_call_global;
data.fn_global = (R (*)(PL))fn;
}
function(R (*fn)(PL)) { function(R (*fn)(PL)) {
data.fn_call = &fn_call_global; data.fn_call = &fn_call_global;
data.fn_global = fn; data.fn_global = fn;
@ -156,7 +161,8 @@ namespace nall {
data.object = obj; data.object = obj;
} }
function &operator=(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); return *this; } function& operator=(void *fn) { return operator=(function(fn)); }
function& operator=(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); return *this; }
function(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); } function(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); }
}; };

View File

@ -20,6 +20,7 @@
#include <io.h> #include <io.h>
#include <direct.h> #include <direct.h>
#include <shlobj.h> #include <shlobj.h>
#undef interface
#else #else
#include <unistd.h> #include <unistd.h>
#include <pwd.h> #include <pwd.h>
@ -73,3 +74,4 @@
#endif #endif
#endif #endif

View File

@ -11,6 +11,7 @@
#undef NOMINMAX #undef NOMINMAX
#define NOMINMAX #define NOMINMAX
#include <windows.h> #include <windows.h>
#undef interface
namespace nall { namespace nall {
//UTF-8 to UTF-16 //UTF-8 to UTF-16

View File

@ -1,11 +1,6 @@
#include <AL/al.h>
#include <AL/alc.h>
#ifdef __APPLE__
#include <al.h>
#include <alc.h>
#else
#include <AL/al.h>
#include <AL/alc.h>
#endif
namespace ruby { namespace ruby {
#include "openal.hpp" #include "openal.hpp"

View File

@ -26,6 +26,9 @@
#include <GL/gl.h> #include <GL/gl.h>
#include <GL/glx.h> #include <GL/glx.h>
//#include <gl.h >
//#include <glu.h>
namespace ruby { namespace ruby {
#include "glx.hpp" #include "glx.hpp"

View File

@ -1,6 +1,15 @@
rm -r nall rm -r nall
rm -r ruby rm -r ruby
rm -r bpp
cp -r ../../../nall ./nall cp -r ../../../nall ./nall
cp -r ../../../ruby ./ruby cp -r ../../../ruby ./ruby
cp -r ../../../bpp ./bpp
rm ruby/test* rm ruby/test*
rm ruby/cc.* rm ruby/cc.*
rm bpp/test*
rm bpp/*.bpp
rm bpp/bpp
rm bpp/cc.*

View File

@ -1,157 +0,0 @@
/* broken -- need to port libstring to bstring */
#include "libbase.h"
#include "libstring.h"
#include "libstring.cpp"
FILE *fp, *fph, *fpt;
stringarray data, line, part, subpart;
stringarray output_table, output_header, output_op;
struct _op_list {
stringarray name, arg;
} op_list[64];
int32 op_count, line_num;
void clear_op_list() {
op_count = 0;
for(int i = 0; i < 64; i++) {
strcpy(op_list[i].name, "");
for(int l = 0; l < 8; l++) {
strcpy(op_list[i].arg[l], "");
}
}
}
void gen_header() {
int i = line_num;
char t[4096];
clear_op_list();
while(1) {
int z = op_count++;
strcpy(part, line[i]);
strrtrim(part, "),");
strrtrim(part, ") {");
split(subpart, "(", part);
strcpy(op_list[z].name, subpart[0]);
split(part, ", ", subpart[1]);
for(int l = 0; l < count(part); l++) {
strcpy(op_list[z].arg[l], part[l]);
}
if(strend(line[i], " {"))break;
i++;
}
sprintf(output_op, "void " CLASS_NAME "::op_$$() {\r\n switch(status.cycle_pos++) {\r\n");
sprintf(output_header, "void op_$$();\r\n");
sprintf(output_table, "optbl[$0] = &" CLASS_NAME "::op_$$;\r\n");
line_num = i + 1;
}
void update_line(int i, int n) {
char t[4096];
replace(line[i], "end;", "status.cycle_pos = 0;");
replace(line[i], "skip;", "status.cycle_pos++;");
}
void gen_op() {
int i = line_num, n, c;
char t[4096];
while(1) {
if(strmatch(line[i], "}"))break;
n = strdec(line[i]);
sprintf(t, "%d:", n);
strltrim(line[i], t);
sprintf(t, " case %d: {\r\n", n);
strcat(output_op, t);
update_line(i, n);
if(!strmatch(line[i], "")) {
strcat(output_op, " ");
strcat(output_op, line[i]);
strcat(output_op, "\r\n");
}
i++;
while(1) {
if(strptr(line[i])[1] == ':' || strptr(line[i])[2] == ':' || strmatch(line[i], "}"))break;
update_line(i, n);
strcat(output_op, " ");
strcat(output_op, line[i]);
strcat(output_op, "\r\n");
i++;
}
if(strmatch(line[i], "}")) {
strcat(output_op, " status.cycle_pos = 0;\r\n");
}
strcat(output_op, " } break;\r\n");
}
strcat(output_op, " }\r\n}");
line_num = i + 1;
}
void gen_final() {
string t;
for(int i = 0; i < op_count; i++) {
strcpy(t, output_op);
replace(t, "$$", op_list[i].name);
replace(t, "$0", op_list[i].arg[0]);
replace(t, "$1", op_list[i].arg[1]);
replace(t, "$2", op_list[i].arg[2]);
replace(t, "$3", op_list[i].arg[3]);
replace(t, "$4", op_list[i].arg[4]);
replace(t, "$5", op_list[i].arg[5]);
replace(t, "$6", op_list[i].arg[6]);
replace(t, "$7", op_list[i].arg[7]);
fprintf(fp, "%s\r\n\r\n", strptr(t));
strcpy(t, output_header);
replace(t, "$$", op_list[i].name);
fprintf(fph, "%s", strptr(t));
strcpy(t, output_table);
replace(t, "$$", op_list[i].name);
replace(t, "$0", op_list[i].arg[0]);
fprintf(fpt, "%s", strptr(t));
}
}
void generate(char *dest, char *src) {
fp = fopen(src, "rb");
fseek(fp, 0, SEEK_END);
int fsize = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *buf = (char*)malloc(fsize + 1);
fread(buf, 1, fsize, fp);
fclose(fp);
buf[fsize] = 0;
strcpy(data, buf);
free(buf);
replace(data, "\r\n", "\n");
split(line, "\n", data);
fp = fopen(dest, "wb");
line_num = 0;
while(line_num < count(line)) {
while(line_num < count(line) && strmatch(line[line_num], ""))line_num++;
if(line_num >= count(line))break;
gen_header();
gen_op();
gen_final();
}
fclose(fp);
}

View File

@ -1,149 +0,0 @@
/* broken -- need to port libstring to bstring */
#include "libbase.h"
#include "libstring.h"
#include "libstring.cpp"
FILE *fp, *fph, *fpt;
stringarray data, line, part, subpart;
stringarray output_table, output_header, output_op;
struct _op_list {
stringarray name, arg;
} op_list[64];
int32 op_count, line_num;
void clear_op_list() {
op_count = 0;
for(int i = 0; i < 64; i++) {
strcpy(op_list[i].name, "");
for(int l = 0; l < 8; l++) {
strcpy(op_list[i].arg[l], "");
}
}
}
void gen_header() {
int i = line_num;
char t[4096];
clear_op_list();
while(1) {
int z = op_count++;
strcpy(part, line[i]);
strrtrim(part, "),");
strrtrim(part, ") {");
split(subpart, "(", part);
strcpy(op_list[z].name, subpart[0]);
split(part, ", ", subpart[1]);
for(int l = 0; l < count(part); l++) {
strcpy(op_list[z].arg[l], part[l]);
}
if(strend(line[i], " {"))break;
i++;
}
sprintf(output_op, "void " CLASS_NAME "::op_$$() {\r\n");
sprintf(output_header, "void op_$$();\r\n");
sprintf(output_table, "optbl[$0] = &" CLASS_NAME "::op_$$;\r\n");
line_num = i + 1;
}
void update_line(int i) {
char t[4096];
replace(line[i], "end;", "return;");
}
void gen_op() {
int i = line_num, n, c;
char t[4096];
while(1) {
if(!strcmp(line[i], "}"))break;
n = strdec(line[i]);
sprintf(t, "%d:", n);
strltrim(line[i], t);
//sprintf(t, " case %d: {\r\n", n);
//strcat(output_op, t);
update_line(i);
if(strcmp(line[i], "")) {
strcat(output_op, " ");
strcat(output_op, line[i]);
strcat(output_op, "\r\n");
}
i++;
while(1) {
if(strptr(line[i])[1] == ':' || strptr(line[i])[2] == ':' || !strcmp(line[i], "}"))break;
update_line(i);
strcat(output_op, line[i]);
strcat(output_op, "\r\n");
i++;
}
}
strcat(output_op, "}");
line_num = i + 1;
}
void gen_final() {
string t;
for(int i = 0; i < op_count; i++) {
strcpy(t, output_op);
replace(t, "$$", op_list[i].name);
replace(t, "$0", op_list[i].arg[0]);
replace(t, "$1", op_list[i].arg[1]);
replace(t, "$2", op_list[i].arg[2]);
replace(t, "$3", op_list[i].arg[3]);
replace(t, "$4", op_list[i].arg[4]);
replace(t, "$5", op_list[i].arg[5]);
replace(t, "$6", op_list[i].arg[6]);
replace(t, "$7", op_list[i].arg[7]);
fprintf(fp, "%s\r\n\r\n", strptr(t));
strcpy(t, output_header);
replace(t, "$$", op_list[i].name);
fprintf(fph, "%s", strptr(t));
strcpy(t, output_table);
replace(t, "$$", op_list[i].name);
replace(t, "$0", op_list[i].arg[0]);
fprintf(fpt, "%s", strptr(t));
}
}
void generate(char *dest, char *src) {
fp = fopen(src, "rb");
fseek(fp, 0, SEEK_END);
int fsize = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *buf = (char*)malloc(fsize + 1);
fread(buf, 1, fsize, fp);
fclose(fp);
buf[fsize] = 0;
strcpy(data, buf);
free(buf);
replace(data, "\r\n", "\n");
split(line, "\n", data);
fp = fopen(dest, "wb");
line_num = 0;
while(line_num < count(line)) {
while(line_num < count(line) && !strcmp(line[line_num], ""))line_num++;
if(line_num >= count(line))break;
gen_header();
gen_op();
gen_final();
}
fclose(fp);
}

View File

@ -1,127 +0,0 @@
#include <nall/string.hpp>
using namespace nall;
FILE *fp;
string data, output_op;
lstring line, part, subpart;
struct OpList {
string name;
lstring arg;
} op_list[64];
int32_t op_count, line_num;
void clear_op_list() {
op_count = 0;
for(unsigned i = 0; i < 64; i++) {
strcpy(op_list[i].name, "");
for(unsigned l = 0; l < 8; l++) {
strcpy(op_list[i].arg[l], "");
}
}
}
void gen_begin() {
int i = line_num;
clear_op_list();
while(true) {
int z = op_count++;
string temp = line[i];
rtrim(temp, "),");
rtrim(temp, ") {");
split(subpart, "(", temp);
strcpy(op_list[z].name, subpart[0]);
split(part, ", ", subpart[1]);
for(unsigned l = 0; l < count(part); l++) {
strcpy(op_list[z].arg[l], part[l]);
}
if(strend(line[i], " {") == true) break;
i++;
}
strcpy(output_op, "//$$\r\ncase $0: {\r\n");
line_num = i + 1;
}
void update_line(int i) {
replace(line[i], "end;", "break;");
}
void gen_op() {
int i = line_num, n, c;
char t[4096];
while(true) {
if(!strcmp(line[i], "}"))break;
//remove cycle number
n = strdec((const char*)line[i]);
sprintf(t, "%d:", n);
ltrim(line[i], t);
//sprintf(t, "//%d:\r\n", n);
//strcat(output_op, t);
update_line(i);
if(strcmp(line[i], "")) {
strcat(output_op, " ");
strcat(output_op, line[i]);
strcat(output_op, "\r\n");
}
i++;
while(true) {
if(line[i][1] == ':' || line[i][2] == ':' || line[i] == "}") break;
update_line(i);
strcat(output_op, line[i]);
strcat(output_op, "\r\n");
i++;
}
}
strcat(output_op, "} break;");
line_num = i + 1;
}
void gen_end() {
string t;
for(unsigned i = 0; i < op_count; i++) {
t = output_op;
replace(t, "$$", op_list[i].name);
replace(t, "$0", op_list[i].arg[0]);
replace(t, "$1", op_list[i].arg[1]);
replace(t, "$2", op_list[i].arg[2]);
replace(t, "$3", op_list[i].arg[3]);
replace(t, "$4", op_list[i].arg[4]);
replace(t, "$5", op_list[i].arg[5]);
replace(t, "$6", op_list[i].arg[6]);
replace(t, "$7", op_list[i].arg[7]);
fprintf(fp, "%s\r\n\r\n", (const char*)t);
}
}
void generate(const char *dest, const char *src) {
fread(data, src);
replace(data, "\r\n", "\n");
split(line, "\n", data);
fp = fopen(dest, "wb");
string header = CLASS_NAME;
fprintf(fp, "#ifdef %s_CPP\n\n", (const char*)strupper(header)); //inclusion guard
line_num = 0;
while(line_num < count(line)) {
while(line_num < count(line) && !strcmp(line[line_num], "")) line_num++;
if(line_num >= count(line)) break;
gen_begin();
gen_op();
gen_end();
}
fprintf(fp, "#endif\n");
fclose(fp);
}

View File

@ -1,5 +1,7 @@
#include <../base.hpp> #include <../base.hpp>
#define MEMORY_CPP #define MEMORY_CPP
namespace SNES {
namespace memory { namespace memory {
MMIOAccess mmio; MMIOAccess mmio;
@ -24,18 +26,11 @@ void MMIOAccess::map(unsigned addr, MMIO &access) {
mmio[(addr - 0x2000) & 0x3fff] = &access; mmio[(addr - 0x2000) & 0x3fff] = &access;
} }
MMIO* MMIOAccess::get(unsigned addr) {
return mmio[(addr - 0x2000) & 0x3fff];
}
uint8 MMIOAccess::read(unsigned addr) { uint8 MMIOAccess::read(unsigned addr) {
printf("MMIOAccess::read 0x%x\n",addr); return mmio[(addr - 0x2000) & 0x3fff]->mmio_read(addr);
return mmio[(addr - 0x2000) & 0x3fff]->mmio_read(addr);
} }
void MMIOAccess::write(unsigned addr, uint8 data) { void MMIOAccess::write(unsigned addr, uint8 data) {
printf("MMIOAccess::write 0x%x %x\n",addr,data);
mmio[(addr - 0x2000) & 0x3fff]->mmio_write(addr, data); mmio[(addr - 0x2000) & 0x3fff]->mmio_write(addr, data);
} }
@ -70,7 +65,6 @@ void Bus::map(
) { ) {
assert(bank_lo <= bank_hi); assert(bank_lo <= bank_hi);
assert(addr_lo <= addr_hi); assert(addr_lo <= addr_hi);
if(access.size() == -1U) return; if(access.size() == -1U) return;
uint8 page_lo = addr_lo >> 8; uint8 page_lo = addr_lo >> 8;
@ -79,8 +73,6 @@ void Bus::map(
switch(mode) { switch(mode) {
case MapDirect: { case MapDirect: {
printf("Bus::map MapDirect bank_lo=0x%02x bank_hi=0x%02x addr_lo=0x%04x addr_hi=0x%04x\n",
bank_lo,bank_hi,addr_lo,addr_hi);
for(unsigned bank = bank_lo; bank <= bank_hi; bank++) { for(unsigned bank = bank_lo; bank <= bank_hi; bank++) {
for(unsigned page = page_lo; page <= page_hi; page++) { for(unsigned page = page_lo; page <= page_hi; page++) {
map((bank << 16) + (page << 8), access, (bank << 16) + (page << 8)); map((bank << 16) + (page << 8), access, (bank << 16) + (page << 8));
@ -89,8 +81,6 @@ void Bus::map(
} break; } break;
case MapLinear: { case MapLinear: {
printf("Bus::map MapLinear bank_lo=0x%02x bank_hi=0x%02x addr_lo=0x%04x addr_hi=0x%04x\n",
bank_lo,bank_hi,addr_lo,addr_hi);
for(unsigned bank = bank_lo; bank <= bank_hi; bank++) { for(unsigned bank = bank_lo; bank <= bank_hi; bank++) {
for(unsigned page = page_lo; page <= page_hi; page++) { for(unsigned page = page_lo; page <= page_hi; page++) {
map((bank << 16) + (page << 8), access, mirror(offset + index, access.size())); map((bank << 16) + (page << 8), access, mirror(offset + index, access.size()));
@ -101,8 +91,6 @@ void Bus::map(
} break; } break;
case MapShadow: { case MapShadow: {
printf("Bus::map MapShadow bank_lo=0x%02x bank_hi=0x%02x addr_lo=0x%04x addr_hi=0x%04x\n",
bank_lo,bank_hi,addr_lo,addr_hi);
for(unsigned bank = bank_lo; bank <= bank_hi; bank++) { for(unsigned bank = bank_lo; bank <= bank_hi; bank++) {
index += page_lo * 256; index += page_lo * 256;
if(size) index %= size; if(size) index %= size;
@ -119,3 +107,6 @@ void Bus::map(
} break; } break;
} }
} }
};

View File

@ -20,52 +20,62 @@ struct UnmappedMMIO : MMIO {
}; };
struct StaticRAM : Memory { struct StaticRAM : Memory {
uint8* handle() { return data; } uint8* data() { return data_; }
unsigned size() const { return datasize; } unsigned size() const { return size_; }
inline uint8 read(unsigned addr) { return data[addr]; } inline uint8 read(unsigned addr) { return data_[addr]; }
inline void write(unsigned addr, uint8 n) { data[addr] = n; } inline void write(unsigned addr, uint8 n) { data_[addr] = n; }
inline uint8& operator[](unsigned addr) { return data[addr]; } inline uint8& operator[](unsigned addr) { return data_[addr]; }
inline const uint8& operator[](unsigned addr) const { return data[addr]; } inline const uint8& operator[](unsigned addr) const { return data_[addr]; }
StaticRAM(unsigned n) : datasize(n) { data = new uint8[datasize]; } StaticRAM(unsigned n) : size_(n) { data_ = new uint8[size_]; }
~StaticRAM() { delete[] data; } ~StaticRAM() { delete[] data_; }
private: private:
uint8 *data; uint8 *data_;
unsigned datasize; unsigned size_;
}; };
struct MappedRAM : Memory { struct MappedRAM : Memory {
void map(uint8 *source, unsigned length) { data = source; datasize = length > 0 ? length : -1U; } void reset() {
void write_protect(bool status) { write_protection = status; } if(data_) {
uint8* handle() { return data; } delete[] data_;
unsigned size() const { return datasize; } data_ = 0;
}
size_ = -1U;
write_protect_ = false;
}
inline uint8 read(unsigned addr) { return data[addr]; } void map(uint8 *source, unsigned length) {
inline void write(unsigned addr, uint8 n) { if(!write_protection) data[addr] = n; } reset();
inline const uint8& operator[](unsigned addr) const { return data[addr]; } data_ = source;
size_ = data_ && length > 0 ? length : -1U;
}
MappedRAM() : data(0), datasize(0), write_protection(false) {} void write_protect(bool status) { write_protect_ = status; }
uint8* data() { return data_; }
unsigned size() const { return size_; }
inline uint8 read(unsigned addr) { return data_[addr]; }
inline void write(unsigned addr, uint8 n) { if(!write_protect_) data_[addr] = n; }
inline const uint8 operator[](unsigned addr) const { return data_[addr]; }
MappedRAM() : data_(0), size_(-1U), write_protect_(false) {}
private: private:
uint8 *data; uint8 *data_;
unsigned datasize; unsigned size_;
bool write_protection; bool write_protect_;
}; };
struct MMIOAccess : Memory { struct MMIOAccess : Memory {
void map(unsigned addr, MMIO &access); void map(unsigned addr, MMIO &access);
MMIO* get(unsigned addr);
uint8 read(unsigned addr); uint8 read(unsigned addr);
void write(unsigned addr, uint8 data); void write(unsigned addr, uint8 data);
private:
MMIO *mmio[0x4000]; MMIO *mmio[0x4000];
}; };
class Bus { struct Bus {
public:
unsigned mirror(unsigned addr, unsigned size); unsigned mirror(unsigned addr, unsigned size);
void map(unsigned addr, Memory &access, unsigned offset); void map(unsigned addr, Memory &access, unsigned offset);
enum MapMode { MapDirect, MapLinear, MapShadow }; enum MapMode { MapDirect, MapLinear, MapShadow };
@ -91,35 +101,19 @@ public:
return p.access->write(p.offset + addr, data); return p.access->write(p.offset + addr, data);
} }
void set_speed(bool fast) { virtual bool load_cart() { return false; }
fastSpeed = fast ? 6 : 8; virtual void unload_cart() {}
}
alwaysinline unsigned speed(unsigned addr) const { virtual void power() {}
if(addr & 0x408000) { virtual void reset() {}
if(addr & 0x800000) return fastSpeed;
return 8;
}
if((addr + 0x6000) & 0x4000) return 8;
if((addr - 0x4000) & 0x7e00) return 6;
return 12;
}
virtual bool load_cart() = 0;
virtual void unload_cart() = 0;
virtual void power() = 0;
virtual void reset() = 0;
Bus() {} Bus() {}
virtual ~Bus() {} virtual ~Bus() {}
protected:
struct Page { struct Page {
Memory *access; Memory *access;
unsigned offset; unsigned offset;
} page[65536]; } page[65536];
unsigned fastSpeed;
}; };
namespace memory { namespace memory {

View File

@ -8,19 +8,16 @@ void sBus::map_cx4() {
void sBus::map_dsp1() { void sBus::map_dsp1() {
switch(cartridge.dsp1_mapper()) { switch(cartridge.dsp1_mapper()) {
case Cartridge::DSP1LoROM1MB: { case Cartridge::DSP1LoROM1MB: {
printf("sBus::map_dsp1 DSP1LoROM1MB\n");
map(MapDirect, 0x20, 0x3f, 0x8000, 0xffff, dsp1); map(MapDirect, 0x20, 0x3f, 0x8000, 0xffff, dsp1);
map(MapDirect, 0xa0, 0xbf, 0x8000, 0xffff, dsp1); map(MapDirect, 0xa0, 0xbf, 0x8000, 0xffff, dsp1);
} break; } break;
case Cartridge::DSP1LoROM2MB: { case Cartridge::DSP1LoROM2MB: {
printf("sBus::map_dsp1 DSP1LoROM2MB\n");
map(MapDirect, 0x60, 0x6f, 0x0000, 0x7fff, dsp1); map(MapDirect, 0x60, 0x6f, 0x0000, 0x7fff, dsp1);
map(MapDirect, 0xe0, 0xef, 0x0000, 0x7fff, dsp1); map(MapDirect, 0xe0, 0xef, 0x0000, 0x7fff, dsp1);
} break; } break;
case Cartridge::DSP1HiROM: { case Cartridge::DSP1HiROM: {
printf("sBus::map_dsp1 DSP1HiROM\n");
map(MapDirect, 0x00, 0x1f, 0x6000, 0x7fff, dsp1); map(MapDirect, 0x00, 0x1f, 0x6000, 0x7fff, dsp1);
map(MapDirect, 0x80, 0x9f, 0x6000, 0x7fff, dsp1); map(MapDirect, 0x80, 0x9f, 0x6000, 0x7fff, dsp1);
} break; } break;
@ -28,7 +25,6 @@ void sBus::map_dsp1() {
} }
void sBus::map_dsp2() { void sBus::map_dsp2() {
printf("sBus::map_dsp2\n");
map(MapDirect, 0x20, 0x3f, 0x6000, 0x6fff, dsp2); map(MapDirect, 0x20, 0x3f, 0x6000, 0x6fff, dsp2);
map(MapDirect, 0x20, 0x3f, 0x8000, 0xbfff, dsp2); map(MapDirect, 0x20, 0x3f, 0x8000, 0xbfff, dsp2);
map(MapDirect, 0xa0, 0xbf, 0x6000, 0x6fff, dsp2); map(MapDirect, 0xa0, 0xbf, 0x6000, 0x6fff, dsp2);
@ -36,25 +32,21 @@ void sBus::map_dsp2() {
} }
void sBus::map_dsp3() { void sBus::map_dsp3() {
printf("sBus::map_dsp3\n");
map(MapDirect, 0x20, 0x3f, 0x8000, 0xffff, dsp3); map(MapDirect, 0x20, 0x3f, 0x8000, 0xffff, dsp3);
map(MapDirect, 0xa0, 0xbf, 0x8000, 0xffff, dsp3); map(MapDirect, 0xa0, 0xbf, 0x8000, 0xffff, dsp3);
} }
void sBus::map_dsp4() { void sBus::map_dsp4() {
printf("sBus::map_dsp4\n");
map(MapDirect, 0x30, 0x3f, 0x8000, 0xffff, dsp4); map(MapDirect, 0x30, 0x3f, 0x8000, 0xffff, dsp4);
map(MapDirect, 0xb0, 0xbf, 0x8000, 0xffff, dsp4); map(MapDirect, 0xb0, 0xbf, 0x8000, 0xffff, dsp4);
} }
void sBus::map_obc1() { void sBus::map_obc1() {
printf("sBus::map_obc1\n");
map(MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, obc1); map(MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, obc1);
map(MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, obc1); map(MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, obc1);
} }
void sBus::map_st010() { void sBus::map_st010() {
printf("sBus::map_st010\n");
map(MapDirect, 0x68, 0x6f, 0x0000, 0x0fff, st010); map(MapDirect, 0x68, 0x6f, 0x0000, 0x0fff, st010);
map(MapDirect, 0xe8, 0xef, 0x0000, 0x0fff, st010); map(MapDirect, 0xe8, 0xef, 0x0000, 0x0fff, st010);
} }

View File

@ -3,14 +3,12 @@
void sBus::map_generic() { void sBus::map_generic() {
switch(cartridge.mapper()) { switch(cartridge.mapper()) {
case Cartridge::LoROM: { case Cartridge::LoROM: {
printf("sBus::map_generic Cartridge::LoROM\n");
map(MapLinear, 0x00, 0x7f, 0x8000, 0xffff, memory::cartrom); map(MapLinear, 0x00, 0x7f, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0x80, 0xff, 0x8000, 0xffff, memory::cartrom); map(MapLinear, 0x80, 0xff, 0x8000, 0xffff, memory::cartrom);
map_generic_sram(); map_generic_sram();
} break; } break;
case Cartridge::HiROM: { case Cartridge::HiROM: {
printf("sBus::map_generic Cartridge::HiROM\n");
map(MapShadow, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom); map(MapShadow, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0x40, 0x7f, 0x0000, 0xffff, memory::cartrom); map(MapLinear, 0x40, 0x7f, 0x0000, 0xffff, memory::cartrom);
map(MapShadow, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom); map(MapShadow, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
@ -19,7 +17,6 @@ void sBus::map_generic() {
} break; } break;
case Cartridge::ExLoROM: { case Cartridge::ExLoROM: {
printf("sBus::map_generic Cartridge::ExLoROM\n");
map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom); map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0x40, 0x7f, 0x0000, 0xffff, memory::cartrom); map(MapLinear, 0x40, 0x7f, 0x0000, 0xffff, memory::cartrom);
map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom); map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
@ -28,7 +25,6 @@ void sBus::map_generic() {
} break; } break;
case Cartridge::ExHiROM: { case Cartridge::ExHiROM: {
printf("sBus::map_generic Cartridge::ExHiROM\n");
map(MapShadow, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom, 0x400000); map(MapShadow, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom, 0x400000);
map(MapLinear, 0x40, 0x7f, 0x0000, 0xffff, memory::cartrom, 0x400000); map(MapLinear, 0x40, 0x7f, 0x0000, 0xffff, memory::cartrom, 0x400000);
map(MapShadow, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom, 0x000000); map(MapShadow, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom, 0x000000);
@ -36,8 +32,11 @@ void sBus::map_generic() {
map_generic_sram(); map_generic_sram();
} break; } break;
case Cartridge::SA1ROM: {
//mapped via SA1Bus::init();
} break;
case Cartridge::SPC7110ROM: { case Cartridge::SPC7110ROM: {
printf("sBus::map_generic Cartridge::SPC7110ROM\n");
map(MapDirect, 0x00, 0x00, 0x6000, 0x7fff, spc7110); //save RAM w/custom logic map(MapDirect, 0x00, 0x00, 0x6000, 0x7fff, spc7110); //save RAM w/custom logic
map(MapShadow, 0x00, 0x0f, 0x8000, 0xffff, memory::cartrom); //program ROM map(MapShadow, 0x00, 0x0f, 0x8000, 0xffff, memory::cartrom); //program ROM
map(MapDirect, 0x30, 0x30, 0x6000, 0x7fff, spc7110); //save RAM w/custom logic map(MapDirect, 0x30, 0x30, 0x6000, 0x7fff, spc7110); //save RAM w/custom logic
@ -48,7 +47,6 @@ void sBus::map_generic() {
} break; } break;
case Cartridge::BSXROM: { case Cartridge::BSXROM: {
printf("sBus::map_generic Cartridge::BSXROM\n");
//full map is dynamically mapped by: //full map is dynamically mapped by:
//src/chip/bsx/bsx_cart.cpp : BSXCart::update_memory_map(); //src/chip/bsx/bsx_cart.cpp : BSXCart::update_memory_map();
map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom); map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
@ -56,7 +54,6 @@ void sBus::map_generic() {
} break; } break;
case Cartridge::BSCLoROM: { case Cartridge::BSCLoROM: {
printf("sBus::map_generic Cartridge::BSCLoROM\n");
map(MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom, 0x000000); map(MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom, 0x000000);
map(MapLinear, 0x20, 0x3f, 0x8000, 0xffff, memory::cartrom, 0x100000); map(MapLinear, 0x20, 0x3f, 0x8000, 0xffff, memory::cartrom, 0x100000);
map(MapLinear, 0x70, 0x7f, 0x0000, 0x7fff, memory::cartram, 0x000000); map(MapLinear, 0x70, 0x7f, 0x0000, 0x7fff, memory::cartram, 0x000000);
@ -67,7 +64,6 @@ void sBus::map_generic() {
} break; } break;
case Cartridge::BSCHiROM: { case Cartridge::BSCHiROM: {
printf("sBus::map_generic Cartridge::BSCHiROM\n");
map(MapShadow, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom); map(MapShadow, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0x20, 0x3f, 0x6000, 0x7fff, memory::cartram); map(MapLinear, 0x20, 0x3f, 0x6000, 0x7fff, memory::cartram);
map(MapShadow, 0x20, 0x3f, 0x8000, 0xffff, bsxflash); map(MapShadow, 0x20, 0x3f, 0x8000, 0xffff, bsxflash);
@ -81,7 +77,6 @@ void sBus::map_generic() {
} break; } break;
case Cartridge::STROM: { case Cartridge::STROM: {
printf("sBus::map_generic Cartridge::STROM\n");
map(MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom); map(MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0x20, 0x3f, 0x8000, 0xffff, memory::stArom); map(MapLinear, 0x20, 0x3f, 0x8000, 0xffff, memory::stArom);
map(MapLinear, 0x40, 0x5f, 0x8000, 0xffff, memory::stBrom); map(MapLinear, 0x40, 0x5f, 0x8000, 0xffff, memory::stBrom);
@ -99,21 +94,15 @@ void sBus::map_generic() {
void sBus::map_generic_sram() { void sBus::map_generic_sram() {
if(memory::cartram.size() == 0 || memory::cartram.size() == -1U) { return; } if(memory::cartram.size() == 0 || memory::cartram.size() == -1U) { return; }
printf("sBus::map_generic_sram\n");
map(MapLinear, 0x20, 0x3f, 0x6000, 0x7fff, memory::cartram); map(MapLinear, 0x20, 0x3f, 0x6000, 0x7fff, memory::cartram);
map(MapLinear, 0xa0, 0xbf, 0x6000, 0x7fff, memory::cartram); map(MapLinear, 0xa0, 0xbf, 0x6000, 0x7fff, memory::cartram);
//research shows only games with very large ROM/RAM sizes require MAD-1 memory mapping of SRAM //research shows only games with very large ROM/RAM sizes require MAD-1 memory mapping of SRAM
//otherwise, default to safer, larger SRAM address window //otherwise, default to safer, larger SRAM address window
uint16 addr_hi = (memory::cartrom.size() > 0x200000 || memory::cartram.size() > 32 * 1024) ? 0x7fff : 0xffff; uint16 addr_hi = (memory::cartrom.size() > 0x200000 || memory::cartram.size() > 32 * 1024) ? 0x7fff : 0xffff;
printf("sBus::map_generic_sram cart_size=%x addr_hi=0x%x\n",memory::cartram.size(),addr_hi);
map(MapLinear, 0x70, 0x7f, 0x0000, addr_hi, memory::cartram); map(MapLinear, 0x70, 0x7f, 0x0000, addr_hi, memory::cartram);
if(cartridge.mapper() != Cartridge::LoROM){ if(cartridge.mapper() != Cartridge::LoROM) return;
printf("sBus::map_generic_sram done\n");
return;
}
map(MapLinear, 0xf0, 0xff, 0x0000, addr_hi, memory::cartram); map(MapLinear, 0xf0, 0xff, 0x0000, addr_hi, memory::cartram);
printf("sBus::map_generic_sram done\n");
} }
#endif #endif

View File

@ -1,7 +1,7 @@
#include <../base.hpp> #include <../base.hpp>
#include <../chip/chip.hpp>
#include <../cart/cart.hpp>
#define SMEMORY_CPP #define SMEMORY_CPP
namespace SNES {
#include "mapper/system.cpp" #include "mapper/system.cpp"
#include "mapper/generic.cpp" #include "mapper/generic.cpp"
@ -9,12 +9,11 @@
void sBus::power() { void sBus::power() {
for(unsigned i = 0x2000; i <= 0x5fff; i++) memory::mmio.map(i, memory::mmio_unmapped); for(unsigned i = 0x2000; i <= 0x5fff; i++) memory::mmio.map(i, memory::mmio_unmapped);
for(unsigned i = 0; i < memory::wram.size(); i++) memory::wram[i] = snes.config.cpu.wram_init_value; for(unsigned i = 0; i < memory::wram.size(); i++) memory::wram[i] = config.cpu.wram_init_value;
reset(); reset();
} }
void sBus::reset() { void sBus::reset() {
set_speed(false);
} }
bool sBus::load_cart() { bool sBus::load_cart() {
@ -43,3 +42,6 @@ sBus::sBus() {
sBus::~sBus() { sBus::~sBus() {
} }
};

View File

@ -1,45 +1,46 @@
#include <../base.hpp> #include <../base.hpp>
#define BPPU_CPP #define BPPU_CPP
namespace SNES {
#include "bppu_mmio.cpp" #include "bppu_mmio.cpp"
#include "bppu_render.cpp" #include "bppu_render.cpp"
void bPPU::enter() { void bPPU::enter() {
loop: while(true) {
//H = 0 (initialize) //H = 0 (initialize)
scanline(); scanline();
if(ivcounter() == 0) frame(); if(ivcounter() == 0) frame();
add_clocks(10); add_clocks(10);
//H = 10 (OAM address reset) //H = 10 (OAM address reset)
if(ivcounter() == (!overscan() ? 225 : 240)) { if(ivcounter() == (!overscan() ? 225 : 240)) {
if(regs.display_disabled == false) { if(regs.display_disabled == false) {
regs.oam_addr = regs.oam_baseaddr << 1; regs.oam_addr = regs.oam_baseaddr << 1;
regs.oam_firstsprite = (regs.oam_priority == false) ? 0 : (regs.oam_addr >> 2) & 127; regs.oam_firstsprite = (regs.oam_priority == false) ? 0 : (regs.oam_addr >> 2) & 127;
}
} }
add_clocks(502);
//H = 512 (render)
render_scanline();
add_clocks(640);
//H = 1152 (cache OBSEL)
cache.oam_basesize = regs.oam_basesize;
cache.oam_nameselect = regs.oam_nameselect;
cache.oam_tdaddr = regs.oam_tdaddr;
add_clocks(ilineclocks() - 1152); //seek to start of next scanline
} }
add_clocks(502);
//H = 512 (render)
render_scanline();
add_clocks(640);
//H = 1152 (cache OBSEL)
cache.oam_basesize = regs.oam_basesize;
cache.oam_nameselect = regs.oam_nameselect;
cache.oam_tdaddr = regs.oam_tdaddr;
add_clocks(ilineclocks() - 1152); //seek to start of next scanline
goto loop;
} }
void bPPU::add_clocks(unsigned clocks) { void bPPU::add_clocks(unsigned clocks) {
tock(clocks); tock(clocks);
scheduler.addclocks_ppu(clocks); scheduler.addclocks_ppu(clocks);
scheduler.sync_ppucpu();
} }
void bPPU::scanline() { void bPPU::scanline() {
snes.scanline();
line = ivcounter(); line = ivcounter();
if(line == 0) { if(line == 0) {
@ -76,7 +77,7 @@ void bPPU::render_scanline() {
void bPPU::frame() { void bPPU::frame() {
PPU::frame(); PPU::frame();
snes.frame(); system.frame();
if(ifield() == 0) { if(ifield() == 0) {
display.interlace = regs.interlace; display.interlace = regs.interlace;
@ -92,7 +93,7 @@ void bPPU::power() {
for(unsigned i = 0; i < memory::cgram.size(); i++) memory::cgram[i] = 0x00; for(unsigned i = 0; i < memory::cgram.size(); i++) memory::cgram[i] = 0x00;
flush_tiledata_cache(); flush_tiledata_cache();
region = (snes.region() == SNES::NTSC ? 0 : 1); //0 = NTSC, 1 = PAL region = (system.region() == System::NTSC ? 0 : 1); //0 = NTSC, 1 = PAL
//$2100 //$2100
regs.display_disabled = 1; regs.display_disabled = 1;
@ -344,3 +345,5 @@ bPPU::bPPU() {
bPPU::~bPPU() { bPPU::~bPPU() {
free_tiledata_cache(); free_tiledata_cache();
} }
};

View File

@ -30,7 +30,7 @@ uint8 bPPU::vram_mmio_read(uint16 addr) {
} else { } else {
uint16 v = vcounter(); uint16 v = vcounter();
uint16 h = hcounter(); uint16 h = hcounter();
uint16 ls = ((snes.region() == SNES::NTSC ? 525 : 625) >> 1) - 1; uint16 ls = ((system.region() == System::NTSC ? 525 : 625) >> 1) - 1;
if(interlace() && !field()) ls++; if(interlace() && !field()) ls++;
if(v == ls && h == 1362) { if(v == ls && h == 1362) {
@ -333,17 +333,17 @@ void bPPU::mmio_w2115(uint8 value) {
regs.vram_incmode = !!(value & 0x80); regs.vram_incmode = !!(value & 0x80);
regs.vram_mapping = (value >> 2) & 3; regs.vram_mapping = (value >> 2) & 3;
switch(value & 3) { switch(value & 3) {
case 0: regs.vram_incsize = 1; break; case 0: regs.vram_incsize = 1; break;
case 1: regs.vram_incsize = 32; break; case 1: regs.vram_incsize = 32; break;
case 2: regs.vram_incsize = 128; break; case 2: regs.vram_incsize = 128; break;
case 3: regs.vram_incsize = 128; break; case 3: regs.vram_incsize = 128; break;
} }
} }
//VMADDL //VMADDL
void bPPU::mmio_w2116(uint8 value) { void bPPU::mmio_w2116(uint8 value) {
regs.vram_addr = (regs.vram_addr & 0xff00) | value; regs.vram_addr = (regs.vram_addr & 0xff00) | value;
uint16 addr = get_vram_address(); uint16 addr = get_vram_address();
regs.vram_readbuffer = vram_mmio_read(addr + 0); regs.vram_readbuffer = vram_mmio_read(addr + 0);
regs.vram_readbuffer |= vram_mmio_read(addr + 1) << 8; regs.vram_readbuffer |= vram_mmio_read(addr + 1) << 8;
} }
@ -351,7 +351,7 @@ uint16 addr = get_vram_address();
//VMADDH //VMADDH
void bPPU::mmio_w2117(uint8 value) { void bPPU::mmio_w2117(uint8 value) {
regs.vram_addr = (value << 8) | (regs.vram_addr & 0x00ff); regs.vram_addr = (value << 8) | (regs.vram_addr & 0x00ff);
uint16 addr = get_vram_address(); uint16 addr = get_vram_address();
regs.vram_readbuffer = vram_mmio_read(addr + 0); regs.vram_readbuffer = vram_mmio_read(addr + 0);
regs.vram_readbuffer |= vram_mmio_read(addr + 1) << 8; regs.vram_readbuffer |= vram_mmio_read(addr + 1) << 8;
} }
@ -759,21 +759,20 @@ uint8 bPPU::mmio_read(unsigned addr) {
case 0x2128: case 0x2128:
case 0x2129: case 0x2129:
case 0x212a: return regs.ppu1_mdr; case 0x212a: return regs.ppu1_mdr;
case 0x2134: return mmio_r2134(); //MPYL case 0x2134: return mmio_r2134(); //MPYL
case 0x2135: return mmio_r2135(); //MPYM case 0x2135: return mmio_r2135(); //MPYM
case 0x2136: return mmio_r2136(); //MPYH case 0x2136: return mmio_r2136(); //MPYH
case 0x2137: return mmio_r2137(); //SLHV case 0x2137: return mmio_r2137(); //SLHV
case 0x2138: return mmio_r2138(); //OAMDATAREAD case 0x2138: return mmio_r2138(); //OAMDATAREAD
case 0x2139: return mmio_r2139(); //VMDATALREAD case 0x2139: return mmio_r2139(); //VMDATALREAD
case 0x213a: return mmio_r213a(); //VMDATAHREAD case 0x213a: return mmio_r213a(); //VMDATAHREAD
case 0x213b: return mmio_r213b(); //CGDATAREAD case 0x213b: return mmio_r213b(); //CGDATAREAD
case 0x213c: return mmio_r213c(); //OPHCT case 0x213c: return mmio_r213c(); //OPHCT
case 0x213d: return mmio_r213d(); //OPVCT case 0x213d: return mmio_r213d(); //OPVCT
case 0x213e: return mmio_r213e(); //STAT77 case 0x213e: return mmio_r213e(); //STAT77
case 0x213f: return mmio_r213f(); //STAT78 case 0x213f: return mmio_r213f(); //STAT78
} }
//return 0x00;
return cpu.regs.mdr; return cpu.regs.mdr;
} }
@ -781,59 +780,60 @@ void bPPU::mmio_write(unsigned addr, uint8 data) {
scheduler.sync_cpuppu(); scheduler.sync_cpuppu();
switch(addr & 0xffff) { switch(addr & 0xffff) {
case 0x2100: mmio_w2100(data); return; //INIDISP case 0x2100: return mmio_w2100(data); //INIDISP
case 0x2101: mmio_w2101(data); return; //OBSEL case 0x2101: return mmio_w2101(data); //OBSEL
case 0x2102: mmio_w2102(data); return; //OAMADDL case 0x2102: return mmio_w2102(data); //OAMADDL
case 0x2103: mmio_w2103(data); return; //OAMADDH case 0x2103: return mmio_w2103(data); //OAMADDH
case 0x2104: mmio_w2104(data); return; //OAMDATA case 0x2104: return mmio_w2104(data); //OAMDATA
case 0x2105: mmio_w2105(data); return; //BGMODE case 0x2105: return mmio_w2105(data); //BGMODE
case 0x2106: mmio_w2106(data); return; //MOSAIC case 0x2106: return mmio_w2106(data); //MOSAIC
case 0x2107: mmio_w2107(data); return; //BG1SC case 0x2107: return mmio_w2107(data); //BG1SC
case 0x2108: mmio_w2108(data); return; //BG2SC case 0x2108: return mmio_w2108(data); //BG2SC
case 0x2109: mmio_w2109(data); return; //BG3SC case 0x2109: return mmio_w2109(data); //BG3SC
case 0x210a: mmio_w210a(data); return; //BG4SC case 0x210a: return mmio_w210a(data); //BG4SC
case 0x210b: mmio_w210b(data); return; //BG12NBA case 0x210b: return mmio_w210b(data); //BG12NBA
case 0x210c: mmio_w210c(data); return; //BG34NBA case 0x210c: return mmio_w210c(data); //BG34NBA
case 0x210d: mmio_w210d(data); return; //BG1HOFS case 0x210d: return mmio_w210d(data); //BG1HOFS
case 0x210e: mmio_w210e(data); return; //BG1VOFS case 0x210e: return mmio_w210e(data); //BG1VOFS
case 0x210f: mmio_w210f(data); return; //BG2HOFS case 0x210f: return mmio_w210f(data); //BG2HOFS
case 0x2110: mmio_w2110(data); return; //BG2VOFS case 0x2110: return mmio_w2110(data); //BG2VOFS
case 0x2111: mmio_w2111(data); return; //BG3HOFS case 0x2111: return mmio_w2111(data); //BG3HOFS
case 0x2112: mmio_w2112(data); return; //BG3VOFS case 0x2112: return mmio_w2112(data); //BG3VOFS
case 0x2113: mmio_w2113(data); return; //BG4HOFS case 0x2113: return mmio_w2113(data); //BG4HOFS
case 0x2114: mmio_w2114(data); return; //BG4VOFS case 0x2114: return mmio_w2114(data); //BG4VOFS
case 0x2115: mmio_w2115(data); return; //VMAIN case 0x2115: return mmio_w2115(data); //VMAIN
case 0x2116: mmio_w2116(data); return; //VMADDL case 0x2116: return mmio_w2116(data); //VMADDL
case 0x2117: mmio_w2117(data); return; //VMADDH case 0x2117: return mmio_w2117(data); //VMADDH
case 0x2118: mmio_w2118(data); return; //VMDATAL case 0x2118: return mmio_w2118(data); //VMDATAL
case 0x2119: mmio_w2119(data); return; //VMDATAH case 0x2119: return mmio_w2119(data); //VMDATAH
case 0x211a: mmio_w211a(data); return; //M7SEL case 0x211a: return mmio_w211a(data); //M7SEL
case 0x211b: mmio_w211b(data); return; //M7A case 0x211b: return mmio_w211b(data); //M7A
case 0x211c: mmio_w211c(data); return; //M7B case 0x211c: return mmio_w211c(data); //M7B
case 0x211d: mmio_w211d(data); return; //M7C case 0x211d: return mmio_w211d(data); //M7C
case 0x211e: mmio_w211e(data); return; //M7D case 0x211e: return mmio_w211e(data); //M7D
case 0x211f: mmio_w211f(data); return; //M7X case 0x211f: return mmio_w211f(data); //M7X
case 0x2120: mmio_w2120(data); return; //M7Y case 0x2120: return mmio_w2120(data); //M7Y
case 0x2121: mmio_w2121(data); return; //CGADD case 0x2121: return mmio_w2121(data); //CGADD
case 0x2122: mmio_w2122(data); return; //CGDATA case 0x2122: return mmio_w2122(data); //CGDATA
case 0x2123: mmio_w2123(data); return; //W12SEL case 0x2123: return mmio_w2123(data); //W12SEL
case 0x2124: mmio_w2124(data); return; //W34SEL case 0x2124: return mmio_w2124(data); //W34SEL
case 0x2125: mmio_w2125(data); return; //WOBJSEL case 0x2125: return mmio_w2125(data); //WOBJSEL
case 0x2126: mmio_w2126(data); return; //WH0 case 0x2126: return mmio_w2126(data); //WH0
case 0x2127: mmio_w2127(data); return; //WH1 case 0x2127: return mmio_w2127(data); //WH1
case 0x2128: mmio_w2128(data); return; //WH2 case 0x2128: return mmio_w2128(data); //WH2
case 0x2129: mmio_w2129(data); return; //WH3 case 0x2129: return mmio_w2129(data); //WH3
case 0x212a: mmio_w212a(data); return; //WBGLOG case 0x212a: return mmio_w212a(data); //WBGLOG
case 0x212b: mmio_w212b(data); return; //WOBJLOG case 0x212b: return mmio_w212b(data); //WOBJLOG
case 0x212c: mmio_w212c(data); return; //TM case 0x212c: return mmio_w212c(data); //TM
case 0x212d: mmio_w212d(data); return; //TS case 0x212d: return mmio_w212d(data); //TS
case 0x212e: mmio_w212e(data); return; //TMW case 0x212e: return mmio_w212e(data); //TMW
case 0x212f: mmio_w212f(data); return; //TSW case 0x212f: return mmio_w212f(data); //TSW
case 0x2130: mmio_w2130(data); return; //CGWSEL case 0x2130: return mmio_w2130(data); //CGWSEL
case 0x2131: mmio_w2131(data); return; //CGADDSUB case 0x2131: return mmio_w2131(data); //CGADDSUB
case 0x2132: mmio_w2132(data); return; //COLDATA case 0x2132: return mmio_w2132(data); //COLDATA
case 0x2133: mmio_w2133(data); return; //SETINI case 0x2133: return mmio_w2133(data); //SETINI
} }
} }
#endif //ifdef BPPU_CPP #endif

View File

@ -1,8 +1,8 @@
#ifdef BPPU_CPP #ifdef BPPU_CPP
void bPPU::build_sprite_list() { void bPPU::build_sprite_list() {
uint8 *tableA = memory::oam.handle(); uint8 *tableA = memory::oam.data();
uint8 *tableB = memory::oam.handle() + 512; uint8 *tableB = memory::oam.data() + 512;
for(unsigned i = 0; i < 128; i++) { for(unsigned i = 0; i < 128; i++) {
unsigned x = !!(*tableB & (1 << ((i & 3) << 1))); //0x01, 0x04, 0x10, 0x40 unsigned x = !!(*tableB & (1 << ((i & 3) << 1))); //0x01, 0x04, 0x10, 0x40

View File

@ -1,7 +1,7 @@
#ifdef PPU_CPP #ifdef PPU_CPP
//wrappers to allow PPUcounter::tick()/tock() to be inlined //wrappers to allow PPUcounter::tick()/tock() to be inlined
bool PPUcounter::region() const { return snes.region() == SNES::NTSC ? 0 : 1; } bool PPUcounter::region() const { return system.region() == System::NTSC ? 0 : 1; }
bool PPUcounter::interlace() const { return ppu.interlace(); } bool PPUcounter::interlace() const { return ppu.interlace(); }
void PPUcounter::scanline() { cpu.scanline(); } void PPUcounter::scanline() { cpu.scanline(); }
@ -15,20 +15,20 @@ void PPUcounter::scanline() { cpu.scanline(); }
//dot 327 range = { 1310, 1312, 1314 } //dot 327 range = { 1310, 1312, 1314 }
uint16 PPUcounter::hdot() const { uint16 PPUcounter::hdot() const {
if(region() == 0 && interlace() == false && status.vcounter == 240 && status.field == 1) { if(region() == 0 && interlace() == false && vcounter() == 240 && field() == 1) {
return (status.hcounter >> 2); return (hcounter() >> 2);
} else { } else {
return (status.hcounter - ((status.hcounter > 1292) << 1) - ((status.hcounter > 1310) << 1)) >> 2; return (hcounter() - ((hcounter() > 1292) << 1) - ((hcounter() > 1310) << 1)) >> 2;
} }
} }
uint16 PPUcounter::lineclocks() const { uint16 PPUcounter::lineclocks() const {
if(region() == 0 && interlace() == false && vcounter() == 240 && status.field == 1) return 1360; if(region() == 0 && interlace() == false && vcounter() == 240 && field() == 1) return 1360;
return 1364; return 1364;
} }
uint16 PPUcounter::ilineclocks() const { uint16 PPUcounter::ilineclocks() const {
if(region() == 0 && interlace() == false && ivcounter() == 240 && status.field == 1) return 1360; if(region() == 0 && interlace() == false && ivcounter() == 240 && ifield() == 1) return 1360;
return 1364; return 1364;
} }

View File

@ -1,9 +1,7 @@
class PPUcounter { class PPUcounter {
public: public:
alwaysinline void tick() { alwaysinline void tick() {
history.ppudiff += 2;
status.hcounter += 2; status.hcounter += 2;
if(status.hcounter >= 1360 && status.hcounter == lineclocks()) { if(status.hcounter >= 1360 && status.hcounter == lineclocks()) {
status.hcounter = 0; status.hcounter = 0;
status.vcounter++; status.vcounter++;
@ -17,7 +15,6 @@ public:
status.vcounter = 0; status.vcounter = 0;
status.field = !status.field; status.field = !status.field;
} }
scanline(); scanline();
} }
@ -25,6 +22,7 @@ public:
history.field [history.index] = status.field; history.field [history.index] = status.field;
history.vcounter[history.index] = status.vcounter; history.vcounter[history.index] = status.vcounter;
history.hcounter[history.index] = status.hcounter; history.hcounter[history.index] = status.hcounter;
history.ppudiff += 2;
} }
alwaysinline void tock(unsigned clocks) { alwaysinline void tock(unsigned clocks) {
@ -67,7 +65,7 @@ private:
uint16 vcounter[2048]; uint16 vcounter[2048];
uint16 hcounter[2048]; uint16 hcounter[2048];
unsigned index; int32 index;
signed ppudiff; int32 ppudiff;
} history; } history;
}; };

View File

@ -1,5 +1,7 @@
#include <../base.hpp> #include <../base.hpp>
#define PPU_CPP #define PPU_CPP
namespace SNES {
#include "counter.cpp" #include "counter.cpp"
@ -25,8 +27,8 @@ void PPU::frame() {
} }
void PPU::power() { void PPU::power() {
ppu1_version = snes.config.ppu1.version; ppu1_version = config.ppu1.version;
ppu2_version = snes.config.ppu2.version; ppu2_version = config.ppu2.version;
} }
void PPU::reset() { void PPU::reset() {
@ -45,3 +47,5 @@ PPU::PPU() {
PPU::~PPU() { PPU::~PPU() {
delete[] output; delete[] output;
} }
};

View File

@ -1,50 +0,0 @@
#ifdef READER_CPP
#include "filereader.hpp"
unsigned FileReader::size() {
return fp.size();
}
//This function will allocate memory even if open() fails.
//This is needed so that when SRAM files do not exist, the
//memory for the SRAM data will be allocated still.
//The memory is flushed to 0x00 when no file is opened.
uint8_t* FileReader::read(unsigned length) {
uint8_t *data = 0;
if(length == 0) {
//read the entire file into RAM
data = new(zeromemory) uint8_t[fp.size()];
if(fp.open()) fp.read(data, fp.size());
} else if(length > fp.size()) {
//read the entire file into RAM, pad the rest with 0x00s
data = new(zeromemory) uint8_t[length];
if(fp.open()) fp.read(data, fp.size());
} else { //filesize >= length
//read only what was requested
data = new(zeromemory) uint8_t[length];
if(fp.open()) fp.read(data, length);
}
return data;
}
bool FileReader::ready() {
return fp.open();
}
FileReader::FileReader(const char *fn) {
if(!fp.open(fn, file::mode_read)) return;
if(fp.size() == 0) {
//empty file
fp.close();
}
}
FileReader::~FileReader() {
if(fp.open()) fp.close();
}
#endif //ifdef READER_CPP

View File

@ -1,12 +0,0 @@
class FileReader : public Reader {
public:
unsigned size();
uint8_t* read(unsigned length = 0);
bool ready();
FileReader(const char *fn);
~FileReader();
private:
file fp;
};

View File

@ -1,85 +0,0 @@
#ifdef READER_CPP
#include "gzreader.hpp"
unsigned GZReader::size() {
return filesize;
}
//This function will allocate memory even if open() fails.
//This is needed so that when SRAM files do not exist, the
//memory for the SRAM data will be allocated still.
//The memory is flushed to 0x00 when no file is opened.
uint8_t* GZReader::read(unsigned length) {
uint8_t *data = 0;
if(length == 0) {
//read the entire file into RAM
data = new(zeromemory) uint8_t[filesize];
if(gp) gzread(gp, data, filesize);
} else if(length > filesize) {
//read the entire file into RAM, pad the rest with 0x00s
data = new(zeromemory) uint8_t[length];
if(gp) gzread(gp, data, filesize);
} else { //filesize >= length
//read only what was requested
data = new(zeromemory) uint8_t[length];
if(gp) gzread(gp, data, length);
}
return data;
}
bool GZReader::ready() {
return (gp != 0);
}
GZReader::GZReader(const char *fn) : gp(0) {
#if !defined(_WIN32)
fp = fopen(fn, "rb");
#else
fp = _wfopen(utf16_t(fn), L"rb");
#endif
if(!fp) return;
fseek(fp, 0, SEEK_END);
filesize = ftell(fp);
if(filesize < 4) {
//too small to be a valid GZ archive
fclose(fp);
fp = 0;
return;
}
fseek(fp, -4, SEEK_END);
unsigned gzsize;
gzsize = fgetc(fp);
gzsize |= fgetc(fp) << 8;
gzsize |= fgetc(fp) << 16;
gzsize |= fgetc(fp) << 24;
fseek(fp, 0, SEEK_SET);
//zlib does not support UTF-8 filenames on Windows,
//thus _wfopen() wrapper above + fileno() wrapper here.
gp = gzdopen(fileno(fp), "rb");
if(!gp) return;
if(gzdirect(gp) == false) filesize = gzsize;
if(filesize == 0) {
//archive is empty
gzclose(gp);
gp = 0;
return;
}
}
GZReader::~GZReader() {
if(gp) {
gzclose(gp);
gp = 0;
}
}
#endif //ifdef READER_CPP

View File

@ -1,16 +0,0 @@
#include "zlib/zlib.h"
class GZReader : public Reader {
private:
FILE *fp;
gzFile gp;
unsigned filesize;
public:
unsigned size();
uint8_t* read(unsigned length = 0);
bool ready();
GZReader(const char *fn);
~GZReader();
};

View File

@ -1,28 +0,0 @@
/*
Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __7Z_H
#define __7Z_H
#include "iiostrm.h"
bool decompress_lzma_7z(ISequentialInStream& in, unsigned in_size, ISequentialOutStream& out, unsigned out_size) throw ();
bool decompress_lzma_7z(const unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned out_size) throw ();
#endif

View File

@ -1,50 +0,0 @@
/*
Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "7z.h"
#include "lzmadec.h"
bool decompress_lzma_7z(ISequentialInStream& in, unsigned in_size, ISequentialOutStream& out, unsigned out_size) throw ()
{
try
{
NCompress::NLZMA::CDecoder cc;
UINT64 in_size_l = in_size;
UINT64 out_size_l = out_size;
if (cc.ReadCoderProperties(&in) != S_OK) { return(false); }
if (cc.Code(&in, &out, &in_size_l, &out_size_l) != S_OK) { return(false); }
if (out.size_get() != out_size || out.overflow_get()) { return(false); }
return(true);
}
catch (...)
{
return(false);
}
}
bool decompress_lzma_7z(const unsigned char* in_data, unsigned int in_size, unsigned char* out_data, unsigned int out_size) throw ()
{
ISequentialInStream_Array in(reinterpret_cast<const char*>(in_data), in_size);
ISequentialOutStream_Array out(reinterpret_cast<char*>(out_data), out_size);
return(decompress_lzma_7z(in, in_size, out, out_size));
}

View File

@ -1,73 +0,0 @@
#ifndef __COMPRESSION_BITCODER_H
#define __COMPRESSION_BITCODER_H
#include "rngcoder.h"
namespace NCompression {
namespace NArithmetic {
const int kNumBitModelTotalBits = 11;
const UINT32 kBitModelTotal = (1 << kNumBitModelTotalBits);
const int kNumMoveReducingBits = 2;
/////////////////////////////
// CBitModel
template <int aNumMoveBits>
class CBitModel
{
public:
UINT32 m_Probability;
void UpdateModel(UINT32 aSymbol)
{
/*
m_Probability -= (m_Probability + ((aSymbol - 1) & ((1 << aNumMoveBits) - 1))) >> aNumMoveBits;
m_Probability += (1 - aSymbol) << (kNumBitModelTotalBits - aNumMoveBits);
*/
if (aSymbol == 0)
m_Probability += (kBitModelTotal - m_Probability) >> aNumMoveBits;
else
m_Probability -= (m_Probability) >> aNumMoveBits;
}
public:
void Init() { m_Probability = kBitModelTotal / 2; }
};
template <int aNumMoveBits>
class CBitDecoder: public CBitModel<aNumMoveBits>
{
public:
UINT32 Decode(CRangeDecoder *aRangeDecoder)
{
UINT32 aNewBound = (aRangeDecoder->m_Range >> kNumBitModelTotalBits) * CBitModel<aNumMoveBits>::m_Probability;
if (aRangeDecoder->m_Code < aNewBound)
{
aRangeDecoder->m_Range = aNewBound;
CBitModel<aNumMoveBits>::m_Probability += (kBitModelTotal - CBitModel<aNumMoveBits>::m_Probability) >> aNumMoveBits;
if (aRangeDecoder->m_Range < kTopValue)
{
aRangeDecoder->m_Code = (aRangeDecoder->m_Code << 8) | aRangeDecoder->m_Stream.ReadByte();
aRangeDecoder->m_Range <<= 8;
}
return 0;
}
else
{
aRangeDecoder->m_Range -= aNewBound;
aRangeDecoder->m_Code -= aNewBound;
CBitModel<aNumMoveBits>::m_Probability -= (CBitModel<aNumMoveBits>::m_Probability) >> aNumMoveBits;
if (aRangeDecoder->m_Range < kTopValue)
{
aRangeDecoder->m_Code = (aRangeDecoder->m_Code << 8) | aRangeDecoder->m_Stream.ReadByte();
aRangeDecoder->m_Range <<= 8;
}
return 1;
}
}
};
}}
#endif

View File

@ -1,29 +0,0 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __ARICONST_H
#define __ARICONST_H
#include "aribitcd.h"
typedef NCompression::NArithmetic::CRangeDecoder CMyRangeDecoder;
template <int aNumMoveBits> class CMyBitDecoder:
public NCompression::NArithmetic::CBitDecoder<aNumMoveBits> {};
#endif

View File

@ -1,12 +0,0 @@
#ifndef __COMPRESSION_ARIPRICE_H
#define __COMPRESSION_ARIPRICE_H
namespace NCompression {
namespace NArithmetic {
const UINT32 kNumBitPriceShiftBits = 6;
const UINT32 kBitPrice = 1 << kNumBitPriceShiftBits;
}}
#endif

View File

@ -1,126 +0,0 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __BITTREECODER_H
#define __BITTREECODER_H
#include "aribitcd.h"
#include "rcdefs.h"
//////////////////////////
// CBitTreeDecoder
template <int aNumMoveBits, UINT32 m_NumBitLevels>
class CBitTreeDecoder
{
CMyBitDecoder<aNumMoveBits> m_Models[1 << m_NumBitLevels];
public:
void Init()
{
for(UINT32 i = 1; i < (1 << m_NumBitLevels); i++)
m_Models[i].Init();
}
UINT32 Decode(CMyRangeDecoder *aRangeDecoder)
{
UINT32 aModelIndex = 1;
RC_INIT_VAR
for(UINT32 aBitIndex = m_NumBitLevels; aBitIndex > 0; aBitIndex--)
{
// aModelIndex = (aModelIndex << 1) + m_Models[aModelIndex].Decode(aRangeDecoder);
RC_GETBIT(aNumMoveBits, m_Models[aModelIndex].m_Probability, aModelIndex)
}
RC_FLUSH_VAR
return aModelIndex - (1 << m_NumBitLevels);
};
};
////////////////////////////////
// CReverseBitTreeDecoder
template <int aNumMoveBits>
class CReverseBitTreeDecoder2
{
CMyBitDecoder<aNumMoveBits> *m_Models;
UINT32 m_NumBitLevels;
public:
CReverseBitTreeDecoder2(): m_Models(0) { }
~CReverseBitTreeDecoder2() { delete []m_Models; }
bool Create(UINT32 aNumBitLevels)
{
m_NumBitLevels = aNumBitLevels;
m_Models = new CMyBitDecoder<aNumMoveBits>[1 << aNumBitLevels];
return (m_Models != 0);
}
void Init()
{
UINT32 aNumModels = 1 << m_NumBitLevels;
for(UINT32 i = 1; i < aNumModels; i++)
m_Models[i].Init();
}
UINT32 Decode(CMyRangeDecoder *aRangeDecoder)
{
UINT32 aModelIndex = 1;
UINT32 aSymbol = 0;
RC_INIT_VAR
for(UINT32 aBitIndex = 0; aBitIndex < m_NumBitLevels; aBitIndex++)
{
// UINT32 aBit = m_Models[aModelIndex].Decode(aRangeDecoder);
// aModelIndex <<= 1;
// aModelIndex += aBit;
// aSymbol |= (aBit << aBitIndex);
RC_GETBIT2(aNumMoveBits, m_Models[aModelIndex].m_Probability, aModelIndex, ; , aSymbol |= (1 << aBitIndex))
}
RC_FLUSH_VAR
return aSymbol;
};
};
////////////////////////////
// CReverseBitTreeDecoder2
template <int aNumMoveBits, UINT32 m_NumBitLevels>
class CReverseBitTreeDecoder
{
CMyBitDecoder<aNumMoveBits> m_Models[1 << m_NumBitLevels];
public:
void Init()
{
for(UINT32 i = 1; i < (1 << m_NumBitLevels); i++)
m_Models[i].Init();
}
UINT32 Decode(CMyRangeDecoder *aRangeDecoder)
{
UINT32 aModelIndex = 1;
UINT32 aSymbol = 0;
RC_INIT_VAR
for(UINT32 aBitIndex = 0; aBitIndex < m_NumBitLevels; aBitIndex++)
{
// UINT32 aBit = m_Models[aModelIndex].Decode(aRangeDecoder);
// aModelIndex <<= 1;
// aModelIndex += aBit;
// aSymbol |= (aBit << aBitIndex);
RC_GETBIT2(aNumMoveBits, m_Models[aModelIndex].m_Probability, aModelIndex, ; , aSymbol |= (1 << aBitIndex))
}
RC_FLUSH_VAR
return aSymbol;
}
};
#endif

View File

@ -1,26 +0,0 @@
/*
Copyright (C) 2004-2007 NSRT Team ( http://nsrt.edgeemu.com )
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef CRC32_H
#define CRC32_H
namespace CRC32lib
{
unsigned int CRC32(const unsigned char *, size_t, register unsigned int crc32 = 0xFFFFFFFF);
}
#endif

View File

@ -1,132 +0,0 @@
/*
Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "portable.h"
#include "iiostrm.h"
#include "crc32.h"
HRESULT ISequentialInStream_Array::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
if (aSize > size)
{
aSize = size;
}
*aProcessedSize = aSize;
memcpy(aData, data, aSize);
size -= aSize;
data += aSize;
return(S_OK);
}
HRESULT ISequentialOutStream_Array::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
if (aSize > size)
{
overflow = true;
aSize = size;
}
*aProcessedSize = aSize;
memcpy(data, aData, aSize);
size -= aSize;
data += aSize;
total += aSize;
return(S_OK);
}
HRESULT ISequentialInStream_String::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
if (aSize > data.size())
{
aSize = data.size();
}
*aProcessedSize = aSize;
memcpy(aData, data.c_str(), aSize);
data.erase(0, aSize);
return(S_OK);
}
HRESULT ISequentialOutStream_String::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
*aProcessedSize = aSize;
data.append((const char *)aData, aSize);
total += aSize;
return(S_OK);
}
HRESULT ISequentialInStream_Istream::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
data.read((char *)aData, aSize);
*aProcessedSize = data.gcount();
return(S_OK);
}
HRESULT ISequentialOutStream_Ostream::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
*aProcessedSize = aSize;
data.write((char *)aData, aSize);
total += aSize;
return(S_OK);
}
HRESULT ISequentialInStreamCRC32_Array::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
ISequentialInStream_Array::Read(aData, aSize, aProcessedSize);
crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32);
return(S_OK);
}
HRESULT ISequentialOutStreamCRC32_Array::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
ISequentialOutStream_Array::Write(aData, aSize, aProcessedSize);
crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32);
return(S_OK);
}
HRESULT ISequentialInStreamCRC32_String::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
ISequentialInStream_String::Read(aData, aSize, aProcessedSize);
crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32);
return(S_OK);
}
HRESULT ISequentialOutStreamCRC32_String::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
ISequentialOutStream_String::Write(aData, aSize, aProcessedSize);
crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32);
return(S_OK);
}
HRESULT ISequentialInStreamCRC32_Istream::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
ISequentialInStream_Istream::Read(aData, aSize, aProcessedSize);
crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32);
return(S_OK);
}
HRESULT ISequentialOutStreamCRC32_Ostream::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
ISequentialOutStream_Ostream::Write(aData, aSize, aProcessedSize);
crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32);
return(S_OK);
}

View File

@ -1,210 +0,0 @@
/*
Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __IINOUTSTREAMS_H
#define __IINOUTSTREAMS_H
#include <string>
#include <fstream>
#include "portable.h"
class ISequentialInStream
{
public:
virtual HRESULT Read(void *, UINT32, UINT32 *) = 0;
virtual ~ISequentialInStream() {}
};
class ISequentialInStream_Array : public ISequentialInStream
{
const char *data;
unsigned int size;
public:
ISequentialInStream_Array(const char *Adata, unsigned Asize) : data(Adata), size(Asize) { }
HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialInStream_Array() {}
};
class ISequentialInStream_String : public ISequentialInStream
{
std::string& data;
public:
ISequentialInStream_String(std::string& Adata) : data(Adata) { }
HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialInStream_String() {}
};
class ISequentialInStream_Istream : public ISequentialInStream
{
std::istream& data;
public:
ISequentialInStream_Istream(std::istream& Adata) : data(Adata) { }
HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialInStream_Istream() {}
};
class ISequentialOutStream
{
public:
virtual bool overflow_get() const = 0;
virtual unsigned int size_get() const = 0;
virtual HRESULT Write(const void *, UINT32, UINT32 *) = 0;
virtual ~ISequentialOutStream() {}
};
class ISequentialOutStream_Array : public ISequentialOutStream
{
char *data;
unsigned int size;
bool overflow;
unsigned int total;
public:
ISequentialOutStream_Array(char *Adata, unsigned Asize) : data(Adata), size(Asize), overflow(false), total(0) { }
bool overflow_get() const { return(overflow); }
unsigned int size_get() const { return(total); }
HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialOutStream_Array() {}
};
class ISequentialOutStream_String : public ISequentialOutStream
{
std::string& data;
unsigned int total;
public:
ISequentialOutStream_String(std::string& Adata) : data(Adata), total(0) { }
bool overflow_get() const { return(false); }
unsigned int size_get() const { return(total); }
HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialOutStream_String() {}
};
class ISequentialOutStream_Ostream : public ISequentialOutStream
{
std::ostream& data;
unsigned int total;
public:
ISequentialOutStream_Ostream(std::ostream& Adata) : data(Adata), total(0) { }
bool overflow_get() const { return(false); }
unsigned int size_get() const { return(total); }
HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialOutStream_Ostream() {}
};
class ISequentialStreamCRC32
{
protected:
unsigned int crc32;
public:
ISequentialStreamCRC32() : crc32(0) {}
unsigned int crc32_get() const { return(crc32); }
virtual ~ISequentialStreamCRC32() {}
};
class ISequentialInStreamCRC32_Array : public ISequentialInStream_Array, public ISequentialStreamCRC32
{
public:
ISequentialInStreamCRC32_Array(const char *Adata, unsigned Asize) : ISequentialInStream_Array(Adata, Asize) { }
HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialInStreamCRC32_Array() {}
};
class ISequentialInStreamCRC32_String : public ISequentialInStream_String, public ISequentialStreamCRC32
{
public:
ISequentialInStreamCRC32_String(std::string& Adata) : ISequentialInStream_String(Adata) { }
HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialInStreamCRC32_String() {}
};
class ISequentialInStreamCRC32_Istream : public ISequentialInStream_Istream, public ISequentialStreamCRC32
{
public:
ISequentialInStreamCRC32_Istream(std::istream& Adata) : ISequentialInStream_Istream(Adata) { }
HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialInStreamCRC32_Istream() {}
};
class ISequentialOutStreamCRC32_Array : public ISequentialOutStream_Array, public ISequentialStreamCRC32
{
public:
ISequentialOutStreamCRC32_Array(char *Adata, unsigned Asize) : ISequentialOutStream_Array(Adata, Asize) { }
HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialOutStreamCRC32_Array() {}
};
class ISequentialOutStreamCRC32_String : public ISequentialOutStream_String, public ISequentialStreamCRC32
{
public:
ISequentialOutStreamCRC32_String(std::string& Adata) : ISequentialOutStream_String(Adata) { }
HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialOutStreamCRC32_String() {}
};
class ISequentialOutStreamCRC32_Ostream : public ISequentialOutStream_Ostream, public ISequentialStreamCRC32
{
public:
ISequentialOutStreamCRC32_Ostream(std::ostream& Adata) : ISequentialOutStream_Ostream(Adata) { }
HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialOutStreamCRC32_Ostream() {}
};
#endif

View File

@ -1,60 +0,0 @@
/*
Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "inbyte.h"
namespace NStream{
CInByte::CInByte(UINT32 aBufferSize):
m_BufferBase(0),
m_BufferSize(aBufferSize)
{
m_BufferBase = new BYTE[m_BufferSize];
}
CInByte::~CInByte()
{
delete []m_BufferBase;
}
void CInByte::Init(ISequentialInStream *aStream)
{
m_Stream = aStream;
m_ProcessedSize = 0;
m_Buffer = m_BufferBase;
m_BufferLimit = m_Buffer;
m_StreamWasExhausted = false;
}
bool CInByte::ReadBlock()
{
if (m_StreamWasExhausted)
return false;
m_ProcessedSize += (m_Buffer - m_BufferBase);
UINT32 aNumProcessedBytes;
HRESULT aResult = m_Stream->Read(m_BufferBase, m_BufferSize, &aNumProcessedBytes);
if (aResult != S_OK)
throw aResult;
m_Buffer = m_BufferBase;
m_BufferLimit = m_Buffer + aNumProcessedBytes;
m_StreamWasExhausted = (aNumProcessedBytes == 0);
return (!m_StreamWasExhausted);
}
}

View File

@ -1,76 +0,0 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __STREAM_INBYTE_H
#define __STREAM_INBYTE_H
#include "iiostrm.h"
namespace NStream {
class CInByte
{
UINT64 m_ProcessedSize;
BYTE *m_BufferBase;
UINT32 m_BufferSize;
BYTE *m_Buffer;
BYTE *m_BufferLimit;
ISequentialInStream* m_Stream;
bool m_StreamWasExhausted;
bool ReadBlock();
public:
CInByte(UINT32 aBufferSize = 0x100000);
~CInByte();
void Init(ISequentialInStream *aStream);
bool ReadByte(BYTE &aByte)
{
if(m_Buffer >= m_BufferLimit)
if(!ReadBlock())
return false;
aByte = *m_Buffer++;
return true;
}
BYTE ReadByte()
{
if(m_Buffer >= m_BufferLimit)
if(!ReadBlock())
return 0x0;
return *m_Buffer++;
}
void ReadBytes(void *aData, UINT32 aSize, UINT32 &aProcessedSize)
{
for(aProcessedSize = 0; aProcessedSize < aSize; aProcessedSize++)
if (!ReadByte(((BYTE *)aData)[aProcessedSize]))
return;
}
bool ReadBytes(void *aData, UINT32 aSize)
{
UINT32 aProcessedSize;
ReadBytes(aData, aSize, aProcessedSize);
return (aProcessedSize == aSize);
}
UINT64 GetProcessedSize() const { return m_ProcessedSize + (m_Buffer - m_BufferBase); }
};
}
#endif

Some files were not shown because too many files have changed in this diff Show More