mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-14 01:12:04 +02:00
Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
2a6a66f478 | ||
|
3c42e6caa0 | ||
|
5f96547beb |
253
src/Makefile
253
src/Makefile
@@ -1,69 +1,40 @@
|
|||||||
include lib/nall/Makefile.string
|
include lib/nall/Makefile
|
||||||
prefix = /usr/local
|
|
||||||
ui = ui_qt
|
ui = ui_qt
|
||||||
|
|
||||||
################
|
################
|
||||||
### compiler ###
|
### compiler ###
|
||||||
################
|
################
|
||||||
|
|
||||||
ifneq ($(findstring gcc,$(compiler)),) # GCC family
|
c := $(compiler)
|
||||||
flags = -O3 -fomit-frame-pointer -Ilib
|
cpp := $(subst cc,++,$(compiler))
|
||||||
# note: libco *requires* -fomit-frame-pointer on i386 arch
|
flags := -O3 -fomit-frame-pointer -Ilib
|
||||||
libcoflags := $(flags) -static
|
link := -s
|
||||||
c = $(compiler)
|
|
||||||
cpp = $(subst cc,++,$(compiler))
|
|
||||||
obj = o
|
|
||||||
rule = -c $< -o $@
|
|
||||||
link = -s
|
|
||||||
mkbin = -o$1
|
|
||||||
mkdef = -D$1
|
|
||||||
mkincpath = -I$1
|
|
||||||
mklib = -l$1
|
|
||||||
mklibpath = -L$1
|
|
||||||
|
|
||||||
# profile-guided optimization:
|
# profile-guided instrumentation:
|
||||||
# flags += -fprofile-generate
|
# flags += -fprofile-generate
|
||||||
# link += -lgcov
|
# link += -lgcov
|
||||||
# flags += -fprofile-use
|
|
||||||
else ifeq ($(compiler),cl) # Visual C++
|
|
||||||
flags = /nologo /wd4355 /wd4805 /wd4996 /Ox /GL /EHsc /Ilib
|
|
||||||
libcoflags = $(flags)
|
|
||||||
c = cl
|
|
||||||
cpp = cl
|
|
||||||
obj = obj
|
|
||||||
rule = /c $< /Fo$@
|
|
||||||
link = /link
|
|
||||||
mkbin = /Fe$1
|
|
||||||
mkdef = /D$1
|
|
||||||
mkincpath = /I$1
|
|
||||||
mklib = $1.lib
|
|
||||||
mklibpath = /L$1
|
|
||||||
else
|
|
||||||
unknown_compiler: help;
|
|
||||||
endif
|
|
||||||
|
|
||||||
##########
|
# profile-guided optimization:
|
||||||
### os ###
|
flags += -fprofile-use
|
||||||
##########
|
|
||||||
|
|
||||||
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
|
### platform ###
|
||||||
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
|
ifeq ($(platform),x)
|
||||||
mingw_link_flags += -enable-stdcall-fixup -Wl,-s -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
|
ruby := video.glx video.xv video.sdl
|
||||||
|
ruby += audio.alsa audio.openal audio.oss audio.pulseaudio audio.ao
|
||||||
|
ruby += input.sdl input.x
|
||||||
|
else ifeq ($(platform),win)
|
||||||
|
ruby := video.direct3d video.wgl video.directdraw video.gdi
|
||||||
|
ruby += audio.directsound
|
||||||
|
ruby += input.rawinput input.directinput
|
||||||
|
|
||||||
ruby = video.direct3d video.wgl video.directdraw video.gdi audio.directsound input.rawinput input.directinput
|
link += -mwindows
|
||||||
delete = $(if $(findstring i586-mingw-gcc,$(compiler)),rm -f $1,del $(subst /,\,$1))
|
# link += -mconsole
|
||||||
link += $(if $(findstring mingw,$(compiler)),$(mingw_link_flags))
|
link += -luuid -lkernel32 -luser32 -lgdi32 -lshell32
|
||||||
link += $(call mklib,uuid)
|
# statically link Qt for Windows build
|
||||||
link += $(call mklib,kernel32)
|
link += -enable-stdcall-fixup -Wl,-s -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
|
||||||
link += $(call mklib,user32)
|
|
||||||
link += $(call mklib,gdi32)
|
|
||||||
link += $(call mklib,shell32)
|
|
||||||
else
|
else
|
||||||
unknown_platform: help;
|
unknown_platform: help;
|
||||||
endif
|
endif
|
||||||
@@ -72,39 +43,39 @@ 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 cpucore scpu smp ssmp sdsp ppu bppu snes \
|
memory smemory cpu cpucore scpu smp smpcore ssmp sdsp ppu bppu \
|
||||||
sa1 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
|
||||||
|
|
||||||
######################
|
######################
|
||||||
@@ -114,136 +85,138 @@ 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/%.$(obj),$(objects))
|
objects := $(patsubst %,obj/%.o,$(objects))
|
||||||
rubydef := $(foreach c,$(subst .,_,$(call strupper,$(ruby))),$(call mkdef,$c))
|
rubydef := $(foreach c,$(subst .,_,$(call strupper,$(ruby))),-D$c)
|
||||||
|
|
||||||
#################
|
#################
|
||||||
### 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/cpucore.$(obj): cpu/core/core.cpp cpu/core/* cpu/core/disasm/*
|
obj/cpucore.o: cpu/core/core.cpp $(call rwildcard,cpu/core/)
|
||||||
obj/scpu.$(obj) : cpu/scpu/scpu.cpp cpu/scpu/* cpu/scpu/dma/* cpu/scpu/memory/* cpu/scpu/mmio/* cpu/scpu/timing/*
|
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/sa1.$(obj) : chip/sa1/sa1.cpp chip/sa1/* chip/sa1/bus/* chip/sa1/dma/* chip/sa1/memory/* chip/sa1/mmio/*
|
obj/sgb.o : chip/sgb/sgb.cpp $(call rwildcard,chip/sgb/)
|
||||||
obj/bsx.$(obj) : chip/bsx/bsx.cpp chip/bsx/*
|
obj/sa1.o : chip/sa1/sa1.cpp $(call rwildcard,chip/sa1/)
|
||||||
obj/srtc.$(obj) : chip/srtc/srtc.cpp chip/srtc/*
|
obj/bsx.o : chip/bsx/bsx.cpp chip/bsx/*
|
||||||
obj/sdd1.$(obj) : chip/sdd1/sdd1.cpp chip/sdd1/*
|
obj/srtc.o : chip/srtc/srtc.cpp chip/srtc/*
|
||||||
obj/spc7110.$(obj): chip/spc7110/spc7110.cpp chip/spc7110/*
|
obj/sdd1.o : chip/sdd1/sdd1.cpp chip/sdd1/*
|
||||||
obj/cx4.$(obj) : chip/cx4/cx4.cpp chip/cx4/*
|
obj/spc7110.o: chip/spc7110/spc7110.cpp chip/spc7110/*
|
||||||
obj/dsp1.$(obj) : chip/dsp1/dsp1.cpp chip/dsp1/*
|
obj/cx4.o : chip/cx4/cx4.cpp chip/cx4/*
|
||||||
obj/dsp2.$(obj) : chip/dsp2/dsp2.cpp chip/dsp2/*
|
obj/dsp1.o : chip/dsp1/dsp1.cpp chip/dsp1/*
|
||||||
obj/dsp3.$(obj) : chip/dsp3/dsp3.cpp chip/dsp3/*
|
obj/dsp2.o : chip/dsp2/dsp2.cpp chip/dsp2/*
|
||||||
obj/dsp4.$(obj) : chip/dsp4/dsp4.cpp chip/dsp4/*
|
obj/dsp3.o : chip/dsp3/dsp3.cpp chip/dsp3/*
|
||||||
obj/obc1.$(obj) : chip/obc1/obc1.cpp chip/obc1/*
|
obj/dsp4.o : chip/dsp4/dsp4.cpp chip/dsp4/*
|
||||||
obj/st010.$(obj) : chip/st010/st010.cpp chip/st010/*
|
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)
|
||||||
$(strip $(cpp) $(call mkbin,../bsnes) $(objects) $(link))
|
$(strip $(cpp) -o../bsnes $(objects) $(link))
|
||||||
|
|
||||||
install:
|
install:
|
||||||
install -D -m 755 ../bsnes $(DESTDIR)$(prefix)/bin/bsnes
|
install -D -m 755 ../bsnes $(DESTDIR)$(prefix)/bin/bsnes
|
||||||
@@ -251,7 +224,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)
|
||||||
@@ -270,7 +243,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)"
|
||||||
@@ -278,3 +250,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 ""
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
#define BSNES_VERSION "0.044"
|
#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
|
||||||
@@ -20,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,3 +41,4 @@ typedef uint16_t uint16;
|
|||||||
typedef uint32_t uint32;
|
typedef uint32_t uint32;
|
||||||
|
|
||||||
#include "interface.hpp"
|
#include "interface.hpp"
|
||||||
|
|
||||||
|
@@ -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;
|
|
||||||
}
|
|
@@ -1,179 +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,
|
|
||||||
SA1ROM,
|
|
||||||
SPC7110ROM,
|
|
||||||
BSCLoROM,
|
|
||||||
BSCHiROM,
|
|
||||||
BSXROM,
|
|
||||||
STROM,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum DSP1MemoryMapper {
|
|
||||||
DSP1Unmapped,
|
|
||||||
DSP1LoROM1MB,
|
|
||||||
DSP1LoROM2MB,
|
|
||||||
DSP1HiROM,
|
|
||||||
};
|
|
||||||
|
|
||||||
//properties can be read via operator(), eg "if(cartridge.loaded() == true)";
|
|
||||||
//warning: if loaded() == false, no other property is considered valid!
|
|
||||||
|
|
||||||
property_t<bool> loaded; //is a base cartridge inserted?
|
|
||||||
property_t<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;
|
|
@@ -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
|
|
@@ -1,245 +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;
|
|
||||||
string path = (snes.config.path.patch == "" ? basepath(filename) : snes.config.path.patch);
|
|
||||||
if(load_file(get_filename(filename, "ups", path), pdata, psize, CompressionInspect) == true) {
|
|
||||||
bool result = apply_patch(pdata, psize, data, size);
|
|
||||||
delete[] pdata;
|
|
||||||
patched = result;
|
|
||||||
} 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
|
|
157
src/cartridge/cartridge.cpp
Normal file
157
src/cartridge/cartridge.cpp
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
#include <../base.hpp>
|
||||||
|
|
||||||
|
#define CARTRIDGE_CPP
|
||||||
|
namespace SNES {
|
||||||
|
|
||||||
|
#include "header.cpp"
|
||||||
|
|
||||||
|
namespace memory {
|
||||||
|
MappedRAM cartrom, cartram, cartrtc;
|
||||||
|
MappedRAM bsxflash, bsxram, bsxpram;
|
||||||
|
MappedRAM stArom, stAram;
|
||||||
|
MappedRAM stBrom, stBram;
|
||||||
|
MappedRAM gbrom, gbram;
|
||||||
|
};
|
||||||
|
|
||||||
|
Cartridge cartridge;
|
||||||
|
|
||||||
|
void Cartridge::load(Mode cartridge_mode) {
|
||||||
|
cartinfo_t cartinfo;
|
||||||
|
read_header(cartinfo, memory::cartrom.data(), memory::cartrom.size());
|
||||||
|
set_cartinfo(cartinfo);
|
||||||
|
|
||||||
|
set(mode, cartridge_mode);
|
||||||
|
|
||||||
|
if(cartinfo.ram_size > 0) {
|
||||||
|
memory::cartram.map(new(zeromemory) uint8_t[cartinfo.ram_size], cartinfo.ram_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cartinfo.srtc || cartinfo.spc7110rtc) {
|
||||||
|
memory::cartrtc.map(new(zeromemory) uint8_t[20], 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mode() == ModeBsx) {
|
||||||
|
memory::bsxram.map (new(zeromemory) uint8_t[ 32 * 1024], 32 * 1024);
|
||||||
|
memory::bsxpram.map(new(zeromemory) uint8_t[512 * 1024], 512 * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mode() == ModeSufamiTurbo) {
|
||||||
|
if(memory::stArom.data()) memory::stAram.map(new(zeromemory) uint8_t[128 * 1024], 128 * 1024);
|
||||||
|
if(memory::stBrom.data()) memory::stBram.map(new(zeromemory) uint8_t[128 * 1024], 128 * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mode() == ModeSuperGameBoy) {
|
||||||
|
if(memory::gbrom.data()) memory::gbram.map(new(zeromemory) uint8_t[64 * 1024], 64 * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
memory::cartrom.write_protect(true);
|
||||||
|
memory::cartram.write_protect(false);
|
||||||
|
memory::cartrtc.write_protect(false);
|
||||||
|
memory::bsxflash.write_protect(true);
|
||||||
|
memory::bsxram.write_protect(false);
|
||||||
|
memory::bsxpram.write_protect(false);
|
||||||
|
memory::stArom.write_protect(true);
|
||||||
|
memory::stAram.write_protect(false);
|
||||||
|
memory::stBrom.write_protect(true);
|
||||||
|
memory::stBram.write_protect(false);
|
||||||
|
memory::gbrom.write_protect(true);
|
||||||
|
memory::gbram.write_protect(false);
|
||||||
|
|
||||||
|
bus.load_cart();
|
||||||
|
set(loaded, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cartridge::unload() {
|
||||||
|
memory::cartrom.reset();
|
||||||
|
memory::cartram.reset();
|
||||||
|
memory::cartrtc.reset();
|
||||||
|
memory::bsxflash.reset();
|
||||||
|
memory::bsxram.reset();
|
||||||
|
memory::bsxpram.reset();
|
||||||
|
memory::stArom.reset();
|
||||||
|
memory::stAram.reset();
|
||||||
|
memory::stBrom.reset();
|
||||||
|
memory::stBram.reset();
|
||||||
|
memory::gbrom.reset();
|
||||||
|
memory::gbram.reset();
|
||||||
|
|
||||||
|
if(loaded() == false) return;
|
||||||
|
bus.unload_cart();
|
||||||
|
set(loaded, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Cartridge::Type Cartridge::detect_image_type(uint8_t *data, unsigned size) const {
|
||||||
|
cartinfo_t info;
|
||||||
|
read_header(info, data, size);
|
||||||
|
return info.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cartridge::Cartridge() {
|
||||||
|
set(loaded, false);
|
||||||
|
unload();
|
||||||
|
}
|
||||||
|
|
||||||
|
Cartridge::~Cartridge() {
|
||||||
|
unload();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cartridge::set_cartinfo(const Cartridge::cartinfo_t &source) {
|
||||||
|
set(region, source.region);
|
||||||
|
set(mapper, source.mapper);
|
||||||
|
set(dsp1_mapper, source.dsp1_mapper);
|
||||||
|
|
||||||
|
set(has_bsx_slot, source.bsx_slot);
|
||||||
|
set(has_superfx, source.superfx);
|
||||||
|
set(has_sa1, source.sa1);
|
||||||
|
set(has_srtc, source.srtc);
|
||||||
|
set(has_sdd1, source.sdd1);
|
||||||
|
set(has_spc7110, source.spc7110);
|
||||||
|
set(has_spc7110rtc, source.spc7110rtc);
|
||||||
|
set(has_cx4, source.cx4);
|
||||||
|
set(has_dsp1, source.dsp1);
|
||||||
|
set(has_dsp2, source.dsp2);
|
||||||
|
set(has_dsp3, source.dsp3);
|
||||||
|
set(has_dsp4, source.dsp4);
|
||||||
|
set(has_obc1, source.obc1);
|
||||||
|
set(has_st010, source.st010);
|
||||||
|
set(has_st011, source.st011);
|
||||||
|
set(has_st018, source.st018);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========
|
||||||
|
//cartinfo_t
|
||||||
|
//==========
|
||||||
|
|
||||||
|
void Cartridge::cartinfo_t::reset() {
|
||||||
|
type = TypeUnknown;
|
||||||
|
mapper = LoROM;
|
||||||
|
dsp1_mapper = DSP1Unmapped;
|
||||||
|
region = NTSC;
|
||||||
|
|
||||||
|
rom_size = 0;
|
||||||
|
ram_size = 0;
|
||||||
|
|
||||||
|
bsx_slot = false;
|
||||||
|
superfx = false;
|
||||||
|
sa1 = false;
|
||||||
|
srtc = false;
|
||||||
|
sdd1 = false;
|
||||||
|
spc7110 = false;
|
||||||
|
spc7110rtc = false;
|
||||||
|
cx4 = false;
|
||||||
|
dsp1 = false;
|
||||||
|
dsp2 = false;
|
||||||
|
dsp3 = false;
|
||||||
|
dsp4 = false;
|
||||||
|
obc1 = false;
|
||||||
|
st010 = false;
|
||||||
|
st011 = false;
|
||||||
|
st018 = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cartridge::cartinfo_t::cartinfo_t() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
130
src/cartridge/cartridge.hpp
Normal file
130
src/cartridge/cartridge.hpp
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
class Cartridge : public property {
|
||||||
|
public:
|
||||||
|
enum Mode {
|
||||||
|
ModeNormal,
|
||||||
|
ModeBsxSlotted,
|
||||||
|
ModeBsx,
|
||||||
|
ModeSufamiTurbo,
|
||||||
|
ModeSuperGameBoy,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
TypeNormal,
|
||||||
|
TypeBsxSlotted,
|
||||||
|
TypeBsxBios,
|
||||||
|
TypeBsx,
|
||||||
|
TypeSufamiTurboBios,
|
||||||
|
TypeSufamiTurbo,
|
||||||
|
TypeSuperGameBoyBios,
|
||||||
|
TypeGameBoy,
|
||||||
|
TypeUnknown,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Region {
|
||||||
|
NTSC,
|
||||||
|
PAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum MemoryMapper {
|
||||||
|
LoROM,
|
||||||
|
HiROM,
|
||||||
|
ExLoROM,
|
||||||
|
ExHiROM,
|
||||||
|
SA1ROM,
|
||||||
|
SPC7110ROM,
|
||||||
|
BSCLoROM,
|
||||||
|
BSCHiROM,
|
||||||
|
BSXROM,
|
||||||
|
STROM,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum DSP1MemoryMapper {
|
||||||
|
DSP1Unmapped,
|
||||||
|
DSP1LoROM1MB,
|
||||||
|
DSP1LoROM2MB,
|
||||||
|
DSP1HiROM,
|
||||||
|
};
|
||||||
|
|
||||||
|
//properties can be read via operator(), eg "if(cartridge.loaded() == true)";
|
||||||
|
//warning: if loaded() == false, no other property is considered valid!
|
||||||
|
|
||||||
|
property_t<bool> loaded; //is a base cartridge inserted?
|
||||||
|
|
||||||
|
property_t<Mode> mode;
|
||||||
|
property_t<Region> region;
|
||||||
|
property_t<MemoryMapper> mapper;
|
||||||
|
property_t<DSP1MemoryMapper> dsp1_mapper;
|
||||||
|
|
||||||
|
property_t<bool> has_bsx_slot;
|
||||||
|
property_t<bool> has_superfx;
|
||||||
|
property_t<bool> has_sa1;
|
||||||
|
property_t<bool> has_srtc;
|
||||||
|
property_t<bool> has_sdd1;
|
||||||
|
property_t<bool> has_spc7110, has_spc7110rtc;
|
||||||
|
property_t<bool> has_cx4;
|
||||||
|
property_t<bool> has_dsp1, has_dsp2, has_dsp3, has_dsp4;
|
||||||
|
property_t<bool> has_obc1;
|
||||||
|
property_t<bool> has_st010, has_st011, has_st018;
|
||||||
|
|
||||||
|
//main interface
|
||||||
|
void load(Mode);
|
||||||
|
//void read();
|
||||||
|
//void load();
|
||||||
|
void unload();
|
||||||
|
Type detect_image_type(uint8_t *data, unsigned size) const;
|
||||||
|
|
||||||
|
Cartridge();
|
||||||
|
~Cartridge();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct cartinfo_t {
|
||||||
|
Type type;
|
||||||
|
Region region;
|
||||||
|
MemoryMapper mapper;
|
||||||
|
DSP1MemoryMapper dsp1_mapper;
|
||||||
|
unsigned rom_size, ram_size;
|
||||||
|
|
||||||
|
bool bsx_slot;
|
||||||
|
bool superfx;
|
||||||
|
bool sa1;
|
||||||
|
bool srtc;
|
||||||
|
bool sdd1;
|
||||||
|
bool spc7110, spc7110rtc;
|
||||||
|
bool cx4;
|
||||||
|
bool dsp1, dsp2, dsp3, dsp4;
|
||||||
|
bool obc1;
|
||||||
|
bool st010, st011, st018;
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
cartinfo_t();
|
||||||
|
};
|
||||||
|
|
||||||
|
enum HeaderField {
|
||||||
|
CartName = 0x00,
|
||||||
|
Mapper = 0x15,
|
||||||
|
RomType = 0x16,
|
||||||
|
RomSize = 0x17,
|
||||||
|
RamSize = 0x18,
|
||||||
|
CartRegion = 0x19,
|
||||||
|
Company = 0x1a,
|
||||||
|
Version = 0x1b,
|
||||||
|
Complement = 0x1c, //inverse checksum
|
||||||
|
Checksum = 0x1e,
|
||||||
|
ResetVector = 0x3c,
|
||||||
|
};
|
||||||
|
|
||||||
|
void read_header(cartinfo_t &info, const uint8_t *data, unsigned size) const;
|
||||||
|
unsigned find_header(const uint8_t *data, unsigned size) const;
|
||||||
|
unsigned score_header(const uint8_t *data, unsigned size, unsigned addr) const;
|
||||||
|
void set_cartinfo(const cartinfo_t&);
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace memory {
|
||||||
|
extern MappedRAM cartrom, cartram, cartrtc;
|
||||||
|
extern MappedRAM bsxflash, bsxram, bsxpram;
|
||||||
|
extern MappedRAM stArom, stAram;
|
||||||
|
extern MappedRAM stBrom, stBram;
|
||||||
|
extern MappedRAM gbrom, gbram;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Cartridge cartridge;
|
@@ -1,8 +1,35 @@
|
|||||||
#ifdef CART_CPP
|
#ifdef CARTRIDGE_CPP
|
||||||
|
|
||||||
void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size) const {
|
void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size) const {
|
||||||
info.reset();
|
info.reset();
|
||||||
unsigned index = find_header(data, size);
|
|
||||||
|
//=====================
|
||||||
|
//detect Game Boy carts
|
||||||
|
//=====================
|
||||||
|
|
||||||
|
if(size >= 0x0140) {
|
||||||
|
if(data[0x0104] == 0xce && data[0x0105] == 0xed && data[0x0106] == 0x66 && data[0x0107] == 0x66
|
||||||
|
&& data[0x0108] == 0xcc && data[0x0109] == 0x0d && data[0x010a] == 0x00 && data[0x010b] == 0x0b) {
|
||||||
|
info.type = TypeGameBoy;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned index = find_header(data, size);
|
||||||
|
const uint8 mapper = data[index + Mapper];
|
||||||
|
const uint8 rom_type = data[index + RomType];
|
||||||
|
const uint8 rom_size = data[index + RomSize];
|
||||||
|
const uint8 company = data[index + Company];
|
||||||
|
const uint8 region = data[index + CartRegion] & 0x7f;
|
||||||
|
|
||||||
|
if(data[index + RamSize] & 7) {
|
||||||
|
info.ram_size = 1024 << (data[index + RamSize] & 7);
|
||||||
|
} else {
|
||||||
|
info.ram_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//0, 1, 13 = NTSC; 2 - 12 = PAL
|
||||||
|
info.region = (region <= 1 || region >= 13) ? NTSC : PAL;
|
||||||
|
|
||||||
//=======================
|
//=======================
|
||||||
//detect BS-X flash carts
|
//detect BS-X flash carts
|
||||||
@@ -37,16 +64,19 @@ void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size
|
|||||||
return; //RAM size handled internally by load_cart_st();
|
return; //RAM size handled internally by load_cart_st();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================
|
||||||
|
//detect Super Game Boy BIOS
|
||||||
|
//==========================
|
||||||
|
|
||||||
|
if(!memcmp(data + index, "Super GAMEBOY", 13)) {
|
||||||
|
info.type = TypeSuperGameBoyBios;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//=====================
|
//=====================
|
||||||
//detect standard carts
|
//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)
|
//detect presence of BS-X flash cartridge connector (reads extended header information)
|
||||||
if(data[index - 14] == 'Z') {
|
if(data[index - 14] == 'Z') {
|
||||||
if(data[index - 11] == 'J') {
|
if(data[index - 11] == 'J') {
|
||||||
@@ -163,15 +193,6 @@ void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size
|
|||||||
if(mapper == 0x30 && rom_type == 0xf5) {
|
if(mapper == 0x30 && rom_type == 0xf5) {
|
||||||
info.st018 = true;
|
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 Cartridge::find_header(const uint8_t *data, unsigned size) const {
|
@@ -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
|
||||||
|
@@ -1,2 +0,0 @@
|
|||||||
make platform=x compiler=gcc
|
|
||||||
#make platform=x compiler=gcc enable_gzip=true enable_jma=true
|
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -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();
|
||||||
|
@@ -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"
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include "sgb/sgb.hpp"
|
||||||
#include "sa1/sa1.hpp"
|
#include "sa1/sa1.hpp"
|
||||||
#include "bsx/bsx.hpp"
|
#include "bsx/bsx.hpp"
|
||||||
#include "srtc/srtc.hpp"
|
#include "srtc/srtc.hpp"
|
||||||
|
@@ -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"
|
||||||
@@ -195,3 +198,5 @@ void Cx4::reset() {
|
|||||||
memset(ram, 0, 0x0c00);
|
memset(ram, 0, 0x0c00);
|
||||||
memset(reg, 0, 0x0100);
|
memset(reg, 0, 0x0100);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -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() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -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() {}
|
||||||
@@ -70,3 +73,6 @@ void OBC1::ram_write(unsigned addr, uint8 data) {
|
|||||||
|
|
||||||
OBC1::OBC1() {}
|
OBC1::OBC1() {}
|
||||||
OBC1::~OBC1() {}
|
OBC1::~OBC1() {}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
#ifdef SA1_CPP
|
#ifdef SA1_CPP
|
||||||
|
|
||||||
|
SA1Bus sa1bus;
|
||||||
|
|
||||||
namespace memory {
|
namespace memory {
|
||||||
VectorSelectionPage vectorsp;
|
VectorSelectionPage vectorsp;
|
||||||
StaticRAM iram(2048);
|
StaticRAM iram(2048);
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
//BS-X flash carts, when present, are mapped to 0x400000+
|
//BS-X flash carts, when present, are mapped to 0x400000+
|
||||||
Memory& SA1::mmio_access(unsigned &addr) {
|
Memory& SA1::mmio_access(unsigned &addr) {
|
||||||
if(cartridge.bsx_flash_loaded() == false) return memory::cartrom;
|
if(!memory::bsxflash.data()) return memory::cartrom;
|
||||||
if(addr < 0x400000) return memory::cartrom;
|
if(addr < 0x400000) return memory::cartrom;
|
||||||
addr &= 0x3fffff;
|
addr &= 0x3fffff;
|
||||||
return bsxflash;
|
return bsxflash;
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
#include <../base.hpp>
|
#include <../base.hpp>
|
||||||
#include <../cart/cart.hpp>
|
|
||||||
#include <../chip/bsx/bsx.hpp>
|
|
||||||
#define SA1_CPP
|
|
||||||
|
|
||||||
#include "sa1.hpp"
|
#define SA1_CPP
|
||||||
|
namespace SNES {
|
||||||
|
|
||||||
|
SA1 sa1;
|
||||||
|
|
||||||
#include "bus/bus.cpp"
|
#include "bus/bus.cpp"
|
||||||
#include "dma/dma.cpp"
|
#include "dma/dma.cpp"
|
||||||
#include "memory/memory.cpp"
|
#include "memory/memory.cpp"
|
||||||
@@ -141,7 +142,7 @@ void SA1::reset() {
|
|||||||
status.interrupt_pending = false;
|
status.interrupt_pending = false;
|
||||||
status.interrupt_vector = 0x0000;
|
status.interrupt_vector = 0x0000;
|
||||||
|
|
||||||
status.scanlines = (snes.region() == SNES::NTSC ? 262 : 312);
|
status.scanlines = (system.region() == System::NTSC ? 262 : 312);
|
||||||
status.vcounter = 0;
|
status.vcounter = 0;
|
||||||
status.hcounter = 0;
|
status.hcounter = 0;
|
||||||
|
|
||||||
@@ -312,3 +313,6 @@ void SA1::reset() {
|
|||||||
|
|
||||||
SA1::SA1() {
|
SA1::SA1() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -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.mmio[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;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
66
src/chip/sgb/sgb.cpp
Normal file
66
src/chip/sgb/sgb.cpp
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
#include <../base.hpp>
|
||||||
|
|
||||||
|
#define SGB_CPP
|
||||||
|
namespace SNES {
|
||||||
|
|
||||||
|
SuperGameBoy sgb;
|
||||||
|
|
||||||
|
void SuperGameBoy::enter() {
|
||||||
|
while(true) {
|
||||||
|
if(sgb_run) {
|
||||||
|
unsigned samples = sgb_run(samplebuffer, 16);
|
||||||
|
scheduler.addclocks_cop(samples * 10);
|
||||||
|
scheduler.sync_copcpu();
|
||||||
|
} else {
|
||||||
|
scheduler.addclocks_cop(64 * 1024 * 1024);
|
||||||
|
scheduler.sync_copcpu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SuperGameBoy::read(unsigned addr) {
|
||||||
|
addr &= 0xffff;
|
||||||
|
if(sgb_read) return sgb_read(addr);
|
||||||
|
return 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuperGameBoy::write(unsigned addr, uint8_t data) {
|
||||||
|
addr &= 0xffff;
|
||||||
|
if(sgb_write) return sgb_write(addr, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuperGameBoy::init() {
|
||||||
|
if(libsgb.open("SuperGameBoy")) {
|
||||||
|
sgb_init = libsgb.sym("sgb_init");
|
||||||
|
sgb_term = libsgb.sym("sgb_term");
|
||||||
|
sgb_power = libsgb.sym("sgb_power");
|
||||||
|
sgb_reset = libsgb.sym("sgb_reset");
|
||||||
|
sgb_read = libsgb.sym("sgb_read");
|
||||||
|
sgb_write = libsgb.sym("sgb_write");
|
||||||
|
sgb_run = libsgb.sym("sgb_run");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuperGameBoy::enable() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuperGameBoy::power() {
|
||||||
|
bus.map(Bus::MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, *this);
|
||||||
|
bus.map(Bus::MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, *this);
|
||||||
|
|
||||||
|
if(sgb_init) {
|
||||||
|
sgb_init(SGB2,
|
||||||
|
memory::gbrom.data(), memory::gbrom.size(),
|
||||||
|
memory::gbram.data(), memory::gbram.size()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sgb_power) sgb_power();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuperGameBoy::reset() {
|
||||||
|
if(sgb_reset) sgb_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
28
src/chip/sgb/sgb.hpp
Normal file
28
src/chip/sgb/sgb.hpp
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
class SuperGameBoy : public Memory {
|
||||||
|
public:
|
||||||
|
void enter();
|
||||||
|
|
||||||
|
uint8_t read(unsigned addr);
|
||||||
|
void write(unsigned addr, uint8_t data);
|
||||||
|
|
||||||
|
void init();
|
||||||
|
void enable();
|
||||||
|
void power();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
library libsgb;
|
||||||
|
uint32_t samplebuffer[4096];
|
||||||
|
|
||||||
|
enum { SGB1 = 0, SGB2 = 1 };
|
||||||
|
function<bool (bool, uint8_t*, unsigned, uint8_t*, unsigned)> sgb_init;
|
||||||
|
function<void ()> sgb_term;
|
||||||
|
function<void ()> sgb_power;
|
||||||
|
function<void ()> sgb_reset;
|
||||||
|
function<uint8_t (unsigned)> sgb_read;
|
||||||
|
function<void (unsigned, uint8_t)> sgb_write;
|
||||||
|
function<unsigned (uint32_t*, unsigned)> sgb_run;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern SuperGameBoy sgb;
|
||||||
|
|
@@ -1,8 +1,10 @@
|
|||||||
#include <../base.hpp>
|
#include <../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() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -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() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -1 +1 @@
|
|||||||
@mingw32-make platform=win compiler=mingw32-gcc clean
|
@mingw32-make clean
|
||||||
|
@@ -1 +0,0 @@
|
|||||||
make platform=x compiler=gcc clean
|
|
@@ -1,5 +1,8 @@
|
|||||||
#include <../base.hpp>
|
#include <../base.hpp>
|
||||||
|
|
||||||
|
#define CPUCORE_CPP
|
||||||
|
namespace SNES {
|
||||||
|
|
||||||
#include "opcode_algorithms.cpp"
|
#include "opcode_algorithms.cpp"
|
||||||
#include "opcode_functions.cpp"
|
#include "opcode_functions.cpp"
|
||||||
#include "opcode_tables.cpp"
|
#include "opcode_tables.cpp"
|
||||||
@@ -43,3 +46,6 @@ alwaysinline void CPUcore::op_io_cond6(uint16 addr) {
|
|||||||
CPUcore::CPUcore() {
|
CPUcore::CPUcore() {
|
||||||
initialize_opcode_table();
|
initialize_opcode_table();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef CPUCORE_CPP
|
||||||
|
|
||||||
inline void CPUcore::op_adc_b() {
|
inline void CPUcore::op_adc_b() {
|
||||||
int r;
|
int r;
|
||||||
if(regs.p.d) {
|
if(regs.p.d) {
|
||||||
@@ -363,3 +365,5 @@ inline void CPUcore::op_tsb_w() {
|
|||||||
regs.p.z = (rd.w & regs.a.w) == 0;
|
regs.p.z = (rd.w & regs.a.w) == 0;
|
||||||
rd.w |= regs.a.w;
|
rd.w |= regs.a.w;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@@ -1,37 +1,37 @@
|
|||||||
void CPUcore::initialize_opcode_table() {
|
#ifdef CPUCORE_CPP
|
||||||
for(unsigned i = 0; i < 256 * 5; i++) op_table[i] = 0;
|
|
||||||
|
|
||||||
|
void CPUcore::initialize_opcode_table() {
|
||||||
//same implementation for all processor states
|
//same implementation for all processor states
|
||||||
#define opA(id, name) \
|
#define opA(id, name) \
|
||||||
op_table[table_EM + id] = &sCPU::op_ ## name; \
|
op_table[table_EM + id] = &CPUcore::op_ ## name; \
|
||||||
op_table[table_MX + id] = &sCPU::op_ ## name; \
|
op_table[table_MX + id] = &CPUcore::op_ ## name; \
|
||||||
op_table[table_Mx + id] = &sCPU::op_ ## name; \
|
op_table[table_Mx + id] = &CPUcore::op_ ## name; \
|
||||||
op_table[table_mX + id] = &sCPU::op_ ## name; \
|
op_table[table_mX + id] = &CPUcore::op_ ## name; \
|
||||||
op_table[table_mx + id] = &sCPU::op_ ## name;
|
op_table[table_mx + id] = &CPUcore::op_ ## name;
|
||||||
|
|
||||||
//implementation changes based on E processor state
|
//implementation changes based on E processor state
|
||||||
#define opE(id, name) \
|
#define opE(id, name) \
|
||||||
op_table[table_EM + id] = &sCPU::op_ ## name ## _e; \
|
op_table[table_EM + id] = &CPUcore::op_ ## name ## _e; \
|
||||||
op_table[table_MX + id] = &sCPU::op_ ## name ## _n; \
|
op_table[table_MX + id] = &CPUcore::op_ ## name ## _n; \
|
||||||
op_table[table_Mx + id] = &sCPU::op_ ## name ## _n; \
|
op_table[table_Mx + id] = &CPUcore::op_ ## name ## _n; \
|
||||||
op_table[table_mX + id] = &sCPU::op_ ## name ## _n; \
|
op_table[table_mX + id] = &CPUcore::op_ ## name ## _n; \
|
||||||
op_table[table_mx + id] = &sCPU::op_ ## name ## _n; \
|
op_table[table_mx + id] = &CPUcore::op_ ## name ## _n; \
|
||||||
|
|
||||||
//implementation changes based on M processor state
|
//implementation changes based on M processor state
|
||||||
#define opM(id, name) \
|
#define opM(id, name) \
|
||||||
op_table[table_EM + id] = &sCPU::op_ ## name ## _b; \
|
op_table[table_EM + id] = &CPUcore::op_ ## name ## _b; \
|
||||||
op_table[table_MX + id] = &sCPU::op_ ## name ## _b; \
|
op_table[table_MX + id] = &CPUcore::op_ ## name ## _b; \
|
||||||
op_table[table_Mx + id] = &sCPU::op_ ## name ## _b; \
|
op_table[table_Mx + id] = &CPUcore::op_ ## name ## _b; \
|
||||||
op_table[table_mX + id] = &sCPU::op_ ## name ## _w; \
|
op_table[table_mX + id] = &CPUcore::op_ ## name ## _w; \
|
||||||
op_table[table_mx + id] = &sCPU::op_ ## name ## _w;
|
op_table[table_mx + id] = &CPUcore::op_ ## name ## _w;
|
||||||
|
|
||||||
//implementation changes based on X processor state
|
//implementation changes based on X processor state
|
||||||
#define opX(id, name) \
|
#define opX(id, name) \
|
||||||
op_table[table_EM + id] = &sCPU::op_ ## name ## _b; \
|
op_table[table_EM + id] = &CPUcore::op_ ## name ## _b; \
|
||||||
op_table[table_MX + id] = &sCPU::op_ ## name ## _b; \
|
op_table[table_MX + id] = &CPUcore::op_ ## name ## _b; \
|
||||||
op_table[table_Mx + id] = &sCPU::op_ ## name ## _w; \
|
op_table[table_Mx + id] = &CPUcore::op_ ## name ## _w; \
|
||||||
op_table[table_mX + id] = &sCPU::op_ ## name ## _b; \
|
op_table[table_mX + id] = &CPUcore::op_ ## name ## _b; \
|
||||||
op_table[table_mx + id] = &sCPU::op_ ## name ## _w;
|
op_table[table_mx + id] = &CPUcore::op_ ## name ## _w;
|
||||||
|
|
||||||
opE(0x00, brk) opM(0x01, ora_idpx) opE(0x02, cop) opM(0x03, ora_sr)
|
opE(0x00, brk) opM(0x01, ora_idpx) opE(0x02, cop) opM(0x03, ora_sr)
|
||||||
opM(0x04, tsb_dp) opM(0x05, ora_dp) opM(0x06, asl_dp) opM(0x07, ora_ildp)
|
opM(0x04, tsb_dp) opM(0x05, ora_dp) opM(0x06, asl_dp) opM(0x07, ora_ildp)
|
||||||
@@ -136,3 +136,6 @@ void CPUcore::update_table() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@@ -1,8 +1,10 @@
|
|||||||
#include <../base.hpp>
|
#include <../base.hpp>
|
||||||
|
|
||||||
#define CPU_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() {
|
||||||
@@ -13,3 +15,5 @@ CPU::CPU() {
|
|||||||
|
|
||||||
CPU::~CPU() {
|
CPU::~CPU() {
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -4,7 +4,6 @@ void sCPU::op_io() {
|
|||||||
status.clock_count = 6;
|
status.clock_count = 6;
|
||||||
precycle_edge();
|
precycle_edge();
|
||||||
add_clocks(6);
|
add_clocks(6);
|
||||||
if(regs.wai) scheduler.sync_cpucop();
|
|
||||||
cycle_edge();
|
cycle_edge();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12,9 +11,7 @@ uint8 sCPU::op_read(uint32 addr) {
|
|||||||
status.clock_count = 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();
|
scheduler.sync_cpucop();
|
||||||
scheduler.sync_cpuppu();
|
|
||||||
regs.mdr = bus.read(addr);
|
regs.mdr = bus.read(addr);
|
||||||
add_clocks(4);
|
add_clocks(4);
|
||||||
cycle_edge();
|
cycle_edge();
|
||||||
@@ -25,9 +22,7 @@ void sCPU::op_write(uint32 addr, uint8 data) {
|
|||||||
status.clock_count = speed(addr);
|
status.clock_count = speed(addr);
|
||||||
precycle_edge();
|
precycle_edge();
|
||||||
add_clocks(status.clock_count);
|
add_clocks(status.clock_count);
|
||||||
|
|
||||||
scheduler.sync_cpucop();
|
scheduler.sync_cpucop();
|
||||||
scheduler.sync_cpuppu();
|
|
||||||
bus.write(addr, regs.mdr = data);
|
bus.write(addr, regs.mdr = data);
|
||||||
cycle_edge();
|
cycle_edge();
|
||||||
}
|
}
|
||||||
@@ -43,3 +38,4 @@ unsigned sCPU::speed(unsigned addr) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
#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 "dma/dma.cpp"
|
#include "dma/dma.cpp"
|
||||||
@@ -94,3 +96,5 @@ sCPU::sCPU() {
|
|||||||
|
|
||||||
sCPU::~sCPU() {
|
sCPU::~sCPU() {
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -13,21 +13,24 @@ 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 and S-SMP, in case chips are not communicating
|
//forcefully sync S-CPU to other processors, in case chips are not communicating
|
||||||
if((ppu.vcounter() & 7) == 0) scheduler.sync_cpusmp();
|
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
|
||||||
@@ -44,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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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,10 +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();
|
scheduler.sync_dspsmp();
|
||||||
}
|
}
|
||||||
|
|
||||||
aDSP::aDSP() {}
|
aDSP::aDSP() {}
|
||||||
aDSP::~aDSP() {}
|
aDSP::~aDSP() {}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -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() {
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
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]
|
||||||
@@ -324,3 +324,6 @@ sDSP::sDSP() {
|
|||||||
|
|
||||||
sDSP::~sDSP() {
|
sDSP::~sDSP() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
namespace SNES {
|
||||||
#include "cheat/cheat.hpp"
|
#include "cheat/cheat.hpp"
|
||||||
|
|
||||||
#include "memory/memory.hpp"
|
#include "memory/memory.hpp"
|
||||||
@@ -7,12 +8,13 @@
|
|||||||
#include "cpu/core/core.hpp"
|
#include "cpu/core/core.hpp"
|
||||||
#include "cpu/scpu/scpu.hpp"
|
#include "cpu/scpu/scpu.hpp"
|
||||||
|
|
||||||
|
#include "smp/smp.hpp"
|
||||||
|
#include "smp/core/core.hpp"
|
||||||
|
#include "smp/ssmp/ssmp.hpp"
|
||||||
|
|
||||||
#include "ppu/ppu.hpp"
|
#include "ppu/ppu.hpp"
|
||||||
#include "ppu/bppu/bppu.hpp"
|
#include "ppu/bppu/bppu.hpp"
|
||||||
|
|
||||||
#include "smp/smp.hpp"
|
|
||||||
#include "smp/ssmp/ssmp.hpp"
|
|
||||||
|
|
||||||
#include "dsp/dsp.hpp"
|
#include "dsp/dsp.hpp"
|
||||||
#include "dsp/sdsp/sdsp.hpp"
|
#include "dsp/sdsp/sdsp.hpp"
|
||||||
|
|
||||||
@@ -22,4 +24,8 @@ extern SMPCORE smp;
|
|||||||
extern DSPCORE dsp;
|
extern DSPCORE dsp;
|
||||||
extern PPUCORE ppu;
|
extern PPUCORE ppu;
|
||||||
|
|
||||||
#include "snes/snes.hpp"
|
#include "system/system.hpp"
|
||||||
|
#include "chip/chip.hpp"
|
||||||
|
#include "cartridge/cartridge.hpp"
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
#ifdef READER_CPP
|
#ifdef READER_CPP
|
||||||
|
|
||||||
#include "filereader.hpp"
|
#include "filereader.hpp"
|
||||||
|
|
||||||
unsigned FileReader::size() {
|
unsigned FileReader::size() {
|
@@ -1,5 +1,4 @@
|
|||||||
#ifdef READER_CPP
|
#ifdef READER_CPP
|
||||||
|
|
||||||
#include "gzreader.hpp"
|
#include "gzreader.hpp"
|
||||||
|
|
||||||
unsigned GZReader::size() {
|
unsigned GZReader::size() {
|
@@ -1,4 +1,4 @@
|
|||||||
#include "zlib/zlib.h"
|
#include <zlib/zlib.h>
|
||||||
|
|
||||||
class GZReader : public Reader {
|
class GZReader : public Reader {
|
||||||
private:
|
private:
|
@@ -1,7 +1,5 @@
|
|||||||
#ifdef READER_CPP
|
#ifdef READER_CPP
|
||||||
|
|
||||||
#include "jmareader.hpp"
|
#include "jmareader.hpp"
|
||||||
#include "jma/jma.h"
|
|
||||||
|
|
||||||
unsigned JMAReader::size() {
|
unsigned JMAReader::size() {
|
||||||
return filesize;
|
return filesize;
|
@@ -1,4 +1,4 @@
|
|||||||
#include "jma/jma.h"
|
#include <libjma/jma.h>
|
||||||
|
|
||||||
class JMAReader : public Reader {
|
class JMAReader : public Reader {
|
||||||
public:
|
public:
|
@@ -1,7 +1,6 @@
|
|||||||
#include <../base.hpp>
|
#include "libreader.hpp"
|
||||||
#define READER_CPP
|
#define READER_CPP
|
||||||
|
|
||||||
#include "reader.hpp"
|
|
||||||
#include "filereader.cpp"
|
#include "filereader.cpp"
|
||||||
|
|
||||||
#if defined(GZIP_SUPPORT)
|
#if defined(GZIP_SUPPORT)
|
@@ -1,3 +1,9 @@
|
|||||||
|
#include <nall/file.hpp>
|
||||||
|
#include <nall/platform.hpp>
|
||||||
|
#include <nall/stdint.hpp>
|
||||||
|
#include <nall/string.hpp>
|
||||||
|
using namespace nall;
|
||||||
|
|
||||||
class Reader {
|
class Reader {
|
||||||
public:
|
public:
|
||||||
enum Type {
|
enum Type {
|
@@ -1,5 +1,4 @@
|
|||||||
#ifdef READER_CPP
|
#ifdef READER_CPP
|
||||||
|
|
||||||
#include "zipreader.hpp"
|
#include "zipreader.hpp"
|
||||||
|
|
||||||
unsigned ZipReader::size() {
|
unsigned ZipReader::size() {
|
@@ -1,4 +1,4 @@
|
|||||||
#include "zlib/unzip.h"
|
#include <zlib/unzip.h>
|
||||||
|
|
||||||
#define ZIP_MAX_FILE_NAME PATH_MAX
|
#define ZIP_MAX_FILE_NAME PATH_MAX
|
||||||
|
|
@@ -1,4 +1,4 @@
|
|||||||
# Makefile.string
|
# Makefile
|
||||||
# author: byuu
|
# author: byuu
|
||||||
# license: public domain
|
# license: public domain
|
||||||
|
|
||||||
@@ -10,6 +10,46 @@
|
|||||||
[space] :=
|
[space] :=
|
||||||
[space] +=
|
[space] +=
|
||||||
|
|
||||||
|
#####
|
||||||
|
# platform detection
|
||||||
|
#####
|
||||||
|
|
||||||
|
ifeq ($(platform),)
|
||||||
|
uname := $(shell uname -a)
|
||||||
|
ifeq ($(uname),)
|
||||||
|
platform := win
|
||||||
|
delete = del $(subst /,\,$1)
|
||||||
|
else ifneq ($(findstring Darwin,$(uname)),)
|
||||||
|
platform := osx
|
||||||
|
delete = rm -f $1
|
||||||
|
else
|
||||||
|
platform := x
|
||||||
|
delete = rm -f $1
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(compiler),)
|
||||||
|
compiler := gcc
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(prefix),)
|
||||||
|
prefix := /usr/local
|
||||||
|
endif
|
||||||
|
|
||||||
|
#####
|
||||||
|
# function rwildcard(directory, pattern)
|
||||||
|
#####
|
||||||
|
rwildcard = \
|
||||||
|
$(strip \
|
||||||
|
$(filter $(if $2,$2,%), \
|
||||||
|
$(foreach f, \
|
||||||
|
$(wildcard $1*), \
|
||||||
|
$(eval t = $(call rwildcard,$f/)) \
|
||||||
|
$(if $t,$t,$f) \
|
||||||
|
) \
|
||||||
|
) \
|
||||||
|
)
|
||||||
|
|
||||||
#####
|
#####
|
||||||
# function strtr(source, from, to)
|
# function strtr(source, from, to)
|
||||||
#####
|
#####
|
||||||
@@ -61,3 +101,9 @@ streq = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),,1)
|
|||||||
# function strne(source)
|
# function strne(source)
|
||||||
#####
|
#####
|
||||||
strne = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),1,)
|
strne = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),1,)
|
||||||
|
|
||||||
|
#####
|
||||||
|
# function ifhas(needle, haystack, true, false)
|
||||||
|
#####
|
||||||
|
ifhas = $(if $(findstring $1,$2),$3,$4)
|
||||||
|
|
81
src/lib/nall/dl.hpp
Normal file
81
src/lib/nall/dl.hpp
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#ifndef NALL_DL_HPP
|
||||||
|
#define NALL_DL_HPP
|
||||||
|
|
||||||
|
//dynamic linking support
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <nall/detect.hpp>
|
||||||
|
#include <nall/stdint.hpp>
|
||||||
|
#include <nall/utility.hpp>
|
||||||
|
|
||||||
|
#if defined(PLATFORM_X)
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#elif defined(PLATFORM_WIN)
|
||||||
|
#include <windows.h>
|
||||||
|
#include <nall/utf8.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
struct library : noncopyable {
|
||||||
|
bool open(const char*);
|
||||||
|
void* sym(const char*);
|
||||||
|
void close();
|
||||||
|
|
||||||
|
library() : handle(0) {}
|
||||||
|
~library() { close(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uintptr_t handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(PLATFORM_X)
|
||||||
|
inline bool library::open(const char *name) {
|
||||||
|
if(handle) close();
|
||||||
|
char *t = new char[strlen(name) + 8];
|
||||||
|
strcpy(t, "lib");
|
||||||
|
strcat(t, name);
|
||||||
|
strcat(t, ".so");
|
||||||
|
handle = (uintptr_t)dlopen(t, RTLD_LAZY);
|
||||||
|
delete[] t;
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* library::sym(const char *name) {
|
||||||
|
if(!handle) return 0;
|
||||||
|
return dlsym((void*)handle, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void library::close() {
|
||||||
|
if(!handle) return;
|
||||||
|
dlclose((void*)handle);
|
||||||
|
handle = 0;
|
||||||
|
}
|
||||||
|
#elif defined(PLATFORM_WIN)
|
||||||
|
inline bool library::open(const char *name) {
|
||||||
|
if(handle) close();
|
||||||
|
char *t = new char[strlen(name) + 8];
|
||||||
|
strcpy(t, name);
|
||||||
|
strcat(t, ".dll");
|
||||||
|
handle = (uintptr_t)LoadLibraryW(utf16_t(t));
|
||||||
|
delete[] t;
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* library::sym(const char *name) {
|
||||||
|
if(!handle) return 0;
|
||||||
|
return (void*)GetProcAddress((HMODULE)handle, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void library::close() {
|
||||||
|
if(!handle) return;
|
||||||
|
FreeLibrary((HMODULE)handle);
|
||||||
|
handle = 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
inline bool library::open(const char*) { return false; }
|
||||||
|
inline void* library::sym(const char*) { return 0; }
|
||||||
|
inline void library::close() {}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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,6 +161,7 @@ namespace nall {
|
|||||||
data.object = obj;
|
data.object = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function& operator=(void *fn) { return operator=(function(fn)); }
|
||||||
function& operator=(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); return *this; }
|
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)); }
|
||||||
};
|
};
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
|
||||||
}
|
|
@@ -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);
|
|
||||||
}
|
|
@@ -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++) {
|
|
||||||
op_list[i].name = "";
|
|
||||||
for(unsigned l = 0; l < 8; l++) {
|
|
||||||
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, ") {");
|
|
||||||
subpart.split("(", temp);
|
|
||||||
op_list[z].name = subpart[0];
|
|
||||||
part.split(", ", subpart[1]);
|
|
||||||
for(unsigned l = 0; l < part.size(); l++) {
|
|
||||||
op_list[z].arg[l] = part[l];
|
|
||||||
}
|
|
||||||
if(strend(line[i], " {") == true) break;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
output_op = "//$$\r\ncase $0: {\r\n";
|
|
||||||
line_num = i + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_line(int i) {
|
|
||||||
line[i].replace("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 = strunsigned(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], "")) {
|
|
||||||
output_op << " ";
|
|
||||||
output_op << line[i];
|
|
||||||
output_op << "\r\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
while(true) {
|
|
||||||
if(line[i][1] == ':' || line[i][2] == ':' || line[i] == "}") break;
|
|
||||||
|
|
||||||
update_line(i);
|
|
||||||
output_op << line[i];
|
|
||||||
output_op << "\r\n";
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output_op << "} break;";
|
|
||||||
line_num = i + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gen_end() {
|
|
||||||
string t;
|
|
||||||
for(unsigned i = 0; i < op_count; i++) {
|
|
||||||
t = output_op;
|
|
||||||
t.replace("$$", op_list[i].name);
|
|
||||||
t.replace("$0", op_list[i].arg[0]);
|
|
||||||
t.replace("$1", op_list[i].arg[1]);
|
|
||||||
t.replace("$2", op_list[i].arg[2]);
|
|
||||||
t.replace("$3", op_list[i].arg[3]);
|
|
||||||
t.replace("$4", op_list[i].arg[4]);
|
|
||||||
t.replace("$5", op_list[i].arg[5]);
|
|
||||||
t.replace("$6", op_list[i].arg[6]);
|
|
||||||
t.replace("$7", op_list[i].arg[7]);
|
|
||||||
fprintf(fp, "%s\r\n\r\n", (const char*)t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void generate(const char *dest, const char *src) {
|
|
||||||
data.readfile(src);
|
|
||||||
data.replace("\r\n", "\n");
|
|
||||||
line.split("\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 < line.size()) {
|
|
||||||
while(line_num < line.size() && !strcmp(line[line_num], "")) line_num++;
|
|
||||||
if(line_num >= line.size()) break;
|
|
||||||
|
|
||||||
gen_begin();
|
|
||||||
gen_op();
|
|
||||||
gen_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fp, "#endif\n");
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user