mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-26 13:39:01 +02:00
Compare commits
56 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
805398e5a8 | ||
|
7e6e3e3a69 | ||
|
16ba1d1191 | ||
|
29c871ef62 | ||
|
42f1d08c02 | ||
|
521f4f6952 | ||
|
92cfb1268a | ||
|
4d922ba17c | ||
|
3b2918791c | ||
|
b7d34a8aa3 | ||
|
8fd90cc123 | ||
|
e651beb72e | ||
|
4cbba77fc7 | ||
|
1194d3f9dc | ||
|
89a1b3d65f | ||
|
5a82cdf978 | ||
|
52be510d2b | ||
|
8b7219bdef | ||
|
926ffd9695 | ||
|
a1389a2ba3 | ||
|
5263ffb7aa | ||
|
1744bcb99c | ||
|
6362044c05 | ||
|
319b244af4 | ||
|
a3f1802845 | ||
|
4370acae2e | ||
|
5a804eac58 | ||
|
3b65b50aea | ||
|
a85ff8c437 | ||
|
a15d15047c | ||
|
f77aca7172 | ||
|
c32195cbd6 | ||
|
161366df9b | ||
|
4c43e85141 | ||
|
9da42c18c3 | ||
|
d115c7f6aa | ||
|
2efce0fd83 | ||
|
f6732133e7 | ||
|
95547f4ff8 | ||
|
4f5bdfe347 | ||
|
49b0bed1a6 | ||
|
1554170312 | ||
|
ec137d6fb9 | ||
|
aee683a475 | ||
|
cdbf07b642 | ||
|
8a857dada3 | ||
|
ab1975a6cb | ||
|
476a1c819a | ||
|
42d3f2a37f | ||
|
c58e3af1b5 | ||
|
8226e243b8 | ||
|
9ab3fa6227 | ||
|
85fa3cc968 | ||
|
d1fcddee9c | ||
|
9fd379613a | ||
|
aabf52d678 |
41
license.txt
41
license.txt
@@ -1,5 +1,5 @@
|
|||||||
bsnes (TM) Open Source Reference License
|
bsnes (TM) Reference License
|
||||||
Copyright (C) 2004 - 2007 byuu
|
Copyright (C) 2004 - 2008 byuu
|
||||||
All rights reserved
|
All rights reserved
|
||||||
|
|
||||||
1. Definitions
|
1. Definitions
|
||||||
@@ -52,12 +52,35 @@ Further, respective source code files are labeled with their correct licensing
|
|||||||
information in the header. The lack of such a header indicates said file falls
|
information in the header. The lack of such a header indicates said file falls
|
||||||
under the bsnes license.
|
under the bsnes license.
|
||||||
|
|
||||||
HQ2x Filter, author: MaxST, license: LGPL
|
HQ2x filter, author: MaxST, license: LGPL
|
||||||
JMA, author: NSRT Team, license: GPL (*)
|
JMA decompressor, author: NSRT Team, license: GPL (*)
|
||||||
libco, author: byuu, license: public domain
|
NTSC filter, author: blargg, license: LGPL
|
||||||
libui, author: byuu, license: public domain
|
zlib decompressor, license: zlib license
|
||||||
NTSC Filter, author: blargg, license: LGPL
|
|
||||||
S-DD1, author: Andreas Naive, license: public domain
|
|
||||||
zlib, license: zlib license
|
|
||||||
|
|
||||||
(*) bsnes has received an exemption from the copyright holder to use this work.
|
(*) bsnes has received an exemption from the copyright holder to use this work.
|
||||||
|
|
||||||
|
The software also includes works which have been released to the public domain,
|
||||||
|
which are not bound to any licensing agreements. Below is a complete list of all
|
||||||
|
such software.
|
||||||
|
|
||||||
|
libco, author: byuu
|
||||||
|
libui, author: byuu
|
||||||
|
OBC-1 emu, author: byuu
|
||||||
|
S-DD1 emu, author: Andreas Naive
|
||||||
|
S-RTC emu, author: byuu
|
||||||
|
|
||||||
|
Any software listed above as exemptions may be relicensed individually from
|
||||||
|
bsnes under their respective terms. However, no bsnes licensed portions can be
|
||||||
|
combined with such a derivative work.
|
||||||
|
|
||||||
|
The software also includes the work of other copyright holders, which is
|
||||||
|
licensed under the terms of the bsnes license, with permission to do so from the
|
||||||
|
respective authors. Below is a complete list of all such software.
|
||||||
|
|
||||||
|
Cx4 emu, authors: anomie, Overload, zsKnight, Nach
|
||||||
|
DSP-1 emu, authors: Overload, John Weidman, Neviksti, Andreas Naive
|
||||||
|
DSP-2 emu, author: Overload
|
||||||
|
DSP-3 emu, authors: John Weidman, Kris Bleakley, Lancer, z80 gaiden
|
||||||
|
DSP-4 emu, authors: Dreamer Nom, John Weidman, Kris Bleakley, Nach, z80 gaiden
|
||||||
|
S-DSP emu, author: blargg
|
||||||
|
ST-010 emu, authors: John Weidman, Matthew Kendora, Overload, Feather
|
||||||
|
27
readme.txt
27
readme.txt
@@ -1,5 +1,5 @@
|
|||||||
bsnes
|
bsnes
|
||||||
Version 0.023
|
Version: 0.029
|
||||||
Author: byuu
|
Author: byuu
|
||||||
|
|
||||||
--------
|
--------
|
||||||
@@ -13,17 +13,10 @@ http://byuu.org/
|
|||||||
|
|
||||||
Please see license.txt for important licensing information.
|
Please see license.txt for important licensing information.
|
||||||
|
|
||||||
--------------
|
|
||||||
Shortcut Keys:
|
|
||||||
--------------
|
|
||||||
Esc - Toggle menubar visibility
|
|
||||||
F11 - Toggle fullscreen
|
|
||||||
|
|
||||||
------------------
|
------------------
|
||||||
Known Limitations:
|
Known Limitations:
|
||||||
------------------
|
------------------
|
||||||
S-CPU
|
S-CPU
|
||||||
- Invalid DMA / HDMA transfers not fully emulated
|
|
||||||
- Multiply / Divide register delays not implemented
|
- Multiply / Divide register delays not implemented
|
||||||
|
|
||||||
S-PPU
|
S-PPU
|
||||||
@@ -66,21 +59,11 @@ Coprocessor used only by the following games:
|
|||||||
- Momotarou Densetsu Happy
|
- Momotarou Densetsu Happy
|
||||||
- Super Power League 4
|
- Super Power League 4
|
||||||
|
|
||||||
DSP-3
|
ST-011
|
||||||
Coprocessor used only by SD Gundam GX
|
SETA DSP used only by Quick-move Shogi Match with Nidan Rank-holder Morita
|
||||||
|
|
||||||
DSP-4
|
ST-018
|
||||||
Coprocessor used only by Top Gear 3000
|
SETA RISC CPU used only by Quick-move Shogi Match with Nidan Rank-holder Morita 2
|
||||||
|
|
||||||
ST010 / ST011 / ST018
|
|
||||||
SETA coprocessors used by very few games
|
|
||||||
|
|
||||||
BS-X (Broadcast Satellite)
|
|
||||||
Add-on unit sold only in Japan that played specially-made games that were
|
|
||||||
downloaded via satellite
|
|
||||||
|
|
||||||
BS-X Flashcart
|
|
||||||
Flash cartridge used by BS-X, as well as some standalone games by Asciisoft
|
|
||||||
|
|
||||||
Super Gameboy
|
Super Gameboy
|
||||||
Cartridge passthrough used for playing Gameboy games
|
Cartridge passthrough used for playing Gameboy games
|
||||||
|
439
src/Makefile
439
src/Makefile
@@ -1,311 +1,276 @@
|
|||||||
######################
|
include lib/nall/Makefile.string
|
||||||
### bsnes makefile ###
|
prefix = /usr/local
|
||||||
######################
|
|
||||||
|
|
||||||
ifeq ($(PLATFORM),)
|
################
|
||||||
_null_: help
|
### compiler ###
|
||||||
|
################
|
||||||
|
|
||||||
|
ifneq ($(findstring gcc,$(compiler)),) # GCC family
|
||||||
|
flags = -O3 -fomit-frame-pointer -Ilib
|
||||||
|
c = $(compiler) $(flags)
|
||||||
|
cpp = $(subst cc,++,$(compiler)) $(flags)
|
||||||
|
obj = o
|
||||||
|
rule = -c $< -o $@
|
||||||
|
link =
|
||||||
|
mkbin = -o$1
|
||||||
|
mkdef = -D$1
|
||||||
|
mklib = -l$1
|
||||||
|
else ifeq ($(compiler),cl) # Visual C++
|
||||||
|
flags = /nologo /wd4355 /wd4996 /O2 /EHsc /Ilib
|
||||||
|
c = cl $(flags)
|
||||||
|
cpp = cl $(flags)
|
||||||
|
obj = obj
|
||||||
|
rule = /c $< /Fo$@
|
||||||
|
link = /link
|
||||||
|
mkbin = /Fe$1
|
||||||
|
mkdef = /D$1
|
||||||
|
mklib = $1.lib
|
||||||
|
else
|
||||||
|
unknown_compiler: help;
|
||||||
endif
|
endif
|
||||||
|
|
||||||
##################################
|
##########
|
||||||
### platform-specific settings ###
|
### os ###
|
||||||
##################################
|
##########
|
||||||
|
|
||||||
ifeq ($(PLATFORM),x-gcc-lui)
|
ifeq ($(platform),x) # X11
|
||||||
OS = unix
|
ruby = video.glx video.xv video.sdl audio.openal audio.oss audio.ao input.sdl input.x
|
||||||
CC = gcc
|
link += `pkg-config --libs gtk+-2.0`
|
||||||
CFLAGS = -O3 -fomit-frame-pointer -ffast-math -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_LUI `pkg-config --cflags gtk+-2.0`
|
link += $(call mklib,Xtst)
|
||||||
AS = nasm
|
delete = rm -f $1
|
||||||
ASFLAGS = -f elf
|
else ifeq ($(platform),win) # Windows
|
||||||
LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao
|
ruby = video.direct3d video.directdraw video.gdi audio.directsound input.directinput
|
||||||
LIBCO = libco_x86
|
link += $(if $(findstring mingw,$(compiler)),-mwindows)
|
||||||
LIBUI = libui_gtk
|
link += $(call mklib,uuid)
|
||||||
|
link += $(call mklib,kernel32)
|
||||||
|
link += $(call mklib,user32)
|
||||||
|
link += $(call mklib,gdi32)
|
||||||
|
link += $(call mklib,shell32)
|
||||||
|
link += $(call mklib,winmm)
|
||||||
|
link += $(call mklib,comdlg32)
|
||||||
|
link += $(call mklib,comctl32)
|
||||||
|
delete = $(if $(findstring i586-mingw-gcc,$(compiler)),rm -f $1,del $(subst /,\,$1))
|
||||||
|
else
|
||||||
|
unknown_platform: help;
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(PLATFORM),x-gcc-lui-x64)
|
############
|
||||||
OS = unix
|
### ruby ###
|
||||||
CC = gcc
|
############
|
||||||
CFLAGS = -O3 -fomit-frame-pointer -ffast-math -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86_64 -DUI_LUI `pkg-config --cflags gtk+-2.0`
|
|
||||||
AS = yasm
|
|
||||||
ASFLAGS = -f elf64
|
|
||||||
LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao
|
|
||||||
LIBCO = libco_x86_64
|
|
||||||
LIBUI = libui_gtk
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(PLATFORM),win-visualc-lui)
|
rubyflags =
|
||||||
OS = win
|
rubyflags += $(if $(findstring .sdl,$(ruby)),`sdl-config --cflags`)
|
||||||
CC = cl
|
|
||||||
CFLAGS = /nologo /wd4996 /O2 /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI
|
|
||||||
AS = nasm
|
|
||||||
ASFLAGS = -f win32 -DWIN32
|
|
||||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
|
|
||||||
LIBCO = libco_x86
|
|
||||||
LIBUI = libui_win
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(PLATFORM),win-visualc-lui-pgi)
|
link += $(if $(findstring video.direct3d,$(ruby)),$(call mklib,d3d9))
|
||||||
OS = win
|
link += $(if $(findstring video.directdraw,$(ruby)),$(call mklib,ddraw))
|
||||||
CC = cl
|
link += $(if $(findstring video.glx,$(ruby)),$(call mklib,GL))
|
||||||
CFLAGS = /nologo /wd4996 /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI
|
link += $(if $(findstring video.xv,$(ruby)),$(call mklib,Xv))
|
||||||
AS = nasm
|
link += $(if $(findstring audio.ao,$(ruby)),$(call mklib,ao))
|
||||||
ASFLAGS = -f win32 -DWIN32
|
link += $(if $(findstring audio.directsound,$(ruby)),$(call mklib,dsound))
|
||||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
|
link += $(if $(findstring audio.openal,$(ruby)),$(if $(call streq,$(platform),x),$(call mklib,openal),$(call mklib,openal32)))
|
||||||
LINK = /link /PGD:bsnes.pgd /LTCG:PGINSTRUMENT
|
link += $(if $(findstring input.directinput,$(ruby)),$(call mklib,dinput8) $(call mklib,dxguid))
|
||||||
LIBCO = libco_x86
|
link += $(if $(findstring input.sdl,$(ruby)),`sdl-config --libs`)
|
||||||
LIBUI = libui_win
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(PLATFORM),win-visualc-lui-pgo)
|
|
||||||
OS = win
|
|
||||||
CC = cl
|
|
||||||
CFLAGS = /nologo /wd4996 /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI
|
|
||||||
AS = nasm
|
|
||||||
ASFLAGS = -f win32 -DWIN32
|
|
||||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
|
|
||||||
LINK = /link /PGD:bsnes.pgd /LTCG:PGOPTIMIZE
|
|
||||||
LIBCO = libco_x86
|
|
||||||
LIBUI = libui_win
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(PLATFORM),win-mingw-lui)
|
|
||||||
OS = win
|
|
||||||
CC = mingw32-gcc
|
|
||||||
CFLAGS = -mwindows -O3 -fomit-frame-pointer -DPLATFORM_WIN -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_LUI
|
|
||||||
AS = nasm
|
|
||||||
ASFLAGS = -f win32 -DWIN32
|
|
||||||
LIBS = -ld3d9 -lddraw -ldsound -ldinput8 -ldxguid -luuid -lkernel32 -luser32 -lgdi32 -lshell32 -lwinmm -lcomdlg32 -lcomctl32
|
|
||||||
LIBCO = libco_x86
|
|
||||||
LIBUI = libui_win
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(PLATFORM),win-mingw4-lui)
|
|
||||||
OS = win
|
|
||||||
CC = mingw32-gcc-sjlj
|
|
||||||
CFLAGS = -mwindows -O3 -fomit-frame-pointer -DPLATFORM_WIN -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_LUI
|
|
||||||
AS = nasm
|
|
||||||
ASFLAGS = -f win32 -DWIN32
|
|
||||||
LIBS = -ld3d9 -lddraw -ldsound -ldinput8 -ldxguid -luuid -lkernel32 -luser32 -lgdi32 -lshell32 -lwinmm -lcomdlg32 -lcomctl32
|
|
||||||
LIBCO = libco_x86
|
|
||||||
LIBUI = libui_win
|
|
||||||
endif
|
|
||||||
|
|
||||||
#####################################
|
|
||||||
### compiler / assembler switches ###
|
|
||||||
#####################################
|
|
||||||
|
|
||||||
ifeq ($(CC),gcc)
|
|
||||||
OUT = -obsnes
|
|
||||||
CPP = g++
|
|
||||||
OBJ = o
|
|
||||||
CARGS = -c $< -o $@
|
|
||||||
DEFINE = -D
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(CC),mingw32-gcc)
|
|
||||||
OUT = -obsnes
|
|
||||||
CPP = mingw32-g++
|
|
||||||
OBJ = o
|
|
||||||
CARGS = -c $< -o $@
|
|
||||||
DEFINE = -D
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(CC),mingw32-gcc-sjlj)
|
|
||||||
OUT = -obsnes
|
|
||||||
CPP = mingw32-g++-sjlj
|
|
||||||
OBJ = o
|
|
||||||
CARGS = -c $< -o $@
|
|
||||||
DEFINE = -D
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(CC),cl)
|
|
||||||
OUT = /Febsnes
|
|
||||||
CPP = cl
|
|
||||||
OBJ = obj
|
|
||||||
CARGS = /c $< /Fo$@
|
|
||||||
DEFINE = /D
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(AS),nasm)
|
|
||||||
ASARGS = $< -o $@
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(AS),yasm)
|
|
||||||
ASARGS = $< -o $@
|
|
||||||
endif
|
|
||||||
|
|
||||||
###################
|
|
||||||
### OS switches ###
|
|
||||||
###################
|
|
||||||
|
|
||||||
ifeq ($(OS),unix)
|
|
||||||
RM = rm -f
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(OS),win)
|
|
||||||
OUT := $(OUT).exe
|
|
||||||
RM = del
|
|
||||||
endif
|
|
||||||
|
|
||||||
####################################
|
####################################
|
||||||
### main target and dependencies ###
|
### main target and dependencies ###
|
||||||
####################################
|
####################################
|
||||||
|
|
||||||
OBJECTS = main.$(OBJ) $(LIBCO).$(OBJ) $(LIBUI).$(OBJ) \
|
objects = main libco hiro ruby libfilter string reader cart cheat \
|
||||||
libstring.$(OBJ) \
|
memory smemory cpu scpu smp ssmp bdsp ppu bppu snes \
|
||||||
reader.$(OBJ) cart.$(OBJ) cheat.$(OBJ) memory.$(OBJ) bmemory.$(OBJ) \
|
bsx srtc sdd1 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010
|
||||||
cpu.$(OBJ) scpu.$(OBJ) smp.$(OBJ) ssmp.$(OBJ) bdsp.$(OBJ) ppu.$(OBJ) \
|
|
||||||
bppu.$(OBJ) snes.$(OBJ) srtc.$(OBJ) sdd1.$(OBJ) c4.$(OBJ) dsp1.$(OBJ) \
|
|
||||||
dsp2.$(OBJ) obc1.$(OBJ)
|
|
||||||
|
|
||||||
ifeq ($(GZIP_SUPPORT),true)
|
ifeq ($(enable_gzip),true)
|
||||||
OBJECTS += adler32.$(OBJ) compress.$(OBJ) crc32.$(OBJ) deflate.$(OBJ) \
|
objects += adler32 compress crc32 deflate gzio inffast inflate inftrees ioapi trees unzip zip zutil
|
||||||
gzio.$(OBJ) inffast.$(OBJ) inflate.$(OBJ) inftrees.$(OBJ) ioapi.$(OBJ) \
|
flags += $(call mkdef,GZIP_SUPPORT)
|
||||||
trees.$(OBJ) unzip.$(OBJ) zip.$(OBJ) zutil.$(OBJ)
|
|
||||||
CFLAGS += $(DEFINE)GZIP_SUPPORT
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(JMA_SUPPORT),true)
|
ifeq ($(enable_jma),true)
|
||||||
OBJECTS += jma.$(OBJ) jcrc32.$(OBJ) lzmadec.$(OBJ) 7zlzma.$(OBJ) \
|
objects += jma jcrc32 lzmadec 7zlzma iiostrm inbyte lzma winout
|
||||||
iiostrm.$(OBJ) inbyte.$(OBJ) lzma.$(OBJ) winout.$(OBJ)
|
flags += $(call mkdef,JMA_SUPPORT)
|
||||||
CFLAGS += $(DEFINE)JMA_SUPPORT
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(OS),win)
|
objects := $(patsubst %,obj/%.$(obj),$(objects))
|
||||||
ifeq ($(CC),cl)
|
rubydef := $(foreach c,$(subst .,_,$(call strupper,$(ruby))),$(call mkdef,$c))
|
||||||
OBJECTS += bsnes.res
|
|
||||||
|
# Windows resource file
|
||||||
|
ifeq ($(platform),win)
|
||||||
|
ifeq ($(compiler),cl)
|
||||||
|
objects += obj/bsnes.res
|
||||||
|
else ifneq ($(findstring gcc,$(compiler)),)
|
||||||
|
objects += obj/bsnesrc.$(obj)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: $(OBJECTS)
|
################
|
||||||
$(CPP) $(OUT) $(CFLAGS) $(OBJECTS) $(LIBS) $(LINK)
|
### implicit ###
|
||||||
# mt -nologo -manifest bsnes.exe.manifest -outputresource:bsnes.exe;1
|
################
|
||||||
|
|
||||||
######################
|
compile = \
|
||||||
### implicit rules ###
|
$(strip \
|
||||||
######################
|
$(if $(filter %.c,$<), \
|
||||||
|
$(c) $1 $(rule), \
|
||||||
|
$(if $(filter %.cpp,$<), \
|
||||||
|
$(cpp) $1 $(rule) \
|
||||||
|
) \
|
||||||
|
) \
|
||||||
|
)
|
||||||
|
|
||||||
%.$(OBJ): $<
|
%.$(obj): $<; $(call compile)
|
||||||
$(if $(filter %.asm,$<),$(AS) $(ASFLAGS) $(ASARGS))
|
|
||||||
$(if $(filter %.c,$<),$(CC) $(CFLAGS) $(CARGS))
|
|
||||||
$(if $(filter %.cpp,$<),$(CPP) $(CFLAGS) $(CARGS))
|
|
||||||
|
|
||||||
#########################
|
all: build;
|
||||||
### platform-specific ###
|
|
||||||
#########################
|
|
||||||
main.$(OBJ): ui/main.cpp config/* ui/* ui/video/* ui/audio/* ui/input/* \
|
|
||||||
ui/lui/* ui/lui/settings/* \
|
|
||||||
ui/win/* ui/win/settings/* ui/win/debugger/*
|
|
||||||
bsnes.res : ui/bsnes.rc ; rc /r /fobsnes.res ui/bsnes.rc
|
|
||||||
|
|
||||||
#############
|
############
|
||||||
### libco ###
|
### main ###
|
||||||
#############
|
############
|
||||||
libco_x86.$(OBJ) : lib/libco_x86.asm lib/*
|
|
||||||
libco_x86_64.$(OBJ): lib/libco_x86_64.asm lib/*
|
|
||||||
|
|
||||||
#############
|
obj/main.$(obj): ui/main.cpp ui/* ui/base/* ui/loader/* ui/settings/*
|
||||||
### libui ###
|
obj/bsnes.res: ui/bsnes.rc; rc /r /foobj/bsnes.res ui/bsnes.rc
|
||||||
#############
|
obj/bsnesrc.$(obj): ui/bsnes.rc; windres ui/bsnes.rc obj/bsnesrc.$(obj)
|
||||||
libui_gtk.$(OBJ): lib/libui_gtk.cpp lib/*
|
|
||||||
libui_win.$(OBJ): lib/libui_win.cpp lib/*
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
### libraries ###
|
### libraries ###
|
||||||
#################
|
#################
|
||||||
libstring.$(OBJ): lib/libstring.cpp lib/*
|
|
||||||
|
obj/ruby.$(obj): lib/ruby/ruby.cpp lib/ruby/*
|
||||||
|
$(call compile,$(rubydef) $(rubyflags))
|
||||||
|
obj/hiro.$(obj): lib/hiro/hiro.cpp lib/hiro/* lib/hiro/gtk/* lib/hiro/win/*
|
||||||
|
$(call compile,$(if $(call streq,$(platform),x),`pkg-config --cflags gtk+-2.0`))
|
||||||
|
obj/libco.$(obj): lib/libco/libco.c lib/libco/*
|
||||||
|
$(call compile,-static)
|
||||||
|
obj/libfilter.$(obj): lib/libfilter/libfilter.cpp lib/libfilter/*
|
||||||
|
obj/string.$(obj): lib/nall/string.cpp lib/nall/*
|
||||||
|
|
||||||
#################
|
#################
|
||||||
### utilities ###
|
### utilities ###
|
||||||
#################
|
#################
|
||||||
reader.$(OBJ): reader/reader.cpp reader/*
|
|
||||||
cart.$(OBJ) : cart/cart.cpp cart/*
|
obj/reader.$(obj): reader/reader.cpp reader/*
|
||||||
cheat.$(OBJ) : cheat/cheat.cpp cheat/*
|
obj/cart.$(obj) : cart/cart.cpp cart/*
|
||||||
|
obj/cheat.$(obj) : cheat/cheat.cpp cheat/*
|
||||||
|
|
||||||
##############
|
##############
|
||||||
### memory ###
|
### memory ###
|
||||||
##############
|
##############
|
||||||
memory.$(OBJ) : memory/memory.cpp memory/*
|
|
||||||
bmemory.$(OBJ): memory/bmemory/bmemory.cpp memory/bmemory/* memory/bmemory/mapper/*
|
obj/memory.$(obj) : memory/memory.cpp memory/*
|
||||||
|
obj/smemory.$(obj): memory/smemory/smemory.cpp memory/smemory/* memory/smemory/mapper/*
|
||||||
|
|
||||||
###########
|
###########
|
||||||
### cpu ###
|
### cpu ###
|
||||||
###########
|
###########
|
||||||
cpu.$(OBJ) : cpu/cpu.cpp cpu/*
|
|
||||||
scpu.$(OBJ): cpu/scpu/scpu.cpp cpu/scpu/* cpu/scpu/core/* cpu/scpu/dma/* cpu/scpu/memory/* cpu/scpu/mmio/* cpu/scpu/timing/*
|
obj/cpu.$(obj) : cpu/cpu.cpp cpu/*
|
||||||
|
obj/scpu.$(obj): cpu/scpu/scpu.cpp cpu/scpu/* cpu/scpu/core/* cpu/scpu/dma/* cpu/scpu/memory/* cpu/scpu/mmio/* cpu/scpu/timing/*
|
||||||
|
|
||||||
###########
|
###########
|
||||||
### smp ###
|
### smp ###
|
||||||
###########
|
###########
|
||||||
smp.$(OBJ) : smp/smp.cpp smp/*
|
|
||||||
ssmp.$(OBJ): smp/ssmp/ssmp.cpp smp/ssmp/* smp/ssmp/core/* smp/ssmp/memory/* smp/ssmp/timing/*
|
obj/smp.$(obj) : smp/smp.cpp smp/*
|
||||||
|
obj/ssmp.$(obj): smp/ssmp/ssmp.cpp smp/ssmp/* smp/ssmp/core/* smp/ssmp/memory/* smp/ssmp/timing/*
|
||||||
|
|
||||||
###########
|
###########
|
||||||
### dsp ###
|
### dsp ###
|
||||||
###########
|
###########
|
||||||
adsp.$(OBJ): dsp/adsp/adsp.cpp dsp/adsp/*
|
|
||||||
bdsp.$(OBJ): dsp/bdsp/bdsp.cpp dsp/bdsp/*
|
obj/adsp.$(obj): dsp/adsp/adsp.cpp dsp/adsp/*
|
||||||
|
obj/bdsp.$(obj): dsp/bdsp/bdsp.cpp dsp/bdsp/*
|
||||||
|
|
||||||
###########
|
###########
|
||||||
### ppu ###
|
### ppu ###
|
||||||
###########
|
###########
|
||||||
ppu.$(OBJ) : ppu/ppu.cpp ppu/*
|
|
||||||
bppu.$(OBJ): ppu/bppu/bppu.cpp ppu/bppu/*
|
obj/ppu.$(obj) : ppu/ppu.cpp ppu/*
|
||||||
|
obj/bppu.$(obj): ppu/bppu/bppu.cpp ppu/bppu/*
|
||||||
|
|
||||||
############
|
############
|
||||||
### snes ###
|
### snes ###
|
||||||
############
|
############
|
||||||
snes.$(OBJ): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* snes/input/*
|
|
||||||
|
obj/snes.$(obj): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* snes/input/*
|
||||||
|
|
||||||
#####################
|
#####################
|
||||||
### special chips ###
|
### special chips ###
|
||||||
#####################
|
#####################
|
||||||
srtc.$(OBJ): chip/srtc/srtc.cpp chip/srtc/*
|
|
||||||
sdd1.$(OBJ): chip/sdd1/sdd1.cpp chip/sdd1/*
|
obj/bsx.$(obj) : chip/bsx/bsx.cpp chip/bsx/*
|
||||||
c4.$(OBJ) : chip/c4/c4.cpp chip/c4/*
|
obj/srtc.$(obj) : chip/srtc/srtc.cpp chip/srtc/*
|
||||||
dsp1.$(OBJ): chip/dsp1/dsp1.cpp chip/dsp1/*
|
obj/sdd1.$(obj) : chip/sdd1/sdd1.cpp chip/sdd1/*
|
||||||
dsp2.$(OBJ): chip/dsp2/dsp2.cpp chip/dsp2/*
|
obj/cx4.$(obj) : chip/cx4/cx4.cpp chip/cx4/*
|
||||||
obc1.$(OBJ): chip/obc1/obc1.cpp chip/obc1/*
|
obj/dsp1.$(obj) : chip/dsp1/dsp1.cpp chip/dsp1/*
|
||||||
|
obj/dsp2.$(obj) : chip/dsp2/dsp2.cpp chip/dsp2/*
|
||||||
|
obj/dsp3.$(obj) : chip/dsp3/dsp3.cpp chip/dsp3/*
|
||||||
|
obj/dsp4.$(obj) : chip/dsp4/dsp4.cpp chip/dsp4/*
|
||||||
|
obj/obc1.$(obj) : chip/obc1/obc1.cpp chip/obc1/*
|
||||||
|
obj/st010.$(obj): chip/st010/st010.cpp chip/st010/*
|
||||||
|
|
||||||
############
|
############
|
||||||
### zlib ###
|
### zlib ###
|
||||||
############
|
############
|
||||||
adler32.$(OBJ) : reader/zlib/adler32.c reader/zlib/*
|
|
||||||
compress.$(OBJ): reader/zlib/compress.c reader/zlib/*
|
obj/adler32.$(obj) : reader/zlib/adler32.c reader/zlib/*
|
||||||
crc32.$(OBJ) : reader/zlib/crc32.c reader/zlib/*
|
obj/compress.$(obj): reader/zlib/compress.c reader/zlib/*
|
||||||
deflate.$(OBJ) : reader/zlib/deflate.c reader/zlib/*
|
obj/crc32.$(obj) : reader/zlib/crc32.c reader/zlib/*
|
||||||
gzio.$(OBJ) : reader/zlib/gzio.c reader/zlib/*
|
obj/deflate.$(obj) : reader/zlib/deflate.c reader/zlib/*
|
||||||
inffast.$(OBJ) : reader/zlib/inffast.c reader/zlib/*
|
obj/gzio.$(obj) : reader/zlib/gzio.c reader/zlib/*
|
||||||
inflate.$(OBJ) : reader/zlib/inflate.c reader/zlib/*
|
obj/inffast.$(obj) : reader/zlib/inffast.c reader/zlib/*
|
||||||
inftrees.$(OBJ): reader/zlib/inftrees.c reader/zlib/*
|
obj/inflate.$(obj) : reader/zlib/inflate.c reader/zlib/*
|
||||||
ioapi.$(OBJ) : reader/zlib/ioapi.c reader/zlib/*
|
obj/inftrees.$(obj): reader/zlib/inftrees.c reader/zlib/*
|
||||||
trees.$(OBJ) : reader/zlib/trees.c reader/zlib/*
|
obj/ioapi.$(obj) : reader/zlib/ioapi.c reader/zlib/*
|
||||||
unzip.$(OBJ) : reader/zlib/unzip.c reader/zlib/*
|
obj/trees.$(obj) : reader/zlib/trees.c reader/zlib/*
|
||||||
zip.$(OBJ) : reader/zlib/zip.c reader/zlib/*
|
obj/unzip.$(obj) : reader/zlib/unzip.c reader/zlib/*
|
||||||
zutil.$(OBJ) : reader/zlib/zutil.c reader/zlib/*
|
obj/zip.$(obj) : reader/zlib/zip.c reader/zlib/*
|
||||||
|
obj/zutil.$(obj) : reader/zlib/zutil.c reader/zlib/*
|
||||||
|
|
||||||
###########
|
###########
|
||||||
### jma ###
|
### jma ###
|
||||||
###########
|
###########
|
||||||
jma.$(OBJ) : reader/jma/jma.cpp reader/jma/*
|
|
||||||
jcrc32.$(OBJ) : reader/jma/jcrc32.cpp reader/jma/*
|
|
||||||
lzmadec.$(OBJ): reader/jma/lzmadec.cpp reader/jma/*
|
|
||||||
7zlzma.$(OBJ) : reader/jma/7zlzma.cpp reader/jma/*
|
|
||||||
iiostrm.$(OBJ): reader/jma/iiostrm.cpp reader/jma/*
|
|
||||||
inbyte.$(OBJ) : reader/jma/inbyte.cpp reader/jma/*
|
|
||||||
lzma.$(OBJ) : reader/jma/lzma.cpp reader/jma/*
|
|
||||||
winout.$(OBJ) : reader/jma/winout.cpp reader/jma/*
|
|
||||||
|
|
||||||
####################
|
obj/jma.$(obj) : reader/jma/jma.cpp reader/jma/*
|
||||||
### misc targets ###
|
obj/jcrc32.$(obj) : reader/jma/jcrc32.cpp reader/jma/*
|
||||||
####################
|
obj/lzmadec.$(obj): reader/jma/lzmadec.cpp reader/jma/*
|
||||||
|
obj/7zlzma.$(obj) : reader/jma/7zlzma.cpp reader/jma/*
|
||||||
|
obj/iiostrm.$(obj): reader/jma/iiostrm.cpp reader/jma/*
|
||||||
|
obj/inbyte.$(obj) : reader/jma/inbyte.cpp reader/jma/*
|
||||||
|
obj/lzma.$(obj) : reader/jma/lzma.cpp reader/jma/*
|
||||||
|
obj/winout.$(obj) : reader/jma/winout.cpp reader/jma/*
|
||||||
|
|
||||||
|
###############
|
||||||
|
### targets ###
|
||||||
|
###############
|
||||||
|
|
||||||
|
build: $(objects)
|
||||||
|
$(strip $(cpp) $(call mkbin,../bsnes) $(objects) $(link))
|
||||||
|
|
||||||
|
install:
|
||||||
|
install -D -m 755 ../bsnes $(DESTDIR)$(prefix)/bin/bsnes
|
||||||
|
install -D -m 644 data/bsnes.png $(DESTDIR)$(prefix)/share/icons/bsnes.png
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
-@$(RM) *.$(OBJ)
|
-@$(call delete,obj/*.$(obj))
|
||||||
-@$(RM) *.res
|
-@$(call delete,*.res)
|
||||||
-@$(RM) *.pgd
|
-@$(call delete,*.pgd)
|
||||||
-@$(RM) *.pgc
|
-@$(call delete,*.pgc)
|
||||||
-@$(RM) *.ilk
|
-@$(call delete,*.ilk)
|
||||||
-@$(RM) *.pdb
|
-@$(call delete,*.pdb)
|
||||||
-@$(RM) *.manifest
|
-@$(call delete,*.manifest)
|
||||||
|
|
||||||
help:
|
help:
|
||||||
@echo Please specify which platform to compile for with PLATFORM=platform_name
|
@echo "Usage: $(MAKE) platform=(os) compiler=(cc) [options]"
|
||||||
|
@echo ""
|
||||||
|
@echo "Supported platforms:"
|
||||||
|
@echo " x - Linux / BSD (x86, x86-64)"
|
||||||
|
@echo " win - Windows (x86, x86-64)"
|
||||||
|
@echo ""
|
||||||
|
@echo "Supported compilers:"
|
||||||
|
@echo " gcc - GCC compiler"
|
||||||
|
@echo " mingw32-gcc - MinGW compiler"
|
||||||
|
@echo " i586-mingw32-gcc - MinGW cross compiler"
|
||||||
|
@echo " cl - Visual C++"
|
||||||
|
@echo ""
|
||||||
|
@echo "Available options:"
|
||||||
|
@echo " enable_gzip=[true|false] - Enable ZIP / GZ support (default=false)"
|
||||||
|
@echo " enable_jma=[true|false] - Enable JMA support (default=false)"
|
||||||
|
@echo ""
|
||||||
|
@echo "Example: $(MAKE) platform=x compiler=gcc enable_gzip=true"
|
||||||
|
@echo ""
|
||||||
|
48
src/base.h
48
src/base.h
@@ -1,42 +1,35 @@
|
|||||||
#define BSNES_VERSION "0.023"
|
#define BSNES_VERSION "0.029"
|
||||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||||
|
|
||||||
#define MEMCORE bMemBus
|
#define BUSCORE sBus
|
||||||
#define CPUCORE sCPU
|
#define CPUCORE sCPU
|
||||||
#define SMPCORE sSMP
|
#define SMPCORE sSMP
|
||||||
#define DSPCORE bDSP
|
#define DSPCORE bDSP
|
||||||
#define PPUCORE bPPU
|
#define PPUCORE bPPU
|
||||||
|
|
||||||
//#define FAVOR_ACCURACY
|
//FAST_FRAMESKIP disables calculation of RTO during frameskip
|
||||||
#define FAVOR_SPEED
|
//frameskip offers near-zero speedup if RTO is calculated
|
||||||
|
//accuracy is not affected by this define when frameskipping is off
|
||||||
|
#define FAST_FRAMESKIP
|
||||||
|
|
||||||
//game genie + pro action replay code support (~1-3% speed hit)
|
//game genie + pro action replay code support (~1-3% speed hit)
|
||||||
#define CHEAT_SYSTEM
|
#define CHEAT_SYSTEM
|
||||||
|
|
||||||
//snes core polymorphism
|
#include <nall/algorithm.hpp>
|
||||||
//(allow runtime cpu/smp/dsp/ppu/bus selection, ~10% speed hit)
|
#include <nall/array.hpp>
|
||||||
//#define POLYMORPHISM
|
#include <nall/bit.hpp>
|
||||||
|
#include <nall/config.hpp>
|
||||||
|
#include <nall/detect.hpp>
|
||||||
|
#include <nall/function.hpp>
|
||||||
|
#include <nall/new.hpp>
|
||||||
|
#include <nall/sort.hpp>
|
||||||
|
#include <nall/stdint.hpp>
|
||||||
|
#include <nall/string.hpp>
|
||||||
|
#include <nall/vector.hpp>
|
||||||
|
using namespace nall;
|
||||||
|
|
||||||
#include "lib/libbase.h"
|
#include <libco/libco.h>
|
||||||
|
#include <bbase.h>
|
||||||
#if defined(PROCESSOR_X86)
|
|
||||||
#define ARCH_LSB
|
|
||||||
#include "lib/libco_x86.h"
|
|
||||||
#elif defined(PROCESSOR_X86_64)
|
|
||||||
#define ARCH_LSB
|
|
||||||
#include "lib/libco_x86_64.h"
|
|
||||||
#elif defined(PROCESSOR_G5)
|
|
||||||
#define ARCH_MSB
|
|
||||||
#else
|
|
||||||
#error "unsupported processor"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "lib/libfunctor.h"
|
|
||||||
#include "lib/libsort.h"
|
|
||||||
#include "lib/libarray.h"
|
|
||||||
#include "lib/libvector.h"
|
|
||||||
#include "lib/libstring.h"
|
|
||||||
#include "lib/libconfig.h"
|
|
||||||
|
|
||||||
//platform-specific global functions
|
//platform-specific global functions
|
||||||
void alert(const char*, ...);
|
void alert(const char*, ...);
|
||||||
@@ -55,5 +48,4 @@ namespace source {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
//various class interfaces
|
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
|
BIN
src/bsnes.lnk
BIN
src/bsnes.lnk
Binary file not shown.
@@ -1,156 +1,133 @@
|
|||||||
#include "../base.h"
|
#include "../base.h"
|
||||||
#include "database.cpp"
|
#define CART_CPP
|
||||||
|
|
||||||
#include "cart_normal.cpp"
|
#include "cart_normal.cpp"
|
||||||
|
#include "cart_bsx.cpp"
|
||||||
|
#include "cart_bsc.cpp"
|
||||||
#include "cart_st.cpp"
|
#include "cart_st.cpp"
|
||||||
#include "cart_stdual.cpp"
|
|
||||||
|
|
||||||
#include "cart_file.cpp"
|
#include "cart_file.cpp"
|
||||||
#include "cart_header.cpp"
|
#include "cart_header.cpp"
|
||||||
|
|
||||||
|
namespace memory {
|
||||||
|
MappedRAM cartrom, cartram;
|
||||||
|
MappedRAM bscram;
|
||||||
|
MappedRAM stArom, stAram;
|
||||||
|
MappedRAM stBrom, stBram;
|
||||||
|
};
|
||||||
|
|
||||||
Cartridge cartridge;
|
Cartridge cartridge;
|
||||||
|
|
||||||
void Cartridge::load_begin(uint cart_type) {
|
Cartridge::MemoryMapper Cartridge::mapper() { return info.mapper; }
|
||||||
if(loaded() == true)return;
|
Cartridge::Region Cartridge::region() { return info.region; }
|
||||||
|
|
||||||
|
bool Cartridge::loaded() { return cart.loaded; }
|
||||||
|
|
||||||
|
void Cartridge::load_begin(CartridgeType cart_type) {
|
||||||
|
cart.rom = cart.ram = 0;
|
||||||
|
bs.ram = 0;
|
||||||
|
stA.rom = stA.ram = 0;
|
||||||
|
stB.rom = stB.ram = 0;
|
||||||
|
|
||||||
|
cart.rom_size = cart.ram_size = 0;
|
||||||
|
bs.ram_size = 0;
|
||||||
|
stA.rom_size = stA.ram_size = 0;
|
||||||
|
stB.rom_size = stB.ram_size = 0;
|
||||||
|
|
||||||
info.type = cart_type;
|
info.type = cart_type;
|
||||||
|
|
||||||
|
info.bsxbase = false;
|
||||||
|
info.bsxcart = false;
|
||||||
|
info.bsxflash = false;
|
||||||
|
info.st = false;
|
||||||
|
|
||||||
|
info.superfx = false;
|
||||||
|
info.sa1 = false;
|
||||||
info.srtc = false;
|
info.srtc = false;
|
||||||
info.sdd1 = false;
|
info.sdd1 = false;
|
||||||
info.c4 = false;
|
info.cx4 = false;
|
||||||
info.dsp1 = false;
|
info.dsp1 = false;
|
||||||
info.dsp2 = false;
|
info.dsp2 = false;
|
||||||
|
info.dsp3 = false;
|
||||||
|
info.dsp4 = false;
|
||||||
info.obc1 = false;
|
info.obc1 = false;
|
||||||
|
info.st010 = false;
|
||||||
|
info.st011 = false;
|
||||||
|
info.st018 = false;
|
||||||
|
|
||||||
info.dsp1_mapper = 0;
|
info.dsp1_mapper = DSP1Unmapped;
|
||||||
|
|
||||||
info.header_index = 0xffc0;
|
info.header_index = 0xffc0;
|
||||||
info.mapper = PCB;
|
info.mapper = LoROM;
|
||||||
strcpy(info.name, "");
|
info.name[0] = 0;
|
||||||
strcpy(info.pcb, "");
|
|
||||||
info.region = NTSC;
|
info.region = NTSC;
|
||||||
info.cart_mmio = false;
|
|
||||||
|
|
||||||
info.rom_size = 0;
|
info.rom_size = 0;
|
||||||
info.ram_size = 0;
|
info.ram_size = 0;
|
||||||
|
|
||||||
file.count = 0;
|
|
||||||
for(int i = 0; i < 8; i++) {
|
|
||||||
strcpy(file.rom_name[i], "");
|
|
||||||
strcpy(file.ram_name[i], "");
|
|
||||||
file.rom_size[i] = 0;
|
|
||||||
file.ram_size[i] = 0;
|
|
||||||
file.rom_data[i] = 0;
|
|
||||||
file.ram_data[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cartridge::load(const char *rom_fn) {
|
void Cartridge::load_end() {
|
||||||
if(!rom_fn || !*rom_fn)return;
|
memory::cartrom.map(cart.rom, cart.rom_size);
|
||||||
|
memory::cartram.map(cart.ram, cart.ram_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);
|
||||||
|
|
||||||
char fn[4096], ram_fn[4096];
|
memory::cartrom.write_protect(true);
|
||||||
strcpy(fn, rom_fn);
|
memory::cartram.write_protect(false);
|
||||||
//correct folder slashes
|
memory::bscram.write_protect(true);
|
||||||
for(int i = strlen(fn) - 1; i >= 0; i--) {
|
memory::stArom.write_protect(true);
|
||||||
if(fn[i] == '\\')fn[i] = '/';
|
memory::stAram.write_protect(false);
|
||||||
}
|
memory::stBrom.write_protect(true);
|
||||||
|
memory::stBram.write_protect(false);
|
||||||
|
|
||||||
uint i = file.count++;
|
if(fexists(get_cheat_filename(cart.fn, "cht"))) {
|
||||||
strcpy(file.rom_name[i], fn);
|
|
||||||
|
|
||||||
strcpy(fn, rom_fn);
|
|
||||||
//remove ROM extension
|
|
||||||
for(int i = strlen(fn) - 1; i >= 0; i--) {
|
|
||||||
if(fn[i] == '.') {
|
|
||||||
fn[i] = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(i == 0) {
|
|
||||||
strcpy(file.patch_name, fn);
|
|
||||||
strcat(file.patch_name, ".ups");
|
|
||||||
}
|
|
||||||
strcpy(fn, strptr(config::file_updatepath(fn, config::path.save)));
|
|
||||||
if(i == 0) {
|
|
||||||
strcpy(file.cheat_name, fn);
|
|
||||||
strcat(file.cheat_name, ".cht");
|
|
||||||
}
|
|
||||||
strcpy(file.ram_name[i], fn);
|
|
||||||
strcat(file.ram_name[i], ".");
|
|
||||||
strcat(file.ram_name[i], config::path.save_ext);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Cartridge::load_end() {
|
|
||||||
for(int i = 0; i < file.count; i++) {
|
|
||||||
load_file(file.rom_name[i], file.rom_data[i], file.rom_size[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(fexists(file.cheat_name) == true) {
|
|
||||||
cheat.clear();
|
cheat.clear();
|
||||||
cheat.load(file.cheat_name);
|
cheat.load(cheatfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(info.type) {
|
cart.loaded = true;
|
||||||
case CART_NORMAL: {
|
bus.load_cart();
|
||||||
load_rom_normal();
|
|
||||||
load_ram_normal();
|
|
||||||
} break;
|
|
||||||
case CART_ST: {
|
|
||||||
load_rom_st();
|
|
||||||
load_ram_st();
|
|
||||||
} break;
|
|
||||||
case CART_STDUAL: {
|
|
||||||
load_rom_stdual();
|
|
||||||
load_ram_stdual();
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cart_loaded = true;
|
|
||||||
r_mem->load_cart();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Cartridge::unload() {
|
bool Cartridge::unload() {
|
||||||
if(cart_loaded == false)return false;
|
if(cart.loaded == false) return false;
|
||||||
|
|
||||||
r_mem->unload_cart();
|
bus.unload_cart();
|
||||||
|
|
||||||
switch(info.type) {
|
switch(info.type) {
|
||||||
case CART_NORMAL: {
|
case CartridgeNormal: unload_cart_normal(); break;
|
||||||
save_ram_normal();
|
case CartridgeBSX: unload_cart_bsx(); break;
|
||||||
} break;
|
case CartridgeBSC: unload_cart_bsc(); break;
|
||||||
case CART_ST: {
|
case CartridgeSufamiTurbo: unload_cart_st(); break;
|
||||||
save_ram_st();
|
|
||||||
} break;
|
|
||||||
case CART_STDUAL: {
|
|
||||||
save_ram_stdual();
|
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
safe_free(rom);
|
safe_free(cart.rom);
|
||||||
safe_free(ram);
|
safe_free(cart.ram);
|
||||||
|
safe_free(bs.ram);
|
||||||
|
safe_free(stA.rom);
|
||||||
|
safe_free(stA.ram);
|
||||||
|
safe_free(stB.rom);
|
||||||
|
safe_free(stB.ram);
|
||||||
|
|
||||||
if(cheat.count() > 0 || fexists(file.cheat_name) == true) {
|
char fn[PATH_MAX];
|
||||||
cheat.save(file.cheat_name);
|
strcpy(fn, cart.fn);
|
||||||
|
modify_extension(fn, "cht");
|
||||||
|
if(cheat.count() > 0 || fexists(get_cheat_filename(cart.fn, "cht"))) {
|
||||||
|
cheat.save(cheatfn);
|
||||||
cheat.clear();
|
cheat.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
cart_loaded = false;
|
cart.loaded = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cartridge::Cartridge() {
|
Cartridge::Cartridge() {
|
||||||
load_database();
|
cart.loaded = false;
|
||||||
|
|
||||||
cart_loaded = false;
|
|
||||||
|
|
||||||
rom = 0;
|
|
||||||
ram = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Cartridge::~Cartridge() {
|
Cartridge::~Cartridge() {
|
||||||
if(cart_loaded == true) {
|
if(cart.loaded == true) unload();
|
||||||
unload();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
176
src/cart/cart.h
176
src/cart/cart.h
@@ -1,125 +1,147 @@
|
|||||||
class Cartridge {
|
class Cartridge {
|
||||||
public:
|
public:
|
||||||
|
enum CartridgeType {
|
||||||
|
CartridgeNormal,
|
||||||
|
CartridgeBSX,
|
||||||
|
CartridgeBSC,
|
||||||
|
CartridgeSufamiTurbo,
|
||||||
|
};
|
||||||
|
|
||||||
/*****
|
enum HeaderField {
|
||||||
* cart database
|
|
||||||
*****/
|
|
||||||
|
|
||||||
#include "db/db.h"
|
|
||||||
db_item dbi;
|
|
||||||
uint8 *database;
|
|
||||||
uint database_size;
|
|
||||||
uint database_blocksize;
|
|
||||||
void load_database();
|
|
||||||
bool read_database();
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
enum {
|
|
||||||
CART_NORMAL,
|
|
||||||
CART_ST,
|
|
||||||
CART_STDUAL,
|
|
||||||
};
|
|
||||||
|
|
||||||
bool cart_loaded;
|
|
||||||
|
|
||||||
uint8 rom_header[512], *rom, *ram;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
//header fields
|
|
||||||
CART_NAME = 0x00,
|
CART_NAME = 0x00,
|
||||||
MAPPER = 0x15,
|
MAPPER = 0x15,
|
||||||
ROM_TYPE = 0x16,
|
ROM_TYPE = 0x16,
|
||||||
ROM_SIZE = 0x17,
|
ROM_SIZE = 0x17,
|
||||||
RAM_SIZE = 0x18,
|
RAM_SIZE = 0x18,
|
||||||
REGION = 0x19,
|
REGION = 0x19,
|
||||||
LICENSE = 0x1a,
|
COMPANY = 0x1a,
|
||||||
VERSION = 0x1b,
|
VERSION = 0x1b,
|
||||||
ICKSUM = 0x1c,
|
ICKSUM = 0x1c,
|
||||||
CKSUM = 0x1e,
|
CKSUM = 0x1e,
|
||||||
RESL = 0x3c,
|
RESL = 0x3c,
|
||||||
RESH = 0x3d,
|
RESH = 0x3d,
|
||||||
|
};
|
||||||
|
|
||||||
//regions
|
enum Region {
|
||||||
NTSC = 0,
|
NTSC,
|
||||||
PAL = 1,
|
PAL,
|
||||||
|
};
|
||||||
|
|
||||||
//memory mappers
|
enum MemoryMapper {
|
||||||
PCB = 0x00,
|
LoROM,
|
||||||
LOROM = 0x20,
|
HiROM,
|
||||||
HIROM = 0x21,
|
ExLoROM,
|
||||||
EXLOROM = 0x22,
|
ExHiROM,
|
||||||
EXHIROM = 0x25,
|
BSXROM,
|
||||||
|
BSCLoROM,
|
||||||
|
BSCHiROM,
|
||||||
|
STROM,
|
||||||
|
};
|
||||||
|
|
||||||
//special chip memory mappers
|
enum DSP1MemoryMapper {
|
||||||
DSP1_LOROM_1MB = 1,
|
DSP1Unmapped,
|
||||||
DSP1_LOROM_2MB = 2,
|
DSP1LoROM1MB,
|
||||||
DSP1_HIROM = 3,
|
DSP1LoROM2MB,
|
||||||
};
|
DSP1HiROM,
|
||||||
|
};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint count;
|
bool loaded;
|
||||||
char cheat_name[4096], patch_name[4096];
|
char fn[PATH_MAX];
|
||||||
char rom_name[8][4096], ram_name[8][4096];
|
uint8 *rom, *ram;
|
||||||
uint rom_size[8], ram_size[8];
|
uint rom_size, ram_size;
|
||||||
uint8 *rom_data[8], *ram_data[8];
|
} cart;
|
||||||
} file;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint type;
|
char fn[PATH_MAX];
|
||||||
|
uint8 *ram;
|
||||||
|
uint ram_size;
|
||||||
|
} bs;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
char fn[PATH_MAX];
|
||||||
|
uint8 *rom, *ram;
|
||||||
|
uint rom_size, ram_size;
|
||||||
|
} stA, stB;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
CartridgeType type;
|
||||||
|
|
||||||
//cart information
|
|
||||||
uint32 crc32;
|
uint32 crc32;
|
||||||
|
char filename[PATH_MAX * 4];
|
||||||
char name[128];
|
char name[128];
|
||||||
char pcb[32];
|
|
||||||
|
|
||||||
uint region;
|
Region region;
|
||||||
uint mapper;
|
MemoryMapper mapper;
|
||||||
uint rom_size;
|
uint rom_size;
|
||||||
uint ram_size;
|
uint ram_size;
|
||||||
|
|
||||||
//set to true for games that need cart MMIO mapping (c4, dsp-n, ...),
|
bool bsxbase;
|
||||||
//for games that map outside the standard MMIO range of $2000-$5fff
|
bool bsxcart;
|
||||||
bool cart_mmio;
|
bool bsxflash;
|
||||||
|
bool st;
|
||||||
|
bool superfx;
|
||||||
|
bool sa1;
|
||||||
bool srtc;
|
bool srtc;
|
||||||
bool sdd1;
|
bool sdd1;
|
||||||
bool c4;
|
bool cx4;
|
||||||
bool dsp1;
|
bool dsp1;
|
||||||
bool dsp2;
|
bool dsp2;
|
||||||
|
bool dsp3;
|
||||||
|
bool dsp4;
|
||||||
bool obc1;
|
bool obc1;
|
||||||
|
bool st010;
|
||||||
|
bool st011;
|
||||||
|
bool st018;
|
||||||
|
|
||||||
uint dsp1_mapper;
|
DSP1MemoryMapper dsp1_mapper;
|
||||||
|
|
||||||
//HiROM / LoROM specific code
|
|
||||||
uint header_index;
|
uint header_index;
|
||||||
} info;
|
} info;
|
||||||
|
|
||||||
bool load_file(const char *fn, uint8 *&data, uint &size);
|
MemoryMapper mapper();
|
||||||
bool save_file(const char *fn, uint8 *data, uint size);
|
Region region();
|
||||||
|
|
||||||
void load_rom_normal();
|
void load_cart_normal(const char*);
|
||||||
void load_ram_normal();
|
void load_cart_bsx(const char*, const char*);
|
||||||
void save_ram_normal();
|
void load_cart_bsc(const char*, const char*);
|
||||||
|
void load_cart_st(const char*, const char*, const char*);
|
||||||
|
|
||||||
void load_rom_st();
|
void unload_cart_normal();
|
||||||
void load_ram_st();
|
void unload_cart_bsx();
|
||||||
void save_ram_st();
|
void unload_cart_bsc();
|
||||||
|
void unload_cart_st();
|
||||||
|
|
||||||
void load_rom_stdual();
|
bool loaded();
|
||||||
void load_ram_stdual();
|
void load_begin(CartridgeType);
|
||||||
void save_ram_stdual();
|
void load_end();
|
||||||
|
bool unload();
|
||||||
|
|
||||||
void find_header();
|
void find_header();
|
||||||
void read_header();
|
void read_header();
|
||||||
|
void read_extended_header();
|
||||||
|
|
||||||
bool loaded() { return cart_loaded; }
|
bool load_file(const char *fn, uint8 *&data, uint &size);
|
||||||
void load_begin(uint cart_type);
|
bool save_file(const char *fn, uint8 *data, uint size);
|
||||||
void load(const char *rom_fn);
|
char* modify_extension(char *filename, const char *extension);
|
||||||
bool load_end();
|
char* get_base_filename(char *filename);
|
||||||
bool unload();
|
char* get_path_filename(char *filename, const char *path, const char *source, const char *extension);
|
||||||
|
char* get_save_filename(const char *source, const char *extension);
|
||||||
|
char* get_cheat_filename(const char *source, const char *extension);
|
||||||
|
|
||||||
Cartridge();
|
Cartridge();
|
||||||
~Cartridge();
|
~Cartridge();
|
||||||
|
|
||||||
|
private:
|
||||||
|
char savefn[PATH_MAX];
|
||||||
|
char cheatfn[PATH_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace memory {
|
||||||
|
extern MappedRAM cartrom, cartram;
|
||||||
|
extern MappedRAM bscram;
|
||||||
|
extern MappedRAM stArom, stAram;
|
||||||
|
extern MappedRAM stBrom, stBram;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Cartridge cartridge;
|
extern Cartridge cartridge;
|
||||||
|
56
src/cart/cart_bsc.cpp
Normal file
56
src/cart/cart_bsc.cpp
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#ifdef CART_CPP
|
||||||
|
|
||||||
|
void Cartridge::load_cart_bsc(const char *base, const char *slot) {
|
||||||
|
if(!base || !*base) return;
|
||||||
|
|
||||||
|
strcpy(cart.fn, base);
|
||||||
|
strcpy(bs.fn, slot ? slot : "");
|
||||||
|
load_begin(CartridgeBSC);
|
||||||
|
|
||||||
|
uint8_t *data = 0;
|
||||||
|
unsigned size;
|
||||||
|
load_file(cart.fn, data, size);
|
||||||
|
cart.rom = data, cart.rom_size = size;
|
||||||
|
|
||||||
|
if(*bs.fn) {
|
||||||
|
if(load_file(bs.fn, data, size) == true) {
|
||||||
|
info.bsxflash = true;
|
||||||
|
bs.ram = data, bs.ram_size = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
find_header();
|
||||||
|
read_header();
|
||||||
|
|
||||||
|
info.mapper = cartridge.info.header_index == 0x7fc0 ? BSCLoROM : BSCHiROM;
|
||||||
|
info.region = NTSC;
|
||||||
|
|
||||||
|
if(info.ram_size > 0) {
|
||||||
|
cart.ram = (uint8*)malloc(cart.ram_size = info.ram_size);
|
||||||
|
memset(cart.ram, 0xff, cart.ram_size);
|
||||||
|
|
||||||
|
if(load_file(get_save_filename(cart.fn, "srm"), data, size) == true) {
|
||||||
|
memcpy(cart.ram, data, min(size, cart.ram_size));
|
||||||
|
safe_free(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
load_end();
|
||||||
|
|
||||||
|
//set base filename
|
||||||
|
strcpy(info.filename, cart.fn);
|
||||||
|
get_base_filename(info.filename);
|
||||||
|
if(*bs.fn) {
|
||||||
|
char filenameBS[PATH_MAX];
|
||||||
|
strcpy(filenameBS, bs.fn);
|
||||||
|
get_base_filename(filenameBS);
|
||||||
|
strcat(info.filename, " + ");
|
||||||
|
strcat(info.filename, filenameBS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cartridge::unload_cart_bsc() {
|
||||||
|
if(cart.ram) save_file(get_save_filename(cart.fn, "srm"), cart.ram, cart.ram_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //ifdef CART_CPP
|
52
src/cart/cart_bsx.cpp
Normal file
52
src/cart/cart_bsx.cpp
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#ifdef CART_CPP
|
||||||
|
|
||||||
|
void Cartridge::load_cart_bsx(const char *base, const char *slot) {
|
||||||
|
if(!base || !*base) return;
|
||||||
|
|
||||||
|
strcpy(cart.fn, base);
|
||||||
|
strcpy(bs.fn, slot ? slot : "");
|
||||||
|
|
||||||
|
load_begin(CartridgeBSX);
|
||||||
|
info.bsxbase = true;
|
||||||
|
info.bsxcart = true;
|
||||||
|
info.mapper = BSXROM;
|
||||||
|
info.region = NTSC;
|
||||||
|
|
||||||
|
uint8_t *data = 0;
|
||||||
|
unsigned size;
|
||||||
|
load_file(cart.fn, data, size);
|
||||||
|
cart.rom = data, cart.rom_size = size;
|
||||||
|
cart.ram = 0, cart.ram_size = 0;
|
||||||
|
|
||||||
|
memset(bsxcart.sram.handle (), 0x00, bsxcart.sram.size ());
|
||||||
|
memset(bsxcart.psram.handle(), 0x00, bsxcart.psram.size());
|
||||||
|
|
||||||
|
if(load_file(get_save_filename(cart.fn, "srm"), data, size) == true) {
|
||||||
|
memcpy(bsxcart.sram.handle (), data, min(bsxcart.sram.size (), size));
|
||||||
|
safe_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(load_file(get_save_filename(cart.fn, "psr"), data, size) == true) {
|
||||||
|
memcpy(bsxcart.psram.handle(), data, min(bsxcart.psram.size(), size));
|
||||||
|
safe_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*bs.fn) {
|
||||||
|
if(load_file(bs.fn, data, size) == true) {
|
||||||
|
info.bsxflash = true;
|
||||||
|
bs.ram = data, bs.ram_size = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
load_end();
|
||||||
|
|
||||||
|
strcpy(info.filename, !*bs.fn ? cart.fn : bs.fn);
|
||||||
|
get_base_filename(info.filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cartridge::unload_cart_bsx() {
|
||||||
|
save_file(get_save_filename(cart.fn, "srm"), bsxcart.sram.handle (), bsxcart.sram.size ());
|
||||||
|
save_file(get_save_filename(cart.fn, "psr"), bsxcart.psram.handle(), bsxcart.psram.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //ifdef CART_CPP
|
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef CART_CPP
|
||||||
|
|
||||||
#include "../reader/filereader.h"
|
#include "../reader/filereader.h"
|
||||||
|
|
||||||
#if defined(GZIP_SUPPORT)
|
#if defined(GZIP_SUPPORT)
|
||||||
@@ -9,16 +11,85 @@
|
|||||||
#include "../reader/jmareader.h"
|
#include "../reader/jmareader.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
char* Cartridge::modify_extension(char *filename, const char *extension) {
|
||||||
|
int i;
|
||||||
|
for(i = strlen(filename); i >= 0; i--) {
|
||||||
|
if(filename[i] == '.') break;
|
||||||
|
if(filename[i] == '/') break;
|
||||||
|
if(filename[i] == '\\') break;
|
||||||
|
}
|
||||||
|
if(i > 0 && filename[i] == '.') filename[i] = 0;
|
||||||
|
strcat(filename, ".");
|
||||||
|
strcat(filename, extension);
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
//remove directory information and file extension ("/foo/bar.ext" -> "bar")
|
||||||
|
char* Cartridge::get_base_filename(char *filename) {
|
||||||
|
//remove extension
|
||||||
|
for(int i = strlen(filename) - 1; i >= 0; i--) {
|
||||||
|
if(filename[i] == '.') {
|
||||||
|
filename[i] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//remove directory information
|
||||||
|
for(int i = strlen(filename) - 1; i >= 0; i--) {
|
||||||
|
if(filename[i] == '/' || filename[i] == '\\') {
|
||||||
|
i++;
|
||||||
|
char *output = filename;
|
||||||
|
while(true) {
|
||||||
|
*output++ = filename[i];
|
||||||
|
if(!filename[i]) break;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char* Cartridge::get_path_filename(char *filename, const char *path, const char *source, const char *extension) {
|
||||||
|
strcpy(filename, source);
|
||||||
|
for(char *p = filename; *p; p++) { if(*p == '\\') *p = '/'; }
|
||||||
|
modify_extension(filename, extension);
|
||||||
|
|
||||||
|
//override path with user-specified folder, if one was defined
|
||||||
|
if(path != "") {
|
||||||
|
lstring part;
|
||||||
|
split(part, "/", filename);
|
||||||
|
string fn = path;
|
||||||
|
if(strend(fn, "/") == false) strcat(fn, "/");
|
||||||
|
strcat(fn, part[count(part) - 1]);
|
||||||
|
strcpy(filename, fn);
|
||||||
|
|
||||||
|
//resolve relative path, if found
|
||||||
|
if(strbegin(fn, "./") == true) {
|
||||||
|
ltrim(fn, "./");
|
||||||
|
strcpy(filename, config::path.base);
|
||||||
|
strcat(filename, fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* Cartridge::get_save_filename(const char *source, const char *extension) {
|
||||||
|
return get_path_filename(savefn, config::path.save, source, extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* Cartridge::get_cheat_filename(const char *source, const char *extension) {
|
||||||
|
return get_path_filename(cheatfn, config::path.cheat, source, extension);
|
||||||
|
}
|
||||||
|
|
||||||
bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size) {
|
bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size) {
|
||||||
dprintf("* Loading \"%s\"...", fn);
|
dprintf("* Loading \"%s\"...", fn);
|
||||||
|
|
||||||
if(fexists(fn) == false) {
|
if(fexists(fn) == false) return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(Reader::detect(fn)) {
|
switch(Reader::detect(fn)) {
|
||||||
|
default:
|
||||||
case Reader::RF_NORMAL: {
|
case Reader::Normal: {
|
||||||
FileReader ff(fn);
|
FileReader ff(fn);
|
||||||
if(!ff.ready()) {
|
if(!ff.ready()) {
|
||||||
alert("Error loading image file (%s)!", fn);
|
alert("Error loading image file (%s)!", fn);
|
||||||
@@ -28,8 +99,8 @@ bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size) {
|
|||||||
data = ff.read();
|
data = ff.read();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
#ifdef GZIP_SUPPORT
|
#ifdef GZIP_SUPPORT
|
||||||
case Reader::RF_GZ: {
|
case Reader::GZIP: {
|
||||||
GZReader gf(fn);
|
GZReader gf(fn);
|
||||||
if(!gf.ready()) {
|
if(!gf.ready()) {
|
||||||
alert("Error loading image file (%s)!", fn);
|
alert("Error loading image file (%s)!", fn);
|
||||||
@@ -39,15 +110,15 @@ bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size) {
|
|||||||
data = gf.read();
|
data = gf.read();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Reader::RF_ZIP: {
|
case Reader::ZIP: {
|
||||||
ZipReader zf(fn);
|
ZipReader zf(fn);
|
||||||
size = zf.size();
|
size = zf.size();
|
||||||
data = zf.read();
|
data = zf.read();
|
||||||
} break;
|
} break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef JMA_SUPPORT
|
#ifdef JMA_SUPPORT
|
||||||
case Reader::RF_JMA: {
|
case Reader::JMA: {
|
||||||
try {
|
try {
|
||||||
JMAReader jf(fn);
|
JMAReader jf(fn);
|
||||||
size = jf.size();
|
size = jf.size();
|
||||||
@@ -57,16 +128,17 @@ bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Cartridge::save_file(const char *fn, uint8 *data, uint size) {
|
bool Cartridge::save_file(const char *fn, uint8 *data, uint size) {
|
||||||
FileWriter ff(fn);
|
FileWriter ff(fn);
|
||||||
if(!ff.ready())return false;
|
if(!ff.ready())return false;
|
||||||
ff.write(data, size);
|
ff.write(data, size);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif //ifdef CART_CPP
|
||||||
|
@@ -1,32 +1,48 @@
|
|||||||
|
#ifdef CART_CPP
|
||||||
|
|
||||||
void Cartridge::read_header() {
|
void Cartridge::read_header() {
|
||||||
info.srtc = false;
|
uint8 *rom = cart.rom;
|
||||||
info.sdd1 = false;
|
uint index = info.header_index;
|
||||||
info.c4 = false;
|
uint8 mapper = rom[index + MAPPER];
|
||||||
info.dsp1 = false;
|
uint8 rom_type = rom[index + ROM_TYPE];
|
||||||
info.dsp2 = false;
|
uint8 company = rom[index + COMPANY];
|
||||||
info.obc1 = false;
|
uint8 region = rom[index + REGION] & 0x7f;
|
||||||
|
|
||||||
info.dsp1_mapper = 0;
|
//detect presence of BS-X flash cartridge connector (reads extended header information)
|
||||||
|
bool has_bsxflash = false;
|
||||||
if(info.header_index == 0x7fc0 && info.rom_size >= 0x401000) {
|
if(rom[index - 14] == 'Z') {
|
||||||
info.mapper = EXLOROM;
|
if(rom[index - 11] == 'J') {
|
||||||
strcpy(info.pcb, "UNL-EXLOROM");
|
uint8 n13 = rom[index - 13];
|
||||||
} else if(info.header_index == 0x7fc0 && rom[info.header_index + MAPPER] == 0x32) {
|
if((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9')) {
|
||||||
info.mapper = EXLOROM;
|
if(company == 0x33 || (rom[index - 10] == 0x00 && rom[index - 4] == 0x00)) {
|
||||||
strcpy(info.pcb, "UNL-EXLOROM");
|
has_bsxflash = true;
|
||||||
} else if(info.header_index == 0x7fc0) {
|
}
|
||||||
info.mapper = LOROM;
|
}
|
||||||
strcpy(info.pcb, "UNL-LOROM");
|
}
|
||||||
} else if(info.header_index == 0xffc0) {
|
}
|
||||||
info.mapper = HIROM;
|
|
||||||
strcpy(info.pcb, "UNL-HIROM");
|
if(has_bsxflash == true) {
|
||||||
} else { //info.header_index == 0x40ffc0
|
info.mapper = index == 0x7fc0 ? BSCLoROM : BSCHiROM;
|
||||||
info.mapper = EXHIROM;
|
} else if(index == 0x7fc0 && cart.rom_size >= 0x401000) {
|
||||||
strcpy(info.pcb, "UNL-EXHIROM");
|
info.mapper = ExLoROM;
|
||||||
|
} else if(index == 0x7fc0 && mapper == 0x32) {
|
||||||
|
info.mapper = ExLoROM;
|
||||||
|
} else if(index == 0x7fc0) {
|
||||||
|
info.mapper = LoROM;
|
||||||
|
} else if(index == 0xffc0) {
|
||||||
|
info.mapper = HiROM;
|
||||||
|
} else { //index == 0x40ffc0
|
||||||
|
info.mapper = ExHiROM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mapper == 0x20 && (rom_type == 0x13 || rom_type == 0x14 || rom_type == 0x15 || rom_type == 0x1a)) {
|
||||||
|
info.superfx = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mapper == 0x23 && (rom_type == 0x34 || rom_type == 0x35)) {
|
||||||
|
info.sa1 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 mapper = rom[info.header_index + MAPPER];
|
|
||||||
uint8 rom_type = rom[info.header_index + ROM_TYPE];
|
|
||||||
if(mapper == 0x35 && rom_type == 0x55) {
|
if(mapper == 0x35 && rom_type == 0x55) {
|
||||||
info.srtc = true;
|
info.srtc = true;
|
||||||
}
|
}
|
||||||
@@ -36,14 +52,14 @@ uint8 rom_type = rom[info.header_index + ROM_TYPE];
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(mapper == 0x20 && rom_type == 0xf3) {
|
if(mapper == 0x20 && rom_type == 0xf3) {
|
||||||
info.c4 = true;
|
info.cx4 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) {
|
if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) {
|
||||||
info.dsp1 = true;
|
info.dsp1 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mapper == 0x30 && rom_type == 0x05) {
|
if(mapper == 0x30 && rom_type == 0x05 && company != 0xb2) {
|
||||||
info.dsp1 = true;
|
info.dsp1 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,12 +68,12 @@ uint8 rom_type = rom[info.header_index + ROM_TYPE];
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(info.dsp1 == true) {
|
if(info.dsp1 == true) {
|
||||||
if((mapper & 0x2f) == 0x20 && info.rom_size <= 0x100000) {
|
if((mapper & 0x2f) == 0x20 && cart.rom_size <= 0x100000) {
|
||||||
info.dsp1_mapper = DSP1_LOROM_1MB;
|
info.dsp1_mapper = DSP1LoROM1MB;
|
||||||
} else if((mapper & 0x2f) == 0x20) {
|
} else if((mapper & 0x2f) == 0x20) {
|
||||||
info.dsp1_mapper = DSP1_LOROM_2MB;
|
info.dsp1_mapper = DSP1LoROM2MB;
|
||||||
} else if((mapper & 0x2f) == 0x21) {
|
} else if((mapper & 0x2f) == 0x21) {
|
||||||
info.dsp1_mapper = DSP1_HIROM;
|
info.dsp1_mapper = DSP1HiROM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,11 +81,28 @@ uint8 rom_type = rom[info.header_index + ROM_TYPE];
|
|||||||
info.dsp2 = true;
|
info.dsp2 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(mapper == 0x30 && rom_type == 0x05 && company == 0xb2) {
|
||||||
|
info.dsp3 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mapper == 0x30 && rom_type == 0x03) {
|
||||||
|
info.dsp4 = true;
|
||||||
|
}
|
||||||
|
|
||||||
if(mapper == 0x30 && rom_type == 0x25) {
|
if(mapper == 0x30 && rom_type == 0x25) {
|
||||||
info.obc1 = true;
|
info.obc1 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
info.cart_mmio = info.c4 | info.dsp1 | info.dsp2 | info.obc1;
|
if(mapper == 0x30 && rom_type == 0xf6) {
|
||||||
|
//TODO: both ST010 and ST011 share the same mapper + rom_type.
|
||||||
|
//need way to determine which is which.
|
||||||
|
//for now, default to supported ST010.
|
||||||
|
info.st010 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mapper == 0x30 && rom_type == 0xf5) {
|
||||||
|
info.st018 = true;
|
||||||
|
}
|
||||||
|
|
||||||
if(rom[info.header_index + RAM_SIZE] & 7) {
|
if(rom[info.header_index + RAM_SIZE] & 7) {
|
||||||
info.ram_size = 1024 << (rom[info.header_index + RAM_SIZE] & 7);
|
info.ram_size = 1024 << (rom[info.header_index + RAM_SIZE] & 7);
|
||||||
@@ -77,49 +110,54 @@ uint8 rom_type = rom[info.header_index + ROM_TYPE];
|
|||||||
info.ram_size = 0;
|
info.ram_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//0, 1, 13 = NTSC; 2 - 12 = PAL
|
||||||
|
info.region = (region <= 1 || region >= 13) ? NTSC : PAL;
|
||||||
|
|
||||||
memcpy(&info.name, &rom[info.header_index + CART_NAME], 21);
|
memcpy(&info.name, &rom[info.header_index + CART_NAME], 21);
|
||||||
info.name[21] = 0;
|
info.name[21] = 0;
|
||||||
|
trim(info.name);
|
||||||
|
|
||||||
for(int i = 0; i < 22; i++) {
|
//convert undisplayable characters (half-width katakana, etc) to '?' characters
|
||||||
if(info.name[i] & 0x80) {
|
for(int i = 0; i < 21; i++) {
|
||||||
info.name[i] = '?';
|
if(info.name[i] & 0x80) info.name[i] = '?';
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//always display something
|
||||||
|
if(!info.name[0]) strcpy(info.name, "(untitled)");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cartridge::find_header() {
|
void Cartridge::find_header() {
|
||||||
int32 score_lo = 0,
|
int32 score_lo = 0, score_hi = 0, score_ex = 0;
|
||||||
score_hi = 0,
|
uint8_t *rom = cart.rom;
|
||||||
score_ex = 0;
|
|
||||||
|
|
||||||
if(info.rom_size < 0x010000) {
|
if(cart.rom_size < 0x010000) {
|
||||||
//cart too small to be anything but lorom
|
//cart too small to be anything but lorom
|
||||||
info.header_index = 0x007fc0;
|
info.header_index = 0x007fc0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((rom[0x7fc0 + MAPPER] & ~0x10) == 0x20)score_lo++;
|
if((rom[0x7fc0 + MAPPER] & ~0x10) == 0x20) score_lo++;
|
||||||
if((rom[0xffc0 + MAPPER] & ~0x10) == 0x21)score_hi++;
|
if((rom[0xffc0 + MAPPER] & ~0x10) == 0x21) score_hi++;
|
||||||
|
|
||||||
if(rom[0x7fc0 + ROM_TYPE] < 0x08)score_lo++;
|
if(rom[0x7fc0 + ROM_TYPE] < 0x08) score_lo++;
|
||||||
if(rom[0xffc0 + ROM_TYPE] < 0x08)score_hi++;
|
if(rom[0xffc0 + ROM_TYPE] < 0x08) score_hi++;
|
||||||
|
|
||||||
if(rom[0x7fc0 + ROM_SIZE] < 0x10)score_lo++;
|
if(rom[0x7fc0 + ROM_SIZE] < 0x10) score_lo++;
|
||||||
if(rom[0xffc0 + ROM_SIZE] < 0x10)score_hi++;
|
if(rom[0xffc0 + ROM_SIZE] < 0x10) score_hi++;
|
||||||
|
|
||||||
if(rom[0x7fc0 + RAM_SIZE] < 0x08)score_lo++;
|
if(rom[0x7fc0 + RAM_SIZE] < 0x08) score_lo++;
|
||||||
if(rom[0xffc0 + RAM_SIZE] < 0x08)score_hi++;
|
if(rom[0xffc0 + RAM_SIZE] < 0x08) score_hi++;
|
||||||
|
|
||||||
if(rom[0x7fc0 + REGION] < 14)score_lo++;
|
if(rom[0x7fc0 + REGION] < 14) score_lo++;
|
||||||
if(rom[0xffc0 + REGION] < 14)score_hi++;
|
if(rom[0xffc0 + REGION] < 14) score_hi++;
|
||||||
|
|
||||||
if(rom[0x7fc0 + LICENSE] < 3)score_lo++;
|
if(rom[0x7fc0 + COMPANY] < 3) score_lo++;
|
||||||
if(rom[0xffc0 + LICENSE] < 3)score_hi++;
|
if(rom[0xffc0 + COMPANY] < 3) score_hi++;
|
||||||
|
|
||||||
if(rom[0x7fc0 + RESH] & 0x80)score_lo += 2;
|
if(rom[0x7fc0 + RESH] & 0x80) score_lo += 2;
|
||||||
if(rom[0xffc0 + RESH] & 0x80)score_hi += 2;
|
if(rom[0xffc0 + RESH] & 0x80) score_hi += 2;
|
||||||
|
|
||||||
uint16 cksum, icksum;
|
uint16 cksum, icksum;
|
||||||
cksum = rom[0x7fc0 + CKSUM] | (rom[0x7fc0 + CKSUM + 1] << 8);
|
cksum = rom[0x7fc0 + CKSUM] | (rom[0x7fc0 + CKSUM + 1] << 8);
|
||||||
icksum = rom[0x7fc0 + ICKSUM] | (rom[0x7fc0 + ICKSUM + 1] << 8);
|
icksum = rom[0x7fc0 + ICKSUM] | (rom[0x7fc0 + ICKSUM + 1] << 8);
|
||||||
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
|
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
|
||||||
@@ -132,10 +170,10 @@ uint16 cksum, icksum;
|
|||||||
score_hi += 8;
|
score_hi += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(info.rom_size < 0x401000) {
|
if(cart.rom_size < 0x401000) {
|
||||||
score_ex = 0;
|
score_ex = 0;
|
||||||
} else {
|
} else {
|
||||||
if(rom[0x7fc0 + MAPPER] == 0x32)score_lo++;
|
if(rom[0x7fc0 + MAPPER] == 0x32) score_lo++;
|
||||||
else score_ex += 16;
|
else score_ex += 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,3 +185,5 @@ uint16 cksum, icksum;
|
|||||||
info.header_index = 0x40ffc0;
|
info.header_index = 0x40ffc0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif //ifdef CART_CPP
|
||||||
|
@@ -1,66 +1,49 @@
|
|||||||
void Cartridge::load_rom_normal() {
|
#ifdef CART_CPP
|
||||||
uint size = 0;
|
|
||||||
for(int i = 0; i < file.count; i++) {
|
|
||||||
size += file.rom_size[i] - (((file.rom_size[i] & 0x7fff) == 512) ? 512 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
info.rom_size = size;
|
void Cartridge::load_cart_normal(const char *filename) {
|
||||||
rom = (uint8*)malloc(info.rom_size);
|
if(!filename || !*filename) return;
|
||||||
memset(rom, 0, info.rom_size);
|
|
||||||
|
|
||||||
uint offset = 0;
|
uint8_t *data = 0;
|
||||||
for(int i = 0; i < file.count; i++) {
|
unsigned size;
|
||||||
uint8 *data = file.rom_data[i] + (((file.rom_size[i] & 0x7fff) == 512) ? 512 : 0);
|
if(load_file(filename, data, size) == false) return;
|
||||||
uint size = file.rom_size[i] - (((file.rom_size[i] & 0x7fff) == 512) ? 512 : 0);
|
strcpy(cart.fn, filename);
|
||||||
memcpy(rom + offset, data, size);
|
|
||||||
offset += size;
|
|
||||||
safe_free(file.rom_data[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
info.crc32 = crc32_calculate(rom, info.rom_size);
|
load_begin(CartridgeNormal);
|
||||||
|
|
||||||
if(read_database() == true) {
|
//load ROM data, ignore 512-byte header if detected
|
||||||
info.srtc = false;
|
if((size & 0x7fff) != 512) {
|
||||||
info.sdd1 = false;
|
cart.rom = (uint8*)malloc(cart.rom_size = size);
|
||||||
info.c4 = false;
|
memcpy(cart.rom, data, size);
|
||||||
info.dsp1 = false;
|
|
||||||
info.dsp2 = false;
|
|
||||||
info.obc1 = false;
|
|
||||||
|
|
||||||
info.dsp1_mapper = 0;
|
|
||||||
|
|
||||||
info.header_index = 0xffc0;
|
|
||||||
info.mapper = PCB;
|
|
||||||
strcpy(info.name, dbi.name);
|
|
||||||
strcpy(info.pcb, dbi.pcb);
|
|
||||||
info.region = NTSC;
|
|
||||||
info.cart_mmio = false;
|
|
||||||
|
|
||||||
info.rom_size = dbi.rom;
|
|
||||||
info.ram_size = dbi.ram;
|
|
||||||
} else {
|
} else {
|
||||||
|
cart.rom = (uint8*)malloc(cart.rom_size = size - 512);
|
||||||
|
memcpy(cart.rom, data + 512, size - 512);
|
||||||
|
}
|
||||||
|
safe_free(data);
|
||||||
|
|
||||||
|
info.crc32 = crc32_calculate(cart.rom, cart.rom_size);
|
||||||
|
|
||||||
find_header();
|
find_header();
|
||||||
read_header();
|
read_header();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Cartridge::load_ram_normal() {
|
if(info.ram_size > 0) {
|
||||||
if(info.ram_size == 0) {
|
cart.ram = (uint8*)malloc(cart.ram_size = info.ram_size);
|
||||||
ram = 0;
|
memset(cart.ram, 0xff, cart.ram_size);
|
||||||
return;
|
|
||||||
|
if(load_file(get_save_filename(cart.fn, "srm"), data, size) == true) {
|
||||||
|
memcpy(cart.ram, data, min(size, cart.ram_size));
|
||||||
|
safe_free(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ram = (uint8*)malloc(info.ram_size);
|
load_end();
|
||||||
memset(ram, 0xff, info.ram_size);
|
|
||||||
|
|
||||||
if(load_file(file.ram_name[0], file.ram_data[0], file.ram_size[0]) == true) {
|
//set base filename
|
||||||
memcpy(ram, file.ram_data[0], min(info.ram_size, file.ram_size[0]));
|
strcpy(info.filename, cart.fn);
|
||||||
safe_free(file.ram_data[0]);
|
get_base_filename(info.filename);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cartridge::save_ram_normal() {
|
void Cartridge::unload_cart_normal() {
|
||||||
if(info.ram_size == 0)return;
|
if(cart.ram) save_file(get_save_filename(cart.fn, "srm"), cart.ram, cart.ram_size);
|
||||||
|
|
||||||
save_file(file.ram_name[0], ram, info.ram_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif //ifdef CART_CPP
|
||||||
|
@@ -1,45 +1,84 @@
|
|||||||
void Cartridge::load_rom_st() {
|
#ifdef CART_CPP
|
||||||
uint8 *data;
|
|
||||||
uint size;
|
|
||||||
string bios = config::file_updatepath("stbios.bin", config::path.bios);
|
|
||||||
info.rom_size = 0x200000;
|
|
||||||
rom = (uint8*)malloc(info.rom_size);
|
|
||||||
memset(rom, 0, info.rom_size);
|
|
||||||
|
|
||||||
load_file(strptr(bios), data, size);
|
void Cartridge::load_cart_st(const char *base, const char *slotA, const char *slotB) {
|
||||||
memcpy(rom, data, min(size, 0x040000));
|
if(!base || !*base) return;
|
||||||
safe_free(data);
|
|
||||||
|
|
||||||
memcpy(rom + 0x100000, file.rom_data[0], min(file.rom_size[0], 0x100000));
|
strcpy(cart.fn, base);
|
||||||
safe_free(file.rom_data[0]);
|
strcpy(stA.fn, slotA ? slotA : "");
|
||||||
|
strcpy(stB.fn, slotB ? slotB : "");
|
||||||
|
|
||||||
//
|
load_begin(CartridgeSufamiTurbo);
|
||||||
strcpy(info.name, "???");
|
info.st = true;
|
||||||
strcpy(info.pcb, "STC-SOLO");
|
info.mapper = STROM;
|
||||||
|
|
||||||
info.mapper = PCB;
|
|
||||||
info.region = NTSC;
|
info.region = NTSC;
|
||||||
|
|
||||||
info.rom_size = 0x200000;
|
uint8_t *data = 0;
|
||||||
info.ram_size = 0x020000;
|
unsigned size;
|
||||||
//
|
if(load_file(cart.fn, data, size) == true) {
|
||||||
|
cart.rom = (uint8*)malloc(cart.rom_size = 0x040000);
|
||||||
|
memcpy(cart.rom, data, min(size, cart.rom_size));
|
||||||
|
safe_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
info.crc32 = crc32_calculate(rom + 0x100000, file.rom_size[0]);
|
if(*stA.fn) {
|
||||||
if(read_database() == true) {
|
if(load_file(stA.fn, data, size) == true) {
|
||||||
strcpy(info.name, dbi.name);
|
stA.rom = (uint8*)malloc(stA.rom_size = 0x100000);
|
||||||
|
memcpy(stA.rom, data, min(size, stA.rom_size));
|
||||||
|
safe_free(data);
|
||||||
|
|
||||||
|
stA.ram = (uint8*)malloc(stA.ram_size = 0x020000);
|
||||||
|
memset(stA.ram, 0xff, stA.ram_size);
|
||||||
|
|
||||||
|
if(load_file(get_save_filename(stA.fn, "srm"), data, size) == true) {
|
||||||
|
memcpy(stA.ram, data, min(size, 0x020000U));
|
||||||
|
safe_free(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*stB.fn) {
|
||||||
|
if(load_file(stB.fn, data, size) == true) {
|
||||||
|
stB.rom = (uint8*)malloc(stB.rom_size = 0x100000);
|
||||||
|
memcpy(stB.rom, data, min(size, stB.rom_size));
|
||||||
|
safe_free(data);
|
||||||
|
|
||||||
|
stB.ram = (uint8*)malloc(stB.ram_size = 0x020000);
|
||||||
|
memset(stB.ram, 0xff, stB.ram_size);
|
||||||
|
|
||||||
|
if(load_file(get_save_filename(stB.fn, "srm"), data, size) == true) {
|
||||||
|
memcpy(stB.ram, data, min(size, 0x020000U));
|
||||||
|
safe_free(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
load_end();
|
||||||
|
|
||||||
|
//set base filename
|
||||||
|
if(!*stA.fn && !*stB.fn) {
|
||||||
|
strcpy(info.filename, cart.fn);
|
||||||
|
get_base_filename(info.filename);
|
||||||
|
} else if(*stA.fn && !*stB.fn) {
|
||||||
|
strcpy(info.filename, stA.fn);
|
||||||
|
get_base_filename(info.filename);
|
||||||
|
} else if(!*stA.fn && *stB.fn) {
|
||||||
|
strcpy(info.filename, stB.fn);
|
||||||
|
get_base_filename(info.filename);
|
||||||
|
} else {
|
||||||
|
char filenameA[PATH_MAX], filenameB[PATH_MAX];
|
||||||
|
strcpy(filenameA, stA.fn);
|
||||||
|
get_base_filename(filenameA);
|
||||||
|
strcpy(filenameB, stB.fn);
|
||||||
|
get_base_filename(filenameB);
|
||||||
|
strcpy(info.filename, filenameA);
|
||||||
|
strcat(info.filename, " + ");
|
||||||
|
strcat(info.filename, filenameB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cartridge::load_ram_st() {
|
void Cartridge::unload_cart_st() {
|
||||||
ram = (uint8*)malloc(info.ram_size);
|
if(stA.ram) save_file(get_save_filename(stA.fn, "srm"), stA.ram, stA.ram_size);
|
||||||
memset(ram, 0xff, info.ram_size);
|
if(stB.ram) save_file(get_save_filename(stB.fn, "srm"), stB.ram, stB.ram_size);
|
||||||
|
|
||||||
if(load_file(file.ram_name[0], file.ram_data[0], file.ram_size[0]) == true) {
|
|
||||||
memcpy(ram, file.ram_data[0], min(file.ram_size[0], 0x020000));
|
|
||||||
safe_free(file.ram_data[0]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cartridge::save_ram_st() {
|
#endif //ifdef CART_CPP
|
||||||
save_file(file.ram_name[0], ram, 0x020000);
|
|
||||||
}
|
|
||||||
|
@@ -1,66 +0,0 @@
|
|||||||
void Cartridge::load_rom_stdual() {
|
|
||||||
uint8 *data;
|
|
||||||
uint size;
|
|
||||||
string bios = config::file_updatepath("stbios.bin", config::path.bios);
|
|
||||||
info.rom_size = 0x300000;
|
|
||||||
rom = (uint8*)malloc(info.rom_size);
|
|
||||||
memset(rom, 0, info.rom_size);
|
|
||||||
|
|
||||||
load_file(strptr(bios), data, size);
|
|
||||||
memcpy(rom, data, min(size, 0x040000));
|
|
||||||
safe_free(data);
|
|
||||||
|
|
||||||
memcpy(rom + 0x100000, file.rom_data[0], min(file.rom_size[0], 0x100000));
|
|
||||||
safe_free(file.rom_data[0]);
|
|
||||||
|
|
||||||
memcpy(rom + 0x200000, file.rom_data[1], min(file.rom_size[1], 0x100000));
|
|
||||||
safe_free(file.rom_data[1]);
|
|
||||||
|
|
||||||
char name_a[4096], name_b[4096];
|
|
||||||
strcpy(name_a, "???");
|
|
||||||
strcpy(name_b, "???");
|
|
||||||
//
|
|
||||||
info.mapper = PCB;
|
|
||||||
info.region = NTSC;
|
|
||||||
|
|
||||||
info.rom_size = 0x300000;
|
|
||||||
info.ram_size = 0x040000;
|
|
||||||
//
|
|
||||||
|
|
||||||
info.crc32 = crc32_calculate(rom + 0x100000, file.rom_size[0]);
|
|
||||||
if(read_database() == true) {
|
|
||||||
strcpy(name_a, dbi.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
info.crc32 = crc32_calculate(rom + 0x200000, file.rom_size[1]);
|
|
||||||
if(read_database() == true) {
|
|
||||||
strcpy(name_b, dbi.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
info.crc32 = 0;
|
|
||||||
strcpy(info.name, name_a);
|
|
||||||
strcat(info.name, " + ");
|
|
||||||
strcat(info.name, name_b);
|
|
||||||
strcpy(info.pcb, "STC-DUAL");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Cartridge::load_ram_stdual() {
|
|
||||||
ram = (uint8*)malloc(info.ram_size);
|
|
||||||
memset(ram, 0xff, info.ram_size);
|
|
||||||
|
|
||||||
if(load_file(file.ram_name[0], file.ram_data[0], file.ram_size[0]) == true) {
|
|
||||||
memcpy(ram + 0x000000, file.ram_data[0], min(file.ram_size[0], 0x020000));
|
|
||||||
safe_free(file.ram_data[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(load_file(file.ram_name[1], file.ram_data[1], file.ram_size[1]) == true) {
|
|
||||||
memcpy(ram + 0x020000, file.ram_data[1], min(file.ram_size[1], 0x020000));
|
|
||||||
safe_free(file.ram_data[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Cartridge::save_ram_stdual() {
|
|
||||||
save_file(file.ram_name[0], ram + 0x000000, 0x020000);
|
|
||||||
save_file(file.ram_name[1], ram + 0x020000, 0x020000);
|
|
||||||
}
|
|
@@ -1,37 +0,0 @@
|
|||||||
void Cartridge::load_database() {
|
|
||||||
database = 0;
|
|
||||||
database_size = 0;
|
|
||||||
|
|
||||||
FILE *fp;
|
|
||||||
fp = fopen("cart.db", "rb");
|
|
||||||
if(!fp)return;
|
|
||||||
|
|
||||||
uint size = fsize(fp);
|
|
||||||
if(size < 8) {
|
|
||||||
fclose(fp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
database = (uint8*)malloc(size);
|
|
||||||
fread(database, 1, size, fp);
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
database_blocksize = (database[6] << 0) | (database[7] << 8);
|
|
||||||
database_size = (size - 8) / database_blocksize;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Cartridge::read_database() {
|
|
||||||
uint i, crc32;
|
|
||||||
for(i = 0; i < database_size; i++) {
|
|
||||||
uint8 *p = database + 8 + (i * database_blocksize);
|
|
||||||
crc32 = *(p++) << 0;
|
|
||||||
crc32 |= *(p++) << 8;
|
|
||||||
crc32 |= *(p++) << 16;
|
|
||||||
crc32 |= *(p++) << 24;
|
|
||||||
if(crc32 == cartridge.info.crc32)break;
|
|
||||||
}
|
|
||||||
if(i >= database_size)return false;
|
|
||||||
|
|
||||||
db_read(dbi, database + 8 + (i * database_blocksize));
|
|
||||||
return true;
|
|
||||||
}
|
|
Binary file not shown.
@@ -1,113 +0,0 @@
|
|||||||
[0xbb5c4238]
|
|
||||||
name = "Bishoujo Senshi Sailor Moon Sailor Stars - Fuwa Fuwa Panic 2 (Japan)"
|
|
||||||
pcb = "STC-????"
|
|
||||||
rom = 8mbit
|
|
||||||
ram = 32kbit
|
|
||||||
|
|
||||||
[0x8eb753f3]
|
|
||||||
name = "Crayon Shin-chan - Nagagutsu Dobon!! (Japan)"
|
|
||||||
pcb = "STC-????"
|
|
||||||
rom = 4mbit
|
|
||||||
ram = 8kbit
|
|
||||||
|
|
||||||
[0x7aedd703]
|
|
||||||
name = "Der Langrisser (Japan) [!]"
|
|
||||||
pcb = "SHVC-1A3M-30"
|
|
||||||
rom = 16mbit
|
|
||||||
ram = 64kbit
|
|
||||||
|
|
||||||
[0x19bdcb19]
|
|
||||||
name = "Derby Stallion '96 (Japan) [!]"
|
|
||||||
pcb = "BSC-1A5M-01"
|
|
||||||
rom = 24mbit
|
|
||||||
ram = 256kbit
|
|
||||||
|
|
||||||
[0x4296500d]
|
|
||||||
name = "Gegege no Kitarou - Youkai Donjara (Japan)"
|
|
||||||
pcb = "STC-????"
|
|
||||||
rom = 4mbit
|
|
||||||
ram = 16kbit
|
|
||||||
|
|
||||||
[0x14c66fca]
|
|
||||||
name = "Gekisou Sentai Car Rangers (Japan)"
|
|
||||||
pcb = "STC-????"
|
|
||||||
rom = 4mbit
|
|
||||||
ram = 8kbit
|
|
||||||
|
|
||||||
[0x32b2b3dd]
|
|
||||||
name = "Poi Poi Ninja World (Japan)"
|
|
||||||
pcb = "STC-????"
|
|
||||||
rom = 4mbit
|
|
||||||
ram = 8kbit
|
|
||||||
|
|
||||||
[0x9684526d]
|
|
||||||
name = "Romancing SaGa (Japan) (V1.1) [!]"
|
|
||||||
pcb = "SHVC-1A3B-12"
|
|
||||||
rom = 8mbit
|
|
||||||
ram = 64kbit
|
|
||||||
|
|
||||||
[0xafd74dcb]
|
|
||||||
name = "SD Gundam Generation A - Ichinen Sensouki (Japan)"
|
|
||||||
pcb = "STC-????"
|
|
||||||
rom = 4mbit
|
|
||||||
ram = 8kbit
|
|
||||||
|
|
||||||
[0x48ecae44]
|
|
||||||
name = "SD Gundam Generation B - Grips Senki (Japan)"
|
|
||||||
pcb = "STC-????"
|
|
||||||
rom = 4mbit
|
|
||||||
ram = 8kbit
|
|
||||||
|
|
||||||
[0x72b4235f]
|
|
||||||
name = "SD Gundam Generation C - Axis Senki (Japan)"
|
|
||||||
pcb = "STC-????"
|
|
||||||
rom = 4mbit
|
|
||||||
ram = 8kbit
|
|
||||||
|
|
||||||
[0x792d884c]
|
|
||||||
name = "SD Gundam Generation D - Babylonia Kenkoku Senki (Japan)"
|
|
||||||
pcb = "STC-????"
|
|
||||||
rom = 4mbit
|
|
||||||
ram = 8kbit
|
|
||||||
|
|
||||||
[0xefd3a865]
|
|
||||||
name = "SD Gundam Generation E - Zanskar Senki (Japan)"
|
|
||||||
pcb = "STC-????"
|
|
||||||
rom = 4mbit
|
|
||||||
ram = 8kbit
|
|
||||||
|
|
||||||
[0xc5dfa8fd]
|
|
||||||
name = "SD Gundam Generation F - Colony Kakutouki (Japan)"
|
|
||||||
pcb = "STC-????"
|
|
||||||
rom = 4mbit
|
|
||||||
ram = 8kbit
|
|
||||||
|
|
||||||
[0x43ad5a45]
|
|
||||||
name = "SD Ultra Battle - Seven Densetsu (Japan)"
|
|
||||||
pcb = "STC-????"
|
|
||||||
rom = 4mbit
|
|
||||||
ram = 8kbit
|
|
||||||
|
|
||||||
[0x04939d14]
|
|
||||||
name = "SD Ultra Battle - Ultra Densetsu (Japan)"
|
|
||||||
pcb = "STC-????"
|
|
||||||
rom = 4mbit
|
|
||||||
ram = 8kbit
|
|
||||||
|
|
||||||
[0xa5c0045e]
|
|
||||||
name = "Secret of Evermore (USA) [!]"
|
|
||||||
pcb = "SHVC-1J3M-20"
|
|
||||||
rom = 32mbit
|
|
||||||
ram = 64kbit
|
|
||||||
|
|
||||||
[0x5ebf7246]
|
|
||||||
name = "Sound Novel Tsukuru (Japan) [!]"
|
|
||||||
pcb = "BSC-1A7M-10"
|
|
||||||
rom = 24mbit
|
|
||||||
ram = 512kbit
|
|
||||||
|
|
||||||
[0x64a91e64]
|
|
||||||
name = "Wanderers from Ys (USA) [!]"
|
|
||||||
pcb = "SHVC-1A3B-12"
|
|
||||||
rom = 8mbit
|
|
||||||
ram = 64kbit
|
|
@@ -1,3 +0,0 @@
|
|||||||
cl /nologo /O2 dbcreate.cpp
|
|
||||||
@pause
|
|
||||||
@del *.obj
|
|
@@ -1 +0,0 @@
|
|||||||
@del *.exe
|
|
@@ -1,2 +0,0 @@
|
|||||||
dbcreate
|
|
||||||
@copy cart.db ..\..\..\cart.db
|
|
@@ -1,47 +0,0 @@
|
|||||||
struct db_item {
|
|
||||||
uint32 crc32;
|
|
||||||
char name[128];
|
|
||||||
char pcb [32];
|
|
||||||
uint32 rom;
|
|
||||||
uint32 ram;
|
|
||||||
};
|
|
||||||
|
|
||||||
void db_write(FILE *fp, db_item &dbi) {
|
|
||||||
fputc(dbi.crc32 >> 0, fp);
|
|
||||||
fputc(dbi.crc32 >> 8, fp);
|
|
||||||
fputc(dbi.crc32 >> 16, fp);
|
|
||||||
fputc(dbi.crc32 >> 24, fp);
|
|
||||||
|
|
||||||
fwrite(dbi.name, 1, 128, fp);
|
|
||||||
fwrite(dbi.pcb, 1, 32, fp);
|
|
||||||
|
|
||||||
fputc(dbi.rom >> 0, fp);
|
|
||||||
fputc(dbi.rom >> 8, fp);
|
|
||||||
fputc(dbi.rom >> 16, fp);
|
|
||||||
fputc(dbi.rom >> 24, fp);
|
|
||||||
|
|
||||||
fputc(dbi.ram >> 0, fp);
|
|
||||||
fputc(dbi.ram >> 8, fp);
|
|
||||||
fputc(dbi.ram >> 16, fp);
|
|
||||||
fputc(dbi.ram >> 24, fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void db_read(db_item &dbi, uint8 *data) {
|
|
||||||
dbi.crc32 = (*data++) << 0;
|
|
||||||
dbi.crc32 |= (*data++) << 8;
|
|
||||||
dbi.crc32 |= (*data++) << 16;
|
|
||||||
dbi.crc32 |= (*data++) << 24;
|
|
||||||
|
|
||||||
memcpy(dbi.name, data, 128); dbi.name[127] = 0; data += 128;
|
|
||||||
memcpy(dbi.pcb, data, 32); dbi.pcb [ 31] = 0; data += 32;
|
|
||||||
|
|
||||||
dbi.rom = (*data++) << 0;
|
|
||||||
dbi.rom |= (*data++) << 8;
|
|
||||||
dbi.rom |= (*data++) << 16;
|
|
||||||
dbi.rom |= (*data++) << 24;
|
|
||||||
|
|
||||||
dbi.ram = (*data++) << 0;
|
|
||||||
dbi.ram |= (*data++) << 8;
|
|
||||||
dbi.ram |= (*data++) << 16;
|
|
||||||
dbi.ram |= (*data++) << 24;
|
|
||||||
}
|
|
@@ -1,117 +0,0 @@
|
|||||||
#include "../../lib/libbase.h"
|
|
||||||
#include "../../lib/libvector.h"
|
|
||||||
#include "../../lib/libstring.h"
|
|
||||||
|
|
||||||
#include "../../lib/libstring.cpp"
|
|
||||||
|
|
||||||
#include "db.h"
|
|
||||||
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
uint decode_size(string &str) {
|
|
||||||
//hex encoding
|
|
||||||
if(strbegin(str, "0x")) {
|
|
||||||
strltrim(str, "0x");
|
|
||||||
return strhex(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
//mbit encoding
|
|
||||||
if(strend(str, "mbit")) {
|
|
||||||
strrtrim(str, "mbit");
|
|
||||||
return strdec(str) * 1024 * 1024 / 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
//kbit encoding
|
|
||||||
if(strend(str, "kbit")) {
|
|
||||||
strrtrim(str, "kbit");
|
|
||||||
return strdec(str) * 1024 / 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
//decimal encoding
|
|
||||||
return strdec(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
void build_block(string &block) {
|
|
||||||
stringarray line, hashpart, part;
|
|
||||||
split(line, "\n", block);
|
|
||||||
|
|
||||||
if(strbegin(line[0], "[") == false) {
|
|
||||||
printf("error: invalid block detected: '%s'\n", strptr(line[0]));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
strltrim(line[0], "[");
|
|
||||||
strrtrim(line[0], "]");
|
|
||||||
replace(line[0], "0x", "");
|
|
||||||
split(hashpart, ",", line[0]);
|
|
||||||
|
|
||||||
db_item dbi;
|
|
||||||
dbi.crc32 = 0;
|
|
||||||
*dbi.name = 0;
|
|
||||||
*dbi.pcb = 0;
|
|
||||||
dbi.rom = 0;
|
|
||||||
dbi.ram = 0;
|
|
||||||
|
|
||||||
for(int i = 1; i < count(line); i++) {
|
|
||||||
uint pos;
|
|
||||||
if(strpos(line[i], ";", pos) == true) {
|
|
||||||
strset(line[i], pos, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(line[i] == "")continue;
|
|
||||||
|
|
||||||
split(part, "=", line[i]);
|
|
||||||
strunquote(part[1]);
|
|
||||||
|
|
||||||
if(part[0] == "name") {
|
|
||||||
strncpy(dbi.name, strptr(part[1]), 128);
|
|
||||||
dbi.name[128] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(part[0] == "pcb") {
|
|
||||||
strncpy(dbi.pcb, strptr(part[1]), 32);
|
|
||||||
dbi.pcb[31] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(part[0] == "rom") {
|
|
||||||
dbi.rom = decode_size(part[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(part[0] == "ram") {
|
|
||||||
dbi.ram = decode_size(part[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < count(hashpart); i++) {
|
|
||||||
dbi.crc32 = strhex(hashpart[i]);
|
|
||||||
db_write(fp, dbi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void build_database() {
|
|
||||||
stringarray data, block;
|
|
||||||
if(strfread(data, "cartdb.txt") == false)return;
|
|
||||||
|
|
||||||
fp = fopen("cart.db", "wb");
|
|
||||||
fprintf(fp, "SNESDB");
|
|
||||||
|
|
||||||
uint blocksize = 4 + 128 + 32 + 4 + 4;
|
|
||||||
fputc(blocksize >> 0, fp);
|
|
||||||
fputc(blocksize >> 8, fp);
|
|
||||||
|
|
||||||
replace (data, "\r", "");
|
|
||||||
qreplace(data, " ", "");
|
|
||||||
qreplace(data, "\t", "");
|
|
||||||
split(block, "\n\n", data);
|
|
||||||
|
|
||||||
for(int i = 0; i < count(block); i++) {
|
|
||||||
build_block(block[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
build_database();
|
|
||||||
return 0;
|
|
||||||
}
|
|
@@ -1,3 +1,3 @@
|
|||||||
@make -r PLATFORM=win-visualc-lui
|
@make platform=win compiler=mingw32-gcc
|
||||||
@move bsnes.exe ../bsnes.exe>nul
|
::@make platform=win compiler=mingw32-gcc enable_gzip=true enable_jma=true
|
||||||
@pause
|
@pause
|
@@ -1,2 +1,2 @@
|
|||||||
#!/bin/sh
|
make platform=x compiler=gcc
|
||||||
make PLATFORM=x-gcc-lui
|
#make platform=x compiler=gcc enable_gzip=true enable_jma=true
|
||||||
|
@@ -10,21 +10,21 @@ Cheat cheat;
|
|||||||
*****/
|
*****/
|
||||||
|
|
||||||
bool Cheat::decode(char *str, uint32 &addr, uint8 &data, uint8 &type) {
|
bool Cheat::decode(char *str, uint32 &addr, uint8 &data, uint8 &type) {
|
||||||
stringarray t, part;
|
string t, part;
|
||||||
strcpy(t, str);
|
strcpy(t, str);
|
||||||
strlower(t);
|
strlower(t());
|
||||||
if(strlen(t) == 8 || (strlen(t) == 9 && strptr(t)[6] == ':')) {
|
if(strlen(t) == 8 || (strlen(t) == 9 && t()[6] == ':')) {
|
||||||
type = CT_PRO_ACTION_REPLAY;
|
type = ProActionReplay;
|
||||||
replace(t, ":", "");
|
replace(t, ":", "");
|
||||||
uint32 r = strhex(t);
|
uint32 r = strhex((const char*)t);
|
||||||
addr = r >> 8;
|
addr = r >> 8;
|
||||||
data = r & 0xff;
|
data = r & 0xff;
|
||||||
return true;
|
return true;
|
||||||
} else if(strlen(t) == 9 && strptr(t)[4] == '-') {
|
} else if(strlen(t) == 9 && t()[4] == '-') {
|
||||||
type = CT_GAME_GENIE;
|
type = GameGenie;
|
||||||
replace(t, "-", "");
|
replace(t, "-", "");
|
||||||
strtr(t, "df4709156bc8a23e", "0123456789abcdef");
|
strtr(t, "df4709156bc8a23e", "0123456789abcdef");
|
||||||
uint32 r = strhex(t);
|
uint32 r = strhex((const char*)t);
|
||||||
//8421 8421 8421 8421 8421 8421
|
//8421 8421 8421 8421 8421 8421
|
||||||
//abcd efgh ijkl mnop qrst uvwx
|
//abcd efgh ijkl mnop qrst uvwx
|
||||||
//ijkl qrst opab cduv wxef ghmn
|
//ijkl qrst opab cduv wxef ghmn
|
||||||
@@ -47,10 +47,10 @@ stringarray t, part;
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Cheat::encode(char *str, uint32 addr, uint8 data, uint8 type) {
|
bool Cheat::encode(char *str, uint32 addr, uint8 data, uint8 type) {
|
||||||
if(type == CT_PRO_ACTION_REPLAY) {
|
if(type == ProActionReplay) {
|
||||||
sprintf(str, "%0.6x:%0.2x", addr, data);
|
sprintf(str, "%0.6x:%0.2x", addr, data);
|
||||||
return true;
|
return true;
|
||||||
} else if(type == CT_GAME_GENIE) {
|
} else if(type == GameGenie) {
|
||||||
uint32 r = addr;
|
uint32 r = addr;
|
||||||
addr = (!!(r & 0x008000) << 23) | (!!(r & 0x004000) << 22) |
|
addr = (!!(r & 0x008000) << 23) | (!!(r & 0x004000) << 22) |
|
||||||
(!!(r & 0x002000) << 21) | (!!(r & 0x001000) << 20) |
|
(!!(r & 0x002000) << 21) | (!!(r & 0x001000) << 20) |
|
||||||
@@ -79,9 +79,9 @@ bool Cheat::encode(char *str, uint32 addr, uint8 data, uint8 type) {
|
|||||||
*****/
|
*****/
|
||||||
|
|
||||||
uint Cheat::mirror_address(uint addr) {
|
uint Cheat::mirror_address(uint addr) {
|
||||||
if((addr & 0x40e000) != 0x0000)return addr;
|
if((addr & 0x40e000) != 0x0000) return addr;
|
||||||
//8k WRAM mirror
|
//8k WRAM mirror
|
||||||
//$[00-3f|80-bf]:[0000-1fff] -> $7e:[0000-1fff]
|
//$[00-3f|80-bf]:[0000-1fff] -> $7e:[0000-1fff]
|
||||||
return (0x7e0000 + (addr & 0x1fff));
|
return (0x7e0000 + (addr & 0x1fff));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,10 +104,10 @@ void Cheat::set(uint32 addr) {
|
|||||||
void Cheat::clear(uint32 addr) {
|
void Cheat::clear(uint32 addr) {
|
||||||
addr = mirror_address(addr);
|
addr = mirror_address(addr);
|
||||||
|
|
||||||
//is there more than one cheat code using the same address
|
//is there more than one cheat code using the same address
|
||||||
//(and likely a different override value) that is enabled?
|
//(and likely a different override value) that is enabled?
|
||||||
//if so, do not clear code lookup table entry for this address.
|
//if so, do not clear code lookup table entry for this address.
|
||||||
uint8 r;
|
uint8 r;
|
||||||
if(read(addr, r) == true)return;
|
if(read(addr, r) == true)return;
|
||||||
|
|
||||||
mask[addr >> 3] &= ~(1 << (addr & 7));
|
mask[addr >> 3] &= ~(1 << (addr & 7));
|
||||||
@@ -133,13 +133,13 @@ uint8 r;
|
|||||||
bool Cheat::read(uint32 addr, uint8 &data) {
|
bool Cheat::read(uint32 addr, uint8 &data) {
|
||||||
addr = mirror_address(addr);
|
addr = mirror_address(addr);
|
||||||
for(int i = 0; i < cheat_count; i++) {
|
for(int i = 0; i < cheat_count; i++) {
|
||||||
if(enabled(i) == false)continue;
|
if(enabled(i) == false) continue;
|
||||||
if(addr == mirror_address(index[i].addr)) {
|
if(addr == mirror_address(index[i].addr)) {
|
||||||
data = index[i].data;
|
data = index[i].data;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//code not found, or code is disabled
|
//code not found, or code is disabled
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,8 +148,9 @@ bool Cheat::read(uint32 addr, uint8 &data) {
|
|||||||
* enabled. if any are, make sure the cheat system is on.
|
* enabled. if any are, make sure the cheat system is on.
|
||||||
* otherwise, turn cheat system off to speed up emulation.
|
* otherwise, turn cheat system off to speed up emulation.
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
void Cheat::update_cheat_status() {
|
void Cheat::update_cheat_status() {
|
||||||
for(int i = 0; i < cheat_count; i++) {
|
for(unsigned i = 0; i < cheat_count; i++) {
|
||||||
if(index[i].enabled) {
|
if(index[i].enabled) {
|
||||||
cheat_enabled = true;
|
cheat_enabled = true;
|
||||||
return;
|
return;
|
||||||
@@ -163,11 +164,11 @@ void Cheat::update_cheat_status() {
|
|||||||
*****/
|
*****/
|
||||||
|
|
||||||
bool Cheat::add(bool enable, char *code, char *desc) {
|
bool Cheat::add(bool enable, char *code, char *desc) {
|
||||||
if(cheat_count >= CHEAT_LIMIT)return false;
|
if(cheat_count >= CheatLimit) return false;
|
||||||
|
|
||||||
uint32 addr, len;
|
uint32 addr, len;
|
||||||
uint8 data, type;
|
uint8 data, type;
|
||||||
if(decode(code, addr, data, type) == false)return false;
|
if(decode(code, addr, data, type) == false) return false;
|
||||||
|
|
||||||
index[cheat_count].enabled = enable;
|
index[cheat_count].enabled = enable;
|
||||||
index[cheat_count].addr = addr;
|
index[cheat_count].addr = addr;
|
||||||
@@ -188,17 +189,17 @@ uint8 data, type;
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Cheat::edit(uint32 n, bool enable, char *code, char *desc) {
|
bool Cheat::edit(uint32 n, bool enable, char *code, char *desc) {
|
||||||
if(n >= cheat_count)return false;
|
if(n >= cheat_count) return false;
|
||||||
|
|
||||||
uint32 addr, len;
|
uint32 addr, len;
|
||||||
uint8 data, type;
|
uint8 data, type;
|
||||||
if(decode(code, addr, data, type) == false)return false;
|
if(decode(code, addr, data, type) == false) return false;
|
||||||
|
|
||||||
//disable current code and clear from code lookup table
|
//disable current code and clear from code lookup table
|
||||||
index[n].enabled = false;
|
index[n].enabled = false;
|
||||||
clear(index[n].addr);
|
clear(index[n].addr);
|
||||||
|
|
||||||
//update code and enable in code lookup table
|
//update code and enable in code lookup table
|
||||||
index[n].enabled = enable;
|
index[n].enabled = enable;
|
||||||
index[n].addr = addr;
|
index[n].addr = addr;
|
||||||
index[n].data = data;
|
index[n].data = data;
|
||||||
@@ -217,9 +218,9 @@ uint8 data, type;
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Cheat::remove(uint32 n) {
|
bool Cheat::remove(uint32 n) {
|
||||||
if(n >= cheat_count)return false;
|
if(n >= cheat_count) return false;
|
||||||
|
|
||||||
for(int i = n; i < cheat_count; i++) {
|
for(unsigned i = n; i < cheat_count; i++) {
|
||||||
index[i].enabled = index[i + 1].enabled;
|
index[i].enabled = index[i + 1].enabled;
|
||||||
index[i].addr = index[i + 1].addr;
|
index[i].addr = index[i + 1].addr;
|
||||||
index[i].data = index[i + 1].data;
|
index[i].data = index[i + 1].data;
|
||||||
@@ -233,7 +234,7 @@ bool Cheat::remove(uint32 n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Cheat::get(uint32 n, bool &enable, uint32 &addr, uint8 &data, char *code, char *desc) {
|
bool Cheat::get(uint32 n, bool &enable, uint32 &addr, uint8 &data, char *code, char *desc) {
|
||||||
if(n >= cheat_count)return false;
|
if(n >= cheat_count) return false;
|
||||||
enable = index[n].enabled;
|
enable = index[n].enabled;
|
||||||
addr = index[n].addr;
|
addr = index[n].addr;
|
||||||
data = index[n].data;
|
data = index[n].data;
|
||||||
@@ -247,19 +248,19 @@ bool Cheat::get(uint32 n, bool &enable, uint32 &addr, uint8 &data, char *code, c
|
|||||||
*****/
|
*****/
|
||||||
|
|
||||||
bool Cheat::enabled(uint32 n) {
|
bool Cheat::enabled(uint32 n) {
|
||||||
if(n >= cheat_count)return false;
|
if(n >= cheat_count) return false;
|
||||||
return index[n].enabled;
|
return index[n].enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cheat::enable(uint32 n) {
|
void Cheat::enable(uint32 n) {
|
||||||
if(n >= cheat_count)return;
|
if(n >= cheat_count) return;
|
||||||
index[n].enabled = true;
|
index[n].enabled = true;
|
||||||
set(index[n].addr);
|
set(index[n].addr);
|
||||||
update_cheat_status();
|
update_cheat_status();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cheat::disable(uint32 n) {
|
void Cheat::disable(uint32 n) {
|
||||||
if(n >= cheat_count)return;
|
if(n >= cheat_count) return;
|
||||||
index[n].enabled = false;
|
index[n].enabled = false;
|
||||||
clear(index[n].addr);
|
clear(index[n].addr);
|
||||||
update_cheat_status();
|
update_cheat_status();
|
||||||
@@ -269,51 +270,40 @@ void Cheat::disable(uint32 n) {
|
|||||||
* cheat file manipulation routines
|
* cheat file manipulation routines
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
|
/* file format: */
|
||||||
|
/* nnnn-nnnn = status, "description" \r\n */
|
||||||
|
/* ... */
|
||||||
|
|
||||||
bool Cheat::load(const char *fn) {
|
bool Cheat::load(const char *fn) {
|
||||||
FileReader rf(fn);
|
string data;
|
||||||
if(!rf.ready())return false;
|
if(!fread(data, fn)) return false;
|
||||||
|
|
||||||
uint8 *raw_data = rf.read();
|
|
||||||
stringarray data, line;
|
|
||||||
raw_data[rf.size()] = 0;
|
|
||||||
strcpy(data, (char*)raw_data);
|
|
||||||
safe_free(raw_data);
|
|
||||||
replace(data, "\r\n", "\n");
|
replace(data, "\r\n", "\n");
|
||||||
|
qreplace(data, "=", ",");
|
||||||
|
qreplace(data, " ", "");
|
||||||
|
|
||||||
|
lstring line;
|
||||||
split(line, "\n", data);
|
split(line, "\n", data);
|
||||||
for(int i = 0; i < ::count(line); i++) {
|
for(unsigned i = 0; i < ::count(line); i++) {
|
||||||
stringarray part;
|
lstring part;
|
||||||
uint8 en = *(strptr(line[i]));
|
split(part, ",", line[i]);
|
||||||
if(en == '+') {
|
if(::count(part) != 3) continue;
|
||||||
strltrim(line[i], "+");
|
trim(part[2], "\"");
|
||||||
} else if(en == '-') {
|
add(part[1] == "enabled", part[0](), part[2]());
|
||||||
strltrim(line[i], "-");
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
qreplace(line[i], " ", "");
|
|
||||||
qsplit(part, ",", line[i]);
|
|
||||||
if(::count(part) != 2)continue;
|
|
||||||
strunquote(part[1]);
|
|
||||||
add(en == '+', strptr(part[0]), strptr(part[1]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Cheat::save(const char *fn) {
|
bool Cheat::save(const char *fn) {
|
||||||
FileWriter wf(fn);
|
FILE *fp = fopen(fn, "wb");
|
||||||
if(!wf.ready())return false;
|
if(!fp) return false;
|
||||||
|
for(unsigned i = 0; i < cheat_count; i++) {
|
||||||
string data;
|
fprintf(fp, "%9s = %8s, \"%s\"\r\n",
|
||||||
char t[4096];
|
index[i].code,
|
||||||
strcpy(data, "");
|
index[i].enabled ? "enabled" : "disabled",
|
||||||
for(int i = 0; i < cheat_count; i++) {
|
index[i].desc);
|
||||||
sprintf(t, "%c%s, \"%s\"\r\n", index[i].enabled ? '+' : '-', index[i].code, index[i].desc);
|
|
||||||
strcat(data, t);
|
|
||||||
}
|
}
|
||||||
|
fclose(fp);
|
||||||
wf.write((uint8*)strptr(data), strlen(data));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,7 +315,7 @@ void Cheat::clear() {
|
|||||||
cheat_enabled = false;
|
cheat_enabled = false;
|
||||||
cheat_count = 0;
|
cheat_count = 0;
|
||||||
memset(mask, 0, 0x200000);
|
memset(mask, 0, 0x200000);
|
||||||
for(int i = 0; i < CHEAT_LIMIT + 1; i++) {
|
for(unsigned i = 0; i <= CheatLimit; i++) {
|
||||||
index[i].enabled = false;
|
index[i].enabled = false;
|
||||||
index[i].addr = 0x000000;
|
index[i].addr = 0x000000;
|
||||||
index[i].data = 0x00;
|
index[i].data = 0x00;
|
||||||
|
@@ -1,19 +1,23 @@
|
|||||||
#define CHEAT_LIMIT 1024
|
|
||||||
|
|
||||||
class Cheat {
|
class Cheat {
|
||||||
public:
|
public:
|
||||||
enum { CT_PRO_ACTION_REPLAY, CT_GAME_GENIE };
|
enum { CheatLimit = 1024 };
|
||||||
|
|
||||||
struct CheatIndex {
|
enum Type {
|
||||||
|
ProActionReplay,
|
||||||
|
GameGenie,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CheatIndex {
|
||||||
bool enabled;
|
bool enabled;
|
||||||
uint32 addr;
|
uint32 addr;
|
||||||
uint8 data;
|
uint8 data;
|
||||||
char code[ 16 + 1];
|
char code[ 16 + 1];
|
||||||
char desc[128 + 1];
|
char desc[128 + 1];
|
||||||
} index[CHEAT_LIMIT + 1];
|
} index[CheatLimit + 1];
|
||||||
bool cheat_enabled;
|
|
||||||
uint32 cheat_count;
|
bool cheat_enabled;
|
||||||
uint8 mask[0x200000];
|
uint32 cheat_count;
|
||||||
|
uint8 mask[0x200000];
|
||||||
|
|
||||||
inline bool enabled() { return cheat_enabled; }
|
inline bool enabled() { return cheat_enabled; }
|
||||||
inline uint count() { return cheat_count; }
|
inline uint count() { return cheat_count; }
|
||||||
@@ -22,27 +26,26 @@ uint8 mask[0x200000];
|
|||||||
bool decode(char *str, uint32 &addr, uint8 &data, uint8 &type);
|
bool decode(char *str, uint32 &addr, uint8 &data, uint8 &type);
|
||||||
bool encode(char *str, uint32 addr, uint8 data, uint8 type);
|
bool encode(char *str, uint32 addr, uint8 data, uint8 type);
|
||||||
|
|
||||||
private:
|
|
||||||
uint mirror_address(uint addr);
|
|
||||||
void set(uint32 addr);
|
|
||||||
void clear(uint32 addr);
|
|
||||||
public:
|
|
||||||
|
|
||||||
bool read(uint32 addr, uint8 &data);
|
bool read(uint32 addr, uint8 &data);
|
||||||
|
|
||||||
void update_cheat_status();
|
void update_cheat_status();
|
||||||
bool add(bool enable, char *code, char *desc);
|
bool add(bool enable, char *code, char *desc);
|
||||||
bool edit(uint32 n, bool enable, char *code, char *desc);
|
bool edit(uint32 n, bool enable, char *code, char *desc);
|
||||||
bool get(uint32 n, bool &enable, uint32 &addr, uint8 &data, char *code, char *desc);
|
bool get(uint32 n, bool &enable, uint32 &addr, uint8 &data, char *code, char *desc);
|
||||||
bool remove (uint32 n);
|
bool remove(uint32 n);
|
||||||
bool enabled(uint32 n);
|
bool enabled(uint32 n);
|
||||||
void enable (uint32 n);
|
void enable(uint32 n);
|
||||||
void disable(uint32 n);
|
void disable(uint32 n);
|
||||||
bool load(const char *fn);
|
bool load(const char *fn);
|
||||||
bool save(const char *fn);
|
bool save(const char *fn);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
Cheat();
|
Cheat();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint mirror_address(uint addr);
|
||||||
|
void set(uint32 addr);
|
||||||
|
void clear(uint32 addr);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Cheat cheat;
|
extern Cheat cheat;
|
||||||
|
6
src/chip/bsx/bsx.cpp
Normal file
6
src/chip/bsx/bsx.cpp
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#include "../../base.h"
|
||||||
|
#define BSX_CPP
|
||||||
|
|
||||||
|
#include "bsx_base.cpp"
|
||||||
|
#include "bsx_cart.cpp"
|
||||||
|
#include "bsx_flash.cpp"
|
77
src/chip/bsx/bsx.h
Normal file
77
src/chip/bsx/bsx.h
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
class BSXBase : public MMIO {
|
||||||
|
public:
|
||||||
|
void init();
|
||||||
|
void enable();
|
||||||
|
void power();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
uint8 mmio_read(uint addr);
|
||||||
|
void mmio_write(uint addr, uint8 data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct {
|
||||||
|
uint8 r2188, r2189, r218a, r218b;
|
||||||
|
uint8 r218c, r218d, r218e, r218f;
|
||||||
|
uint8 r2190, r2191, r2192, r2193;
|
||||||
|
uint8 r2194, r2195, r2196, r2197;
|
||||||
|
uint8 r2198, r2199, r219a, r219b;
|
||||||
|
uint8 r219c, r219d, r219e, r219f;
|
||||||
|
|
||||||
|
uint8 r2192_counter;
|
||||||
|
uint8 r2192_hour, r2192_minute, r2192_second;
|
||||||
|
} regs;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BSXCart : public MMIO {
|
||||||
|
public:
|
||||||
|
void init();
|
||||||
|
void enable();
|
||||||
|
void power();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
uint8 mmio_read(uint addr);
|
||||||
|
void mmio_write(uint addr, uint8 data);
|
||||||
|
|
||||||
|
MappedRAM sram;
|
||||||
|
MappedRAM psram;
|
||||||
|
|
||||||
|
BSXCart();
|
||||||
|
~BSXCart();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8 *sram_data; //256kbit SRAM
|
||||||
|
uint8 *psram_data; // 4mbit PSRAM
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint8 r[16];
|
||||||
|
} regs;
|
||||||
|
|
||||||
|
void update_memory_map();
|
||||||
|
};
|
||||||
|
|
||||||
|
class BSXFlash : public Memory {
|
||||||
|
public:
|
||||||
|
void init();
|
||||||
|
void enable();
|
||||||
|
void power();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
uint size();
|
||||||
|
uint8 read(uint addr);
|
||||||
|
void write(uint addr, uint8 data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct {
|
||||||
|
uint command;
|
||||||
|
uint8 write_old;
|
||||||
|
uint8 write_new;
|
||||||
|
|
||||||
|
bool flash_enable;
|
||||||
|
bool read_enable;
|
||||||
|
bool write_enable;
|
||||||
|
} regs;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern BSXBase bsxbase;
|
||||||
|
extern BSXCart bsxcart;
|
||||||
|
extern BSXFlash bsxflash;
|
137
src/chip/bsx/bsx_base.cpp
Normal file
137
src/chip/bsx/bsx_base.cpp
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
#ifdef BSX_CPP
|
||||||
|
|
||||||
|
void BSXBase::init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void BSXBase::enable() {
|
||||||
|
for(uint16 i = 0x2188; i <= 0x219f; i++) memory::mmio.map(i, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BSXBase::power() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BSXBase::reset() {
|
||||||
|
memset(®s, 0x00, sizeof regs);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 BSXBase::mmio_read(uint addr) {
|
||||||
|
addr &= 0xffff;
|
||||||
|
|
||||||
|
switch(addr) {
|
||||||
|
case 0x2188: return regs.r2188;
|
||||||
|
case 0x2189: return regs.r2189;
|
||||||
|
case 0x218a: return regs.r218a;
|
||||||
|
case 0x218c: return regs.r218c;
|
||||||
|
case 0x218e: return regs.r218e;
|
||||||
|
case 0x218f: return regs.r218f;
|
||||||
|
case 0x2190: return regs.r2190;
|
||||||
|
|
||||||
|
case 0x2192: {
|
||||||
|
uint counter = regs.r2192_counter++;
|
||||||
|
if(regs.r2192_counter >= 18) regs.r2192_counter = 0;
|
||||||
|
|
||||||
|
if(counter == 0) {
|
||||||
|
time_t rawtime;
|
||||||
|
time(&rawtime);
|
||||||
|
tm *t = localtime(&rawtime);
|
||||||
|
|
||||||
|
regs.r2192_hour = t->tm_hour;
|
||||||
|
regs.r2192_minute = t->tm_min;
|
||||||
|
regs.r2192_second = t->tm_sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(counter) {
|
||||||
|
case 0: return 0x00; //???
|
||||||
|
case 1: return 0x00; //???
|
||||||
|
case 2: return 0x00; //???
|
||||||
|
case 3: return 0x00; //???
|
||||||
|
case 4: return 0x00; //???
|
||||||
|
case 5: return 0x01;
|
||||||
|
case 6: return 0x01;
|
||||||
|
case 7: return 0x00;
|
||||||
|
case 8: return 0x00;
|
||||||
|
case 9: return 0x00;
|
||||||
|
case 10: return regs.r2192_second;
|
||||||
|
case 11: return regs.r2192_minute;
|
||||||
|
case 12: return regs.r2192_hour;
|
||||||
|
case 13: return 0x00; //???
|
||||||
|
case 14: return 0x00; //???
|
||||||
|
case 15: return 0x00; //???
|
||||||
|
case 16: return 0x00; //???
|
||||||
|
case 17: return 0x00; //???
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x2193: return regs.r2193 & ~0x0c;
|
||||||
|
case 0x2194: return regs.r2194;
|
||||||
|
case 0x2196: return regs.r2196;
|
||||||
|
case 0x2197: return regs.r2197;
|
||||||
|
case 0x2199: return regs.r2199;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cpu.regs.mdr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BSXBase::mmio_write(uint addr, uint8 data) {
|
||||||
|
addr &= 0xffff;
|
||||||
|
|
||||||
|
switch(addr) {
|
||||||
|
case 0x2188: {
|
||||||
|
regs.r2188 = data;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x2189: {
|
||||||
|
regs.r2189 = data;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x218a: {
|
||||||
|
regs.r218a = data;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x218b: {
|
||||||
|
regs.r218b = data;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x218c: {
|
||||||
|
regs.r218c = data;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x218e: {
|
||||||
|
regs.r218e = data;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x218f: {
|
||||||
|
regs.r218e >>= 1;
|
||||||
|
regs.r218e = regs.r218f - regs.r218e;
|
||||||
|
regs.r218f >>= 1;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x2191: {
|
||||||
|
regs.r2191 = data;
|
||||||
|
regs.r2192_counter = 0;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x2192: {
|
||||||
|
regs.r2190 = 0x80;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x2193: {
|
||||||
|
regs.r2193 = data;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x2194: {
|
||||||
|
regs.r2194 = data;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x2197: {
|
||||||
|
regs.r2197 = data;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x2199: {
|
||||||
|
regs.r2199 = data;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //ifdef BSX_CPP
|
99
src/chip/bsx/bsx_cart.cpp
Normal file
99
src/chip/bsx/bsx_cart.cpp
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
#ifdef BSX_CPP
|
||||||
|
|
||||||
|
void BSXCart::init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void BSXCart::enable() {
|
||||||
|
for(uint16 i = 0x5000; i <= 0x5fff; i++) memory::mmio.map(i, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BSXCart::power() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BSXCart::reset() {
|
||||||
|
for(uint i = 0; i < 16; i++) regs.r[i] = 0x00;
|
||||||
|
regs.r[0x07] = 0x80;
|
||||||
|
regs.r[0x08] = 0x80;
|
||||||
|
|
||||||
|
update_memory_map();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BSXCart::update_memory_map() {
|
||||||
|
Memory &cart = (regs.r[0x01] & 0x80) == 0x00 ? (Memory&)bsxflash : (Memory&)psram;
|
||||||
|
|
||||||
|
if((regs.r[0x02] & 0x80) == 0x00) { //LoROM mapping
|
||||||
|
bus.map(Bus::MapLinear, 0x00, 0x7d, 0x8000, 0xffff, cart);
|
||||||
|
bus.map(Bus::MapLinear, 0x80, 0xff, 0x8000, 0xffff, cart);
|
||||||
|
} else { //HiROM mapping
|
||||||
|
bus.map(Bus::MapShadow, 0x00, 0x3f, 0x8000, 0xffff, cart);
|
||||||
|
bus.map(Bus::MapLinear, 0x40, 0x7d, 0x0000, 0xffff, cart);
|
||||||
|
bus.map(Bus::MapShadow, 0x80, 0xbf, 0x8000, 0xffff, cart);
|
||||||
|
bus.map(Bus::MapLinear, 0xc0, 0xff, 0x0000, 0xffff, cart);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(regs.r[0x03] & 0x80) {
|
||||||
|
bus.map(Bus::MapLinear, 0x60, 0x6f, 0x0000, 0xffff, psram);
|
||||||
|
//bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, psram);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((regs.r[0x05] & 0x80) == 0x00) {
|
||||||
|
bus.map(Bus::MapLinear, 0x40, 0x4f, 0x0000, 0xffff, psram);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((regs.r[0x06] & 0x80) == 0x00) {
|
||||||
|
bus.map(Bus::MapLinear, 0x50, 0x5f, 0x0000, 0xffff, psram);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(regs.r[0x07] & 0x80) {
|
||||||
|
bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(regs.r[0x08] & 0x80) {
|
||||||
|
bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
bus.map(Bus::MapShadow, 0x20, 0x3f, 0x6000, 0x7fff, psram);
|
||||||
|
bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, psram);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 BSXCart::mmio_read(uint addr) {
|
||||||
|
if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO
|
||||||
|
uint8 n = (addr >> 16) & 15;
|
||||||
|
return regs.r[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM
|
||||||
|
return sram.read(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BSXCart::mmio_write(uint addr, uint8 data) {
|
||||||
|
if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO
|
||||||
|
uint8 n = (addr >> 16) & 15;
|
||||||
|
regs.r[n] = data;
|
||||||
|
if(n == 0x0e && data & 0x80) update_memory_map();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM
|
||||||
|
return sram.write(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff), data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BSXCart::BSXCart() {
|
||||||
|
sram_data = (uint8*)malloc( 32 * 1024);
|
||||||
|
psram_data = (uint8*)malloc(512 * 1024);
|
||||||
|
|
||||||
|
sram.map (sram_data, 32 * 1024);
|
||||||
|
psram.map(psram_data, 512 * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
BSXCart::~BSXCart() {
|
||||||
|
safe_free(sram_data);
|
||||||
|
safe_free(psram_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //ifdef BSX_CPP
|
113
src/chip/bsx/bsx_flash.cpp
Normal file
113
src/chip/bsx/bsx_flash.cpp
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
#ifdef BSX_CPP
|
||||||
|
|
||||||
|
void BSXFlash::init() {}
|
||||||
|
void BSXFlash::enable() {}
|
||||||
|
|
||||||
|
void BSXFlash::power() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BSXFlash::reset() {
|
||||||
|
regs.command = 0;
|
||||||
|
regs.write_old = 0x00;
|
||||||
|
regs.write_new = 0x00;
|
||||||
|
|
||||||
|
regs.flash_enable = false;
|
||||||
|
regs.read_enable = false;
|
||||||
|
regs.write_enable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint BSXFlash::size() {
|
||||||
|
return memory::bscram.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 BSXFlash::read(uint addr) {
|
||||||
|
if(addr == 0x0002) {
|
||||||
|
if(regs.flash_enable) return 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(addr == 0x5555) {
|
||||||
|
if(regs.flash_enable) return 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(regs.read_enable && addr >= 0xff00 && addr <= 0xff13) {
|
||||||
|
//read flash cartridge vendor information
|
||||||
|
switch(addr - 0xff00) {
|
||||||
|
case 0x00: return 0x4d;
|
||||||
|
case 0x01: return 0x00;
|
||||||
|
case 0x02: return 0x50;
|
||||||
|
case 0x03: return 0x00;
|
||||||
|
case 0x04: return 0x00;
|
||||||
|
case 0x05: return 0x00;
|
||||||
|
case 0x06: return 0x2a; //0x2a = 8mbit, 0x2b = 16mbit (not known to exist, though BIOS recognizes ID)
|
||||||
|
case 0x07: return 0x00;
|
||||||
|
default: return 0x00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return memory::bscram.read(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BSXFlash::write(uint addr, uint8 data) {
|
||||||
|
//there exist both read-only and read-write BS-X flash cartridges ...
|
||||||
|
//unfortunately, the vendor info is not stored inside memory dumps
|
||||||
|
//of BS-X flashcarts, so it is impossible to determine whether a
|
||||||
|
//given flashcart is writeable.
|
||||||
|
//however, it has been observed that LoROM-mapped BS-X carts always
|
||||||
|
//use read-write flashcarts, and HiROM-mapped BS-X carts always use
|
||||||
|
//read-only flashcarts.
|
||||||
|
//below is an unfortunately necessary workaround to this problem.
|
||||||
|
if(cartridge.mapper() == Cartridge::BSCHiROM) return;
|
||||||
|
|
||||||
|
if((addr & 0xff0000) == 0) {
|
||||||
|
regs.write_old = regs.write_new;
|
||||||
|
regs.write_new = data;
|
||||||
|
|
||||||
|
if(regs.write_enable && regs.write_old == regs.write_new) {
|
||||||
|
return memory::bscram.write(addr, data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(regs.write_enable) {
|
||||||
|
return memory::bscram.write(addr, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(addr == 0x0000) {
|
||||||
|
regs.command <<= 8;
|
||||||
|
regs.command |= data;
|
||||||
|
|
||||||
|
if((regs.command & 0xffff) == 0x38d0) {
|
||||||
|
regs.flash_enable = true;
|
||||||
|
regs.read_enable = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(addr == 0x2aaa) {
|
||||||
|
regs.command <<= 8;
|
||||||
|
regs.command |= data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(addr == 0x5555) {
|
||||||
|
regs.command <<= 8;
|
||||||
|
regs.command |= data;
|
||||||
|
|
||||||
|
if((regs.command & 0xffffff) == 0xaa5570) {
|
||||||
|
regs.write_enable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((regs.command & 0xffffff) == 0xaa55a0) {
|
||||||
|
regs.write_old = 0x00;
|
||||||
|
regs.write_new = 0x00;
|
||||||
|
regs.flash_enable = true;
|
||||||
|
regs.write_enable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((regs.command & 0xffffff) == 0xaa55f0) {
|
||||||
|
regs.flash_enable = false;
|
||||||
|
regs.read_enable = false;
|
||||||
|
regs.write_enable = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //ifdef BSX_CPP
|
10
src/chip/chip.h
Normal file
10
src/chip/chip.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include "bsx/bsx.h"
|
||||||
|
#include "srtc/srtc.h"
|
||||||
|
#include "sdd1/sdd1.h"
|
||||||
|
#include "cx4/cx4.h"
|
||||||
|
#include "dsp1/dsp1.h"
|
||||||
|
#include "dsp2/dsp2.h"
|
||||||
|
#include "dsp3/dsp3.h"
|
||||||
|
#include "dsp4/dsp4.h"
|
||||||
|
#include "obc1/obc1.h"
|
||||||
|
#include "st010/st010.h"
|
@@ -6,30 +6,29 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../../base.h"
|
#include "../../base.h"
|
||||||
|
#define CX4_CPP
|
||||||
|
|
||||||
C4 *c4;
|
#include "cx4data.cpp"
|
||||||
|
#include "cx4fn.cpp"
|
||||||
|
#include "cx4oam.cpp"
|
||||||
|
#include "cx4ops.cpp"
|
||||||
|
|
||||||
#include "c4data.cpp"
|
void Cx4::init() {}
|
||||||
#include "c4fn.cpp"
|
void Cx4::enable() {}
|
||||||
#include "c4oam.cpp"
|
|
||||||
#include "c4ops.cpp"
|
|
||||||
|
|
||||||
void C4::init() {}
|
uint32 Cx4::ldr(uint8 r) {
|
||||||
void C4::enable() {}
|
|
||||||
|
|
||||||
uint32 C4::ldr(uint8 r) {
|
|
||||||
uint16 addr = 0x0080 + (r * 3);
|
uint16 addr = 0x0080 + (r * 3);
|
||||||
return (reg[addr]) | (reg[addr + 1] << 8) | (reg[addr + 2] << 16);
|
return (reg[addr]) | (reg[addr + 1] << 8) | (reg[addr + 2] << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4::str(uint8 r, uint32 data) {
|
void Cx4::str(uint8 r, uint32 data) {
|
||||||
uint16 addr = 0x0080 + (r * 3);
|
uint16 addr = 0x0080 + (r * 3);
|
||||||
reg[addr ] = (data);
|
reg[addr ] = (data);
|
||||||
reg[addr + 1] = (data >> 8);
|
reg[addr + 1] = (data >> 8);
|
||||||
reg[addr + 2] = (data >> 16);
|
reg[addr + 2] = (data >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) {
|
void Cx4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) {
|
||||||
int64 rx = x & 0xffffff;
|
int64 rx = x & 0xffffff;
|
||||||
int64 ry = y & 0xffffff;
|
int64 ry = y & 0xffffff;
|
||||||
if(rx & 0x800000)rx |= ~0x7fffff;
|
if(rx & 0x800000)rx |= ~0x7fffff;
|
||||||
@@ -41,7 +40,7 @@ int64 ry = y & 0xffffff;
|
|||||||
rh = (rx >> 24) & 0xffffff;
|
rh = (rx >> 24) & 0xffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 C4::sin(uint32 rx) {
|
uint32 Cx4::sin(uint32 rx) {
|
||||||
r0 = rx & 0x1ff;
|
r0 = rx & 0x1ff;
|
||||||
if(r0 & 0x100)r0 ^= 0x1ff;
|
if(r0 & 0x100)r0 ^= 0x1ff;
|
||||||
if(r0 & 0x080)r0 ^= 0x0ff;
|
if(r0 & 0x080)r0 ^= 0x0ff;
|
||||||
@@ -52,13 +51,13 @@ uint32 C4::sin(uint32 rx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 C4::cos(uint32 rx) {
|
uint32 Cx4::cos(uint32 rx) {
|
||||||
return sin(rx + 0x080);
|
return sin(rx + 0x080);
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4::immediate_reg(uint32 start) {
|
void Cx4::immediate_reg(uint32 start) {
|
||||||
r0 = ldr(0);
|
r0 = ldr(0);
|
||||||
for(uint32 i=start;i<48;i++) {
|
for(uint32 i = start; i < 48; i++) {
|
||||||
if((r0 & 0x0fff) < 0x0c00) {
|
if((r0 & 0x0fff) < 0x0c00) {
|
||||||
ram[r0 & 0x0fff] = immediate_data[i];
|
ram[r0 & 0x0fff] = immediate_data[i];
|
||||||
}
|
}
|
||||||
@@ -67,7 +66,7 @@ void C4::immediate_reg(uint32 start) {
|
|||||||
str(0, r0);
|
str(0, r0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4::transfer_data() {
|
void Cx4::transfer_data() {
|
||||||
uint32 src;
|
uint32 src;
|
||||||
uint16 dest, count;
|
uint16 dest, count;
|
||||||
src = (reg[0x40]) | (reg[0x41] << 8) | (reg[0x42] << 16);
|
src = (reg[0x40]) | (reg[0x41] << 8) | (reg[0x42] << 16);
|
||||||
@@ -75,11 +74,11 @@ uint16 dest, count;
|
|||||||
dest = (reg[0x45]) | (reg[0x46] << 8);
|
dest = (reg[0x45]) | (reg[0x46] << 8);
|
||||||
|
|
||||||
for(uint32 i=0;i<count;i++) {
|
for(uint32 i=0;i<count;i++) {
|
||||||
write(dest++, r_mem->read(src++));
|
write(dest++, bus.read(src++));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4::write(uint16 addr, uint8 data) {
|
void Cx4::write(uint addr, uint8 data) {
|
||||||
addr &= 0x1fff;
|
addr &= 0x1fff;
|
||||||
|
|
||||||
if(addr < 0x0c00) {
|
if(addr < 0x0c00) {
|
||||||
@@ -111,57 +110,57 @@ void C4::write(uint16 addr, uint8 data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch(data) {
|
switch(data) {
|
||||||
case 0x00:op00();break;
|
case 0x00: op00(); break;
|
||||||
case 0x01:op01();break;
|
case 0x01: op01(); break;
|
||||||
case 0x05:op05();break;
|
case 0x05: op05(); break;
|
||||||
case 0x0d:op0d();break;
|
case 0x0d: op0d(); break;
|
||||||
case 0x10:op10();break;
|
case 0x10: op10(); break;
|
||||||
case 0x13:op13();break;
|
case 0x13: op13(); break;
|
||||||
case 0x15:op15();break;
|
case 0x15: op15(); break;
|
||||||
case 0x1f:op1f();break;
|
case 0x1f: op1f(); break;
|
||||||
case 0x22:op22();break;
|
case 0x22: op22(); break;
|
||||||
case 0x25:op25();break;
|
case 0x25: op25(); break;
|
||||||
case 0x2d:op2d();break;
|
case 0x2d: op2d(); break;
|
||||||
case 0x40:op40();break;
|
case 0x40: op40(); break;
|
||||||
case 0x54:op54();break;
|
case 0x54: op54(); break;
|
||||||
case 0x5c:op5c();break;
|
case 0x5c: op5c(); break;
|
||||||
case 0x5e:op5e();break;
|
case 0x5e: op5e(); break;
|
||||||
case 0x60:op60();break;
|
case 0x60: op60(); break;
|
||||||
case 0x62:op62();break;
|
case 0x62: op62(); break;
|
||||||
case 0x64:op64();break;
|
case 0x64: op64(); break;
|
||||||
case 0x66:op66();break;
|
case 0x66: op66(); break;
|
||||||
case 0x68:op68();break;
|
case 0x68: op68(); break;
|
||||||
case 0x6a:op6a();break;
|
case 0x6a: op6a(); break;
|
||||||
case 0x6c:op6c();break;
|
case 0x6c: op6c(); break;
|
||||||
case 0x6e:op6e();break;
|
case 0x6e: op6e(); break;
|
||||||
case 0x70:op70();break;
|
case 0x70: op70(); break;
|
||||||
case 0x72:op72();break;
|
case 0x72: op72(); break;
|
||||||
case 0x74:op74();break;
|
case 0x74: op74(); break;
|
||||||
case 0x76:op76();break;
|
case 0x76: op76(); break;
|
||||||
case 0x78:op78();break;
|
case 0x78: op78(); break;
|
||||||
case 0x7a:op7a();break;
|
case 0x7a: op7a(); break;
|
||||||
case 0x7c:op7c();break;
|
case 0x7c: op7c(); break;
|
||||||
case 0x89:op89();break;
|
case 0x89: op89(); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4::writeb(uint16 addr, uint8 data) {
|
void Cx4::writeb(uint16 addr, uint8 data) {
|
||||||
write(addr, data);
|
write(addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4::writew(uint16 addr, uint16 data) {
|
void Cx4::writew(uint16 addr, uint16 data) {
|
||||||
write(addr, data);
|
write(addr, data);
|
||||||
write(addr + 1, data >> 8);
|
write(addr + 1, data >> 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4::writel(uint16 addr, uint32 data) {
|
void Cx4::writel(uint16 addr, uint32 data) {
|
||||||
write(addr, data);
|
write(addr, data);
|
||||||
write(addr + 1, data >> 8);
|
write(addr + 1, data >> 8);
|
||||||
write(addr + 2, data >> 16);
|
write(addr + 2, data >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 C4::read(uint16 addr) {
|
uint8 Cx4::read(uint addr) {
|
||||||
addr &= 0x1fff;
|
addr &= 0x1fff;
|
||||||
|
|
||||||
if(addr < 0x0c00) {
|
if(addr < 0x0c00) {
|
||||||
@@ -172,28 +171,26 @@ uint8 C4::read(uint16 addr) {
|
|||||||
return reg[addr & 0xff];
|
return reg[addr & 0xff];
|
||||||
}
|
}
|
||||||
|
|
||||||
return r_cpu->regs.mdr;
|
return cpu.regs.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 C4::readb(uint16 addr) {
|
uint8 Cx4::readb(uint16 addr) {
|
||||||
return read(addr);
|
return read(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 C4::readw(uint16 addr) {
|
uint16 Cx4::readw(uint16 addr) {
|
||||||
return read(addr) | (read(addr + 1) << 8);
|
return read(addr) | (read(addr + 1) << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 C4::readl(uint16 addr) {
|
uint32 Cx4::readl(uint16 addr) {
|
||||||
return read(addr) | (read(addr + 1) << 8) + (read(addr + 2) << 16);
|
return read(addr) | (read(addr + 1) << 8) + (read(addr + 2) << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4::power() {
|
void Cx4::power() {
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4::reset() {
|
void Cx4::reset() {
|
||||||
memset(ram, 0, 0x0c00);
|
memset(ram, 0, 0x0c00);
|
||||||
memset(reg, 0, 0x0100);
|
memset(reg, 0, 0x0100);
|
||||||
}
|
}
|
||||||
|
|
||||||
C4::C4() {}
|
|
@@ -1,29 +1,29 @@
|
|||||||
class C4 {
|
class Cx4 : public Memory {
|
||||||
private:
|
private:
|
||||||
uint8 ram[0x0c00];
|
uint8 ram[0x0c00];
|
||||||
uint8 reg[0x0100];
|
uint8 reg[0x0100];
|
||||||
uint32 r0, r1, r2, r3, r4, r5, r6, r7,
|
uint32 r0, r1, r2, r3, r4, r5, r6, r7,
|
||||||
r8, r9, r10, r11, r12, r13, r14, r15;
|
r8, r9, r10, r11, r12, r13, r14, r15;
|
||||||
|
|
||||||
static const uint8 immediate_data[48];
|
static const uint8 immediate_data[48];
|
||||||
static const uint16 wave_data[40];
|
static const uint16 wave_data[40];
|
||||||
static const uint32 sin_table[256];
|
static const uint32 sin_table[256];
|
||||||
|
|
||||||
static const int16 SinTable[512];
|
static const int16 SinTable[512];
|
||||||
static const int16 CosTable[512];
|
static const int16 CosTable[512];
|
||||||
|
|
||||||
int16 C4WFXVal, C4WFYVal, C4WFZVal, C4WFX2Val, C4WFY2Val, C4WFDist, C4WFScale;
|
int16 C4WFXVal, C4WFYVal, C4WFZVal, C4WFX2Val, C4WFY2Val, C4WFDist, C4WFScale;
|
||||||
int16 C41FXVal, C41FYVal, C41FAngleRes, C41FDist, C41FDistVal;
|
int16 C41FXVal, C41FYVal, C41FAngleRes, C41FDist, C41FDistVal;
|
||||||
|
|
||||||
double tanval;
|
double tanval;
|
||||||
double c4x,c4y,c4z, c4x2,c4y2,c4z2;
|
double c4x,c4y,c4z, c4x2,c4y2,c4z2;
|
||||||
|
|
||||||
void C4TransfWireFrame();
|
void C4TransfWireFrame();
|
||||||
void C4TransfWireFrame2();
|
void C4TransfWireFrame2();
|
||||||
void C4CalcWireFrame();
|
void C4CalcWireFrame();
|
||||||
void C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color);
|
void C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color);
|
||||||
void C4DrawWireFrame();
|
void C4DrawWireFrame();
|
||||||
void C4DoScaleRotate(int row_padding);
|
void C4DoScaleRotate(int row_padding);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint32 ldr(uint8 r);
|
uint32 ldr(uint8 r);
|
||||||
@@ -75,22 +75,23 @@ public:
|
|||||||
void op7c();
|
void op7c();
|
||||||
void op89();
|
void op89();
|
||||||
|
|
||||||
|
uint8 readb(uint16 addr);
|
||||||
|
uint16 readw(uint16 addr);
|
||||||
|
uint32 readl(uint16 addr);
|
||||||
|
|
||||||
|
void writeb(uint16 addr, uint8 data);
|
||||||
|
void writew(uint16 addr, uint16 data);
|
||||||
|
void writel(uint16 addr, uint32 data);
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void enable();
|
void enable();
|
||||||
void power();
|
void power();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
void write (uint16 addr, uint8 data);
|
uint8 read (uint addr);
|
||||||
void writeb(uint16 addr, uint8 data);
|
void write(uint addr, uint8 data);
|
||||||
void writew(uint16 addr, uint16 data);
|
|
||||||
void writel(uint16 addr, uint32 data);
|
|
||||||
|
|
||||||
uint8 read (uint16 addr);
|
|
||||||
uint8 readb(uint16 addr);
|
|
||||||
uint16 readw(uint16 addr);
|
|
||||||
uint32 readl(uint16 addr);
|
|
||||||
|
|
||||||
C4();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern C4 *c4;
|
extern Cx4 cx4;
|
@@ -1,11 +1,13 @@
|
|||||||
const uint8 C4::immediate_data[48] = {
|
#ifdef CX4_CPP
|
||||||
|
|
||||||
|
const uint8 Cx4::immediate_data[48] = {
|
||||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||||
0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x80, 0xff, 0xff, 0x7f,
|
0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x80, 0xff, 0xff, 0x7f,
|
||||||
0x00, 0x80, 0x00, 0xff, 0x7f, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0xff,
|
0x00, 0x80, 0x00, 0xff, 0x7f, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0xff,
|
||||||
0x00, 0x00, 0x01, 0xff, 0xff, 0xfe, 0x00, 0x01, 0x00, 0xff, 0xfe, 0x00
|
0x00, 0x00, 0x01, 0xff, 0xff, 0xfe, 0x00, 0x01, 0x00, 0xff, 0xfe, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint16 C4::wave_data[40] = {
|
const uint16 Cx4::wave_data[40] = {
|
||||||
0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e,
|
0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e,
|
||||||
0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020a, 0x020c, 0x020e,
|
0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020a, 0x020c, 0x020e,
|
||||||
0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040a, 0x040c, 0x040e,
|
0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040a, 0x040c, 0x040e,
|
||||||
@@ -13,7 +15,7 @@ const uint16 C4::wave_data[40] = {
|
|||||||
0x0800, 0x0802, 0x0804, 0x0806, 0x0808, 0x080a, 0x080c, 0x080e
|
0x0800, 0x0802, 0x0804, 0x0806, 0x0808, 0x080a, 0x080c, 0x080e
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint32 C4::sin_table[256] = {
|
const uint32 Cx4::sin_table[256] = {
|
||||||
0x000000, 0x000324, 0x000648, 0x00096c, 0x000c8f, 0x000fb2, 0x0012d5, 0x0015f6,
|
0x000000, 0x000324, 0x000648, 0x00096c, 0x000c8f, 0x000fb2, 0x0012d5, 0x0015f6,
|
||||||
0x001917, 0x001c37, 0x001f56, 0x002273, 0x002590, 0x0028aa, 0x002bc4, 0x002edb,
|
0x001917, 0x001c37, 0x001f56, 0x002273, 0x002590, 0x0028aa, 0x002bc4, 0x002edb,
|
||||||
0x0031f1, 0x003505, 0x003817, 0x003b26, 0x003e33, 0x00413e, 0x004447, 0x00474d,
|
0x0031f1, 0x003505, 0x003817, 0x003b26, 0x003e33, 0x00413e, 0x004447, 0x00474d,
|
||||||
@@ -48,7 +50,7 @@ const uint32 C4::sin_table[256] = {
|
|||||||
0xff013b, 0xff00f1, 0xff00b1, 0xff007b, 0xff004e, 0xff002c, 0xff0013, 0xff0004
|
0xff013b, 0xff00f1, 0xff00b1, 0xff007b, 0xff004e, 0xff002c, 0xff0013, 0xff0004
|
||||||
};
|
};
|
||||||
|
|
||||||
const int16 C4::SinTable[512] = {
|
const int16 Cx4::SinTable[512] = {
|
||||||
0, 402, 804, 1206, 1607, 2009, 2410, 2811,
|
0, 402, 804, 1206, 1607, 2009, 2410, 2811,
|
||||||
3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997,
|
3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997,
|
||||||
6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126,
|
6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126,
|
||||||
@@ -115,7 +117,7 @@ const int16 C4::SinTable[512] = {
|
|||||||
-3211, -2811, -2410, -2009, -1607, -1206, -804, -402
|
-3211, -2811, -2410, -2009, -1607, -1206, -804, -402
|
||||||
};
|
};
|
||||||
|
|
||||||
const int16 C4::CosTable[512] = {
|
const int16 Cx4::CosTable[512] = {
|
||||||
32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647,
|
32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647,
|
||||||
32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214,
|
32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214,
|
||||||
32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471,
|
32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471,
|
||||||
@@ -181,3 +183,5 @@ const int16 C4::CosTable[512] = {
|
|||||||
32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568,
|
32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568,
|
||||||
32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765
|
32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif //ifdef CX4_CPP
|
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef CX4_CPP
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#define Tan(a) (CosTable[a] ? ((((int32)SinTable[a]) << 16) / CosTable[a]) : 0x80000000)
|
#define Tan(a) (CosTable[a] ? ((((int32)SinTable[a]) << 16) / CosTable[a]) : 0x80000000)
|
||||||
#define sar(b, n) ((b) >> (n))
|
#define sar(b, n) ((b) >> (n))
|
||||||
@@ -7,7 +9,7 @@
|
|||||||
#define PI 3.1415926535897932384626433832795
|
#define PI 3.1415926535897932384626433832795
|
||||||
|
|
||||||
//Wireframe Helpers
|
//Wireframe Helpers
|
||||||
void C4::C4TransfWireFrame() {
|
void Cx4::C4TransfWireFrame() {
|
||||||
c4x = (double)C4WFXVal;
|
c4x = (double)C4WFXVal;
|
||||||
c4y = (double)C4WFYVal;
|
c4y = (double)C4WFYVal;
|
||||||
c4z = (double)C4WFZVal - 0x95;
|
c4z = (double)C4WFZVal - 0x95;
|
||||||
@@ -32,7 +34,7 @@ void C4::C4TransfWireFrame() {
|
|||||||
C4WFYVal = (int16)(c4y * C4WFScale / (0x90 * (c4z + 0x95)) * 0x95);
|
C4WFYVal = (int16)(c4y * C4WFScale / (0x90 * (c4z + 0x95)) * 0x95);
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4::C4CalcWireFrame() {
|
void Cx4::C4CalcWireFrame() {
|
||||||
C4WFXVal = C4WFX2Val - C4WFXVal;
|
C4WFXVal = C4WFX2Val - C4WFXVal;
|
||||||
C4WFYVal = C4WFY2Val - C4WFYVal;
|
C4WFYVal = C4WFY2Val - C4WFYVal;
|
||||||
|
|
||||||
@@ -49,7 +51,7 @@ void C4::C4CalcWireFrame() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4::C4TransfWireFrame2() {
|
void Cx4::C4TransfWireFrame2() {
|
||||||
c4x = (double)C4WFXVal;
|
c4x = (double)C4WFXVal;
|
||||||
c4y = (double)C4WFYVal;
|
c4y = (double)C4WFYVal;
|
||||||
c4z = (double)C4WFZVal;
|
c4z = (double)C4WFZVal;
|
||||||
@@ -74,34 +76,34 @@ void C4::C4TransfWireFrame2() {
|
|||||||
C4WFYVal = (int16)(c4y * C4WFScale / 0x100);
|
C4WFYVal = (int16)(c4y * C4WFScale / 0x100);
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4::C4DrawWireFrame() {
|
void Cx4::C4DrawWireFrame() {
|
||||||
uint32 line = readl(0x1f80);
|
uint32 line = readl(0x1f80);
|
||||||
uint32 point1, point2;
|
uint32 point1, point2;
|
||||||
int16 X1, Y1, Z1;
|
int16 X1, Y1, Z1;
|
||||||
int16 X2, Y2, Z2;
|
int16 X2, Y2, Z2;
|
||||||
uint8 Color;
|
uint8 Color;
|
||||||
for(int32 i = ram[0x0295]; i > 0; i--, line += 5) {
|
for(int32 i = ram[0x0295]; i > 0; i--, line += 5) {
|
||||||
if(r_mem->read(line) == 0xff && r_mem->read(line + 1) == 0xff) {
|
if(bus.read(line) == 0xff && bus.read(line + 1) == 0xff) {
|
||||||
int32 tmp = line - 5;
|
int32 tmp = line - 5;
|
||||||
while(r_mem->read(tmp + 2) == 0xff && r_mem->read(tmp + 3) == 0xff && (tmp + 2) >= 0) { tmp -= 5; }
|
while(bus.read(tmp + 2) == 0xff && bus.read(tmp + 3) == 0xff && (tmp + 2) >= 0) { tmp -= 5; }
|
||||||
point1 = (read(0x1f82) << 16) | (r_mem->read(tmp + 2) << 8) | r_mem->read(tmp + 3);
|
point1 = (read(0x1f82) << 16) | (bus.read(tmp + 2) << 8) | bus.read(tmp + 3);
|
||||||
} else {
|
} else {
|
||||||
point1 = (read(0x1f82) << 16) | (r_mem->read(line) << 8) | r_mem->read(line + 1);
|
point1 = (read(0x1f82) << 16) | (bus.read(line) << 8) | bus.read(line + 1);
|
||||||
}
|
}
|
||||||
point2 = (read(0x1f82) << 16) | (r_mem->read(line + 2) << 8) | r_mem->read(line + 3);
|
point2 = (read(0x1f82) << 16) | (bus.read(line + 2) << 8) | bus.read(line + 3);
|
||||||
|
|
||||||
X1=(r_mem->read(point1 + 0) << 8) | r_mem->read(point1 + 1);
|
X1=(bus.read(point1 + 0) << 8) | bus.read(point1 + 1);
|
||||||
Y1=(r_mem->read(point1 + 2) << 8) | r_mem->read(point1 + 3);
|
Y1=(bus.read(point1 + 2) << 8) | bus.read(point1 + 3);
|
||||||
Z1=(r_mem->read(point1 + 4) << 8) | r_mem->read(point1 + 5);
|
Z1=(bus.read(point1 + 4) << 8) | bus.read(point1 + 5);
|
||||||
X2=(r_mem->read(point2 + 0) << 8) | r_mem->read(point2 + 1);
|
X2=(bus.read(point2 + 0) << 8) | bus.read(point2 + 1);
|
||||||
Y2=(r_mem->read(point2 + 2) << 8) | r_mem->read(point2 + 3);
|
Y2=(bus.read(point2 + 2) << 8) | bus.read(point2 + 3);
|
||||||
Z2=(r_mem->read(point2 + 4) << 8) | r_mem->read(point2 + 5);
|
Z2=(bus.read(point2 + 4) << 8) | bus.read(point2 + 5);
|
||||||
Color = r_mem->read(line + 4);
|
Color = bus.read(line + 4);
|
||||||
C4DrawLine(X1, Y1, Z1, X2, Y2, Z2, Color);
|
C4DrawLine(X1, Y1, Z1, X2, Y2, Z2, Color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color) {
|
void Cx4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color) {
|
||||||
//Transform coordinates
|
//Transform coordinates
|
||||||
C4WFXVal = (int16)X1;
|
C4WFXVal = (int16)X1;
|
||||||
C4WFYVal = (int16)Y1;
|
C4WFYVal = (int16)Y1;
|
||||||
@@ -145,7 +147,7 @@ void C4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4::C4DoScaleRotate(int row_padding) {
|
void Cx4::C4DoScaleRotate(int row_padding) {
|
||||||
int16 A, B, C, D;
|
int16 A, B, C, D;
|
||||||
|
|
||||||
//Calculate matrix
|
//Calculate matrix
|
||||||
@@ -240,3 +242,5 @@ uint8 bit = 0x80;
|
|||||||
LineY += D;
|
LineY += D;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif //ifdef CX4_CPP
|
@@ -1,5 +1,7 @@
|
|||||||
|
#ifdef CX4_CPP
|
||||||
|
|
||||||
//Build OAM
|
//Build OAM
|
||||||
void C4::op00_00() {
|
void Cx4::op00_00() {
|
||||||
uint32 oamptr = ram[0x626] << 2;
|
uint32 oamptr = ram[0x626] << 2;
|
||||||
for(int32 i = 0x1fd; i > oamptr && i >= 0; i -= 4) {
|
for(int32 i = 0x1fd; i > oamptr && i >= 0; i -= 4) {
|
||||||
//clear oam-to-be
|
//clear oam-to-be
|
||||||
@@ -27,28 +29,28 @@ uint32 srcptr = 0x220;
|
|||||||
sprattr = ram[srcptr + 4] | ram[srcptr + 6];
|
sprattr = ram[srcptr + 4] | ram[srcptr + 6];
|
||||||
|
|
||||||
uint32 spraddr = readl(srcptr + 7);
|
uint32 spraddr = readl(srcptr + 7);
|
||||||
if(r_mem->read(spraddr)) {
|
if(bus.read(spraddr)) {
|
||||||
int16 x, y;
|
int16 x, y;
|
||||||
for(int sprcnt = r_mem->read(spraddr++); sprcnt > 0 && sprcount > 0; sprcnt--, spraddr += 4) {
|
for(int sprcnt = bus.read(spraddr++); sprcnt > 0 && sprcount > 0; sprcnt--, spraddr += 4) {
|
||||||
x = (int8)r_mem->read(spraddr + 1);
|
x = (int8)bus.read(spraddr + 1);
|
||||||
if(sprattr & 0x40) {
|
if(sprattr & 0x40) {
|
||||||
x = -x - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
|
x = -x - ((bus.read(spraddr) & 0x20) ? 16 : 8);
|
||||||
}
|
}
|
||||||
x += sprx;
|
x += sprx;
|
||||||
if(x >= -16 && x <= 272) {
|
if(x >= -16 && x <= 272) {
|
||||||
y = (int8)r_mem->read(spraddr + 2);
|
y = (int8)bus.read(spraddr + 2);
|
||||||
if(sprattr & 0x80) {
|
if(sprattr & 0x80) {
|
||||||
y = -y - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
|
y = -y - ((bus.read(spraddr) & 0x20) ? 16 : 8);
|
||||||
}
|
}
|
||||||
y += spry;
|
y += spry;
|
||||||
if(y >= -16 && y <= 224) {
|
if(y >= -16 && y <= 224) {
|
||||||
ram[oamptr ] = (uint8)x;
|
ram[oamptr ] = (uint8)x;
|
||||||
ram[oamptr + 1] = (uint8)y;
|
ram[oamptr + 1] = (uint8)y;
|
||||||
ram[oamptr + 2] = sprname + r_mem->read(spraddr + 3);
|
ram[oamptr + 2] = sprname + bus.read(spraddr + 3);
|
||||||
ram[oamptr + 3] = sprattr ^ (r_mem->read(spraddr) & 0xc0);
|
ram[oamptr + 3] = sprattr ^ (bus.read(spraddr) & 0xc0);
|
||||||
ram[oamptr2] &= ~(3 << offset);
|
ram[oamptr2] &= ~(3 << offset);
|
||||||
if(x & 0x100)ram[oamptr2] |= 1 << offset;
|
if(x & 0x100)ram[oamptr2] |= 1 << offset;
|
||||||
if(r_mem->read(spraddr) & 0x20)ram[oamptr2] |= 2 << offset;
|
if(bus.read(spraddr) & 0x20)ram[oamptr2] |= 2 << offset;
|
||||||
oamptr += 4;
|
oamptr += 4;
|
||||||
sprcount--;
|
sprcount--;
|
||||||
offset = (offset + 2) & 6;
|
offset = (offset + 2) & 6;
|
||||||
@@ -73,12 +75,12 @@ uint32 srcptr = 0x220;
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Scale and Rotate
|
//Scale and Rotate
|
||||||
void C4::op00_03() {
|
void Cx4::op00_03() {
|
||||||
C4DoScaleRotate(0);
|
C4DoScaleRotate(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Transform Lines
|
//Transform Lines
|
||||||
void C4::op00_05() {
|
void Cx4::op00_05() {
|
||||||
C4WFX2Val = read(0x1f83);
|
C4WFX2Val = read(0x1f83);
|
||||||
C4WFY2Val = read(0x1f86);
|
C4WFY2Val = read(0x1f86);
|
||||||
C4WFDist = read(0x1f89);
|
C4WFDist = read(0x1f89);
|
||||||
@@ -119,17 +121,17 @@ uint32 ptr2 = 0;
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Scale and Rotate
|
//Scale and Rotate
|
||||||
void C4::op00_07() {
|
void Cx4::op00_07() {
|
||||||
C4DoScaleRotate(64);
|
C4DoScaleRotate(64);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Draw Wireframe
|
//Draw Wireframe
|
||||||
void C4::op00_08() {
|
void Cx4::op00_08() {
|
||||||
C4DrawWireFrame();
|
C4DrawWireFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Disintegrate
|
//Disintegrate
|
||||||
void C4::op00_0b() {
|
void Cx4::op00_0b() {
|
||||||
uint8 width, height;
|
uint8 width, height;
|
||||||
uint32 startx, starty;
|
uint32 startx, starty;
|
||||||
uint32 srcptr;
|
uint32 srcptr;
|
||||||
@@ -169,7 +171,7 @@ int32 i, j;
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Bitplane Wave
|
//Bitplane Wave
|
||||||
void C4::op00_0c() {
|
void Cx4::op00_0c() {
|
||||||
uint32 destptr = 0;
|
uint32 destptr = 0;
|
||||||
uint32 waveptr = read(0x1f83);
|
uint32 waveptr = read(0x1f83);
|
||||||
uint16 mask1 = 0xc0c0;
|
uint16 mask1 = 0xc0c0;
|
||||||
@@ -217,3 +219,5 @@ uint16 mask2 = 0x3f3f;
|
|||||||
destptr += 16;
|
destptr += 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif //ifdef CX4_CPP
|
@@ -1,5 +1,7 @@
|
|||||||
|
#ifdef CX4_CPP
|
||||||
|
|
||||||
//Sprite Functions
|
//Sprite Functions
|
||||||
void C4::op00() {
|
void Cx4::op00() {
|
||||||
switch(reg[0x4d]) {
|
switch(reg[0x4d]) {
|
||||||
case 0x00:op00_00();break;
|
case 0x00:op00_00();break;
|
||||||
case 0x03:op00_03();break;
|
case 0x03:op00_03();break;
|
||||||
@@ -12,13 +14,13 @@ void C4::op00() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Draw Wireframe
|
//Draw Wireframe
|
||||||
void C4::op01() {
|
void Cx4::op01() {
|
||||||
memset(ram + 0x300, 0, 2304);
|
memset(ram + 0x300, 0, 2304);
|
||||||
C4DrawWireFrame();
|
C4DrawWireFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Propulsion
|
//Propulsion
|
||||||
void C4::op05() {
|
void Cx4::op05() {
|
||||||
int32 temp = 0x10000;
|
int32 temp = 0x10000;
|
||||||
if(readw(0x1f83)) {
|
if(readw(0x1f83)) {
|
||||||
temp = sar((temp / readw(0x1f83)) * readw(0x1f81), 8);
|
temp = sar((temp / readw(0x1f83)) * readw(0x1f81), 8);
|
||||||
@@ -27,7 +29,7 @@ int32 temp = 0x10000;
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Set Vector length
|
//Set Vector length
|
||||||
void C4::op0d() {
|
void Cx4::op0d() {
|
||||||
C41FXVal = readw(0x1f80);
|
C41FXVal = readw(0x1f80);
|
||||||
C41FYVal = readw(0x1f83);
|
C41FYVal = readw(0x1f83);
|
||||||
C41FDistVal = readw(0x1f86);
|
C41FDistVal = readw(0x1f86);
|
||||||
@@ -40,7 +42,7 @@ void C4::op0d() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Triangle
|
//Triangle
|
||||||
void C4::op10() {
|
void Cx4::op10() {
|
||||||
r0 = ldr(0);
|
r0 = ldr(0);
|
||||||
r1 = ldr(1);
|
r1 = ldr(1);
|
||||||
|
|
||||||
@@ -64,7 +66,7 @@ void C4::op10() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Triangle
|
//Triangle
|
||||||
void C4::op13() {
|
void Cx4::op13() {
|
||||||
r0 = ldr(0);
|
r0 = ldr(0);
|
||||||
r1 = ldr(1);
|
r1 = ldr(1);
|
||||||
|
|
||||||
@@ -87,7 +89,7 @@ void C4::op13() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Pythagorean
|
//Pythagorean
|
||||||
void C4::op15() {
|
void Cx4::op15() {
|
||||||
C41FXVal = readw(0x1f80);
|
C41FXVal = readw(0x1f80);
|
||||||
C41FYVal = readw(0x1f83);
|
C41FYVal = readw(0x1f83);
|
||||||
C41FDist = (int16)sqrt((double)C41FXVal * (double)C41FXVal + (double)C41FYVal * (double)C41FYVal);
|
C41FDist = (int16)sqrt((double)C41FXVal * (double)C41FXVal + (double)C41FYVal * (double)C41FYVal);
|
||||||
@@ -95,7 +97,7 @@ void C4::op15() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Calculate distance
|
//Calculate distance
|
||||||
void C4::op1f() {
|
void Cx4::op1f() {
|
||||||
C41FXVal = readw(0x1f80);
|
C41FXVal = readw(0x1f80);
|
||||||
C41FYVal = readw(0x1f83);
|
C41FYVal = readw(0x1f83);
|
||||||
if(!C41FXVal) {
|
if(!C41FXVal) {
|
||||||
@@ -113,7 +115,7 @@ void C4::op1f() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Trapezoid
|
//Trapezoid
|
||||||
void C4::op22() {
|
void Cx4::op22() {
|
||||||
int16 angle1 = readw(0x1f8c) & 0x1ff;
|
int16 angle1 = readw(0x1f8c) & 0x1ff;
|
||||||
int16 angle2 = readw(0x1f8f) & 0x1ff;
|
int16 angle2 = readw(0x1f8f) & 0x1ff;
|
||||||
int32 tan1 = Tan(angle1);
|
int32 tan1 = Tan(angle1);
|
||||||
@@ -152,7 +154,7 @@ int16 left, right;
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Multiply
|
//Multiply
|
||||||
void C4::op25() {
|
void Cx4::op25() {
|
||||||
r0 = ldr(0);
|
r0 = ldr(0);
|
||||||
r1 = ldr(1);
|
r1 = ldr(1);
|
||||||
mul(r0, r1, r0, r1);
|
mul(r0, r1, r0, r1);
|
||||||
@@ -161,7 +163,7 @@ void C4::op25() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Transform Coords
|
//Transform Coords
|
||||||
void C4::op2d() {
|
void Cx4::op2d() {
|
||||||
C4WFXVal = readw(0x1f81);
|
C4WFXVal = readw(0x1f81);
|
||||||
C4WFYVal = readw(0x1f84);
|
C4WFYVal = readw(0x1f84);
|
||||||
C4WFZVal = readw(0x1f87);
|
C4WFZVal = readw(0x1f87);
|
||||||
@@ -175,7 +177,7 @@ void C4::op2d() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Sum
|
//Sum
|
||||||
void C4::op40() {
|
void Cx4::op40() {
|
||||||
r0 = 0;
|
r0 = 0;
|
||||||
for(uint32 i=0;i<0x800;i++) {
|
for(uint32 i=0;i<0x800;i++) {
|
||||||
r0 += ram[i];
|
r0 += ram[i];
|
||||||
@@ -184,7 +186,7 @@ void C4::op40() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Square
|
//Square
|
||||||
void C4::op54() {
|
void Cx4::op54() {
|
||||||
r0 = ldr(0);
|
r0 = ldr(0);
|
||||||
mul(r0, r0, r1, r2);
|
mul(r0, r0, r1, r2);
|
||||||
str(1, r1);
|
str(1, r1);
|
||||||
@@ -192,31 +194,33 @@ void C4::op54() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Immediate Register
|
//Immediate Register
|
||||||
void C4::op5c() {
|
void Cx4::op5c() {
|
||||||
str(0, 0x000000);
|
str(0, 0x000000);
|
||||||
immediate_reg(0);
|
immediate_reg(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Immediate Register (Multiple)
|
//Immediate Register (Multiple)
|
||||||
void C4::op5e() { immediate_reg( 0); }
|
void Cx4::op5e() { immediate_reg( 0); }
|
||||||
void C4::op60() { immediate_reg( 3); }
|
void Cx4::op60() { immediate_reg( 3); }
|
||||||
void C4::op62() { immediate_reg( 6); }
|
void Cx4::op62() { immediate_reg( 6); }
|
||||||
void C4::op64() { immediate_reg( 9); }
|
void Cx4::op64() { immediate_reg( 9); }
|
||||||
void C4::op66() { immediate_reg(12); }
|
void Cx4::op66() { immediate_reg(12); }
|
||||||
void C4::op68() { immediate_reg(15); }
|
void Cx4::op68() { immediate_reg(15); }
|
||||||
void C4::op6a() { immediate_reg(18); }
|
void Cx4::op6a() { immediate_reg(18); }
|
||||||
void C4::op6c() { immediate_reg(21); }
|
void Cx4::op6c() { immediate_reg(21); }
|
||||||
void C4::op6e() { immediate_reg(24); }
|
void Cx4::op6e() { immediate_reg(24); }
|
||||||
void C4::op70() { immediate_reg(27); }
|
void Cx4::op70() { immediate_reg(27); }
|
||||||
void C4::op72() { immediate_reg(30); }
|
void Cx4::op72() { immediate_reg(30); }
|
||||||
void C4::op74() { immediate_reg(33); }
|
void Cx4::op74() { immediate_reg(33); }
|
||||||
void C4::op76() { immediate_reg(36); }
|
void Cx4::op76() { immediate_reg(36); }
|
||||||
void C4::op78() { immediate_reg(39); }
|
void Cx4::op78() { immediate_reg(39); }
|
||||||
void C4::op7a() { immediate_reg(42); }
|
void Cx4::op7a() { immediate_reg(42); }
|
||||||
void C4::op7c() { immediate_reg(45); }
|
void Cx4::op7c() { immediate_reg(45); }
|
||||||
|
|
||||||
//Immediate ROM
|
//Immediate ROM
|
||||||
void C4::op89() {
|
void Cx4::op89() {
|
||||||
str(0, 0x054336);
|
str(0, 0x054336);
|
||||||
str(1, 0xffffff);
|
str(1, 0xffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif //ifdef CX4_CPP
|
@@ -1,6 +1,5 @@
|
|||||||
#include "../../base.h"
|
#include "../../base.h"
|
||||||
|
#define DSP1_CPP
|
||||||
DSP1 *dsp1;
|
|
||||||
|
|
||||||
#include "dsp1emu.cpp"
|
#include "dsp1emu.cpp"
|
||||||
|
|
||||||
@@ -28,29 +27,30 @@ void DSP1::reset() {
|
|||||||
*****/
|
*****/
|
||||||
bool DSP1::addr_decode(uint16 addr) {
|
bool DSP1::addr_decode(uint16 addr) {
|
||||||
switch(cartridge.info.dsp1_mapper) {
|
switch(cartridge.info.dsp1_mapper) {
|
||||||
|
case Cartridge::DSP1LoROM1MB: {
|
||||||
case Cartridge::DSP1_LOROM_1MB:
|
|
||||||
//$[20-3f]:[8000-bfff] = DR, $[20-3f]:[c000-ffff] = SR
|
//$[20-3f]:[8000-bfff] = DR, $[20-3f]:[c000-ffff] = SR
|
||||||
return (addr >= 0xc000);
|
return (addr >= 0xc000);
|
||||||
|
}
|
||||||
|
|
||||||
case Cartridge::DSP1_LOROM_2MB:
|
case Cartridge::DSP1LoROM2MB: {
|
||||||
//$[60-6f]:[0000-3fff] = DR, $[60-6f]:[4000-7fff] = SR
|
//$[60-6f]:[0000-3fff] = DR, $[60-6f]:[4000-7fff] = SR
|
||||||
return (addr >= 0x4000);
|
return (addr >= 0x4000);
|
||||||
|
}
|
||||||
|
|
||||||
case Cartridge::DSP1_HIROM:
|
case Cartridge::DSP1HiROM: {
|
||||||
//$[00-1f]:[6000-6fff] = DR, $[00-1f]:[7000-7fff] = SR
|
//$[00-1f]:[6000-6fff] = DR, $[00-1f]:[7000-7fff] = SR
|
||||||
return (addr >= 0x7000);
|
return (addr >= 0x7000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 DSP1::read(uint16 addr) {
|
uint8 DSP1::read(uint addr) {
|
||||||
return (addr_decode(addr) == 0) ? dsp1.getDr() : dsp1.getSr();
|
return (addr_decode(addr) == 0) ? dsp1.getDr() : dsp1.getSr();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSP1::write(uint16 addr, uint8 data) {
|
void DSP1::write(uint addr, uint8 data) {
|
||||||
if(addr_decode(addr) == 0) {
|
if(addr_decode(addr) == 0) {
|
||||||
dsp1.setDr(data);
|
dsp1.setDr(data);
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
#include "dsp1emu.h"
|
#include "dsp1emu.h"
|
||||||
|
|
||||||
class DSP1 {
|
class DSP1 : public Memory {
|
||||||
private:
|
private:
|
||||||
Dsp1 dsp1;
|
Dsp1 dsp1;
|
||||||
|
bool addr_decode(uint16 addr);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void init();
|
void init();
|
||||||
@@ -10,9 +11,8 @@ public:
|
|||||||
void power();
|
void power();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
bool addr_decode(uint16 addr);
|
uint8 read(uint addr);
|
||||||
uint8 read (uint16 addr);
|
void write(uint addr, uint8 data);
|
||||||
void write(uint16 addr, uint8 data);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern DSP1 *dsp1;
|
extern DSP1 dsp1;
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef DSP1_CPP
|
||||||
|
|
||||||
// DSP-1's emulation code
|
// DSP-1's emulation code
|
||||||
//
|
//
|
||||||
// Based on research by Overload, The Dumper, Neviksti and Andreas Naive
|
// Based on research by Overload, The Dumper, Neviksti and Andreas Naive
|
||||||
@@ -1620,3 +1622,4 @@ const int16 Dsp1::SinTable[256] = {
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif //ifdef DSP1_CPP
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
#include "../../base.h"
|
#include "../../base.h"
|
||||||
|
#define DSP2_CPP
|
||||||
DSP2 *dsp2;
|
|
||||||
|
|
||||||
#include "dsp2_op.cpp"
|
#include "dsp2_op.cpp"
|
||||||
|
|
||||||
@@ -30,7 +29,7 @@ void DSP2::reset() {
|
|||||||
status.op0dinlen = 0;
|
status.op0dinlen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 DSP2::read(uint16 addr) {
|
uint8 DSP2::read(uint addr) {
|
||||||
uint8 r = 0xff;
|
uint8 r = 0xff;
|
||||||
if(status.out_count) {
|
if(status.out_count) {
|
||||||
r = status.output[status.out_index++];
|
r = status.output[status.out_index++];
|
||||||
@@ -42,7 +41,7 @@ uint8 r = 0xff;
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSP2::write(uint16 addr, uint8 data) {
|
void DSP2::write(uint addr, uint8 data) {
|
||||||
if(status.waiting_for_command) {
|
if(status.waiting_for_command) {
|
||||||
status.command = data;
|
status.command = data;
|
||||||
status.in_index = 0;
|
status.in_index = 0;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
class DSP2 {
|
class DSP2 : public Memory {
|
||||||
public:
|
public:
|
||||||
struct {
|
struct {
|
||||||
bool waiting_for_command;
|
bool waiting_for_command;
|
||||||
uint command;
|
uint command;
|
||||||
uint in_count, in_index;
|
uint in_count, in_index;
|
||||||
@@ -19,25 +19,26 @@ struct {
|
|||||||
bool op0dhaslen;
|
bool op0dhaslen;
|
||||||
int op0doutlen;
|
int op0doutlen;
|
||||||
int op0dinlen;
|
int op0dinlen;
|
||||||
} status;
|
} status;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void enable();
|
void enable();
|
||||||
void power();
|
void power();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
uint8 read(uint addr);
|
||||||
|
void write(uint addr, uint8 data);
|
||||||
|
|
||||||
|
DSP2();
|
||||||
|
~DSP2();
|
||||||
|
|
||||||
|
protected:
|
||||||
void op01();
|
void op01();
|
||||||
void op03();
|
void op03();
|
||||||
void op05();
|
void op05();
|
||||||
void op06();
|
void op06();
|
||||||
void op09();
|
void op09();
|
||||||
void op0d();
|
void op0d();
|
||||||
|
|
||||||
uint8 read (uint16 addr);
|
|
||||||
void write(uint16 addr, uint8 data);
|
|
||||||
|
|
||||||
DSP2();
|
|
||||||
~DSP2();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern DSP2 *dsp2;
|
extern DSP2 dsp2;
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef DSP2_CPP
|
||||||
|
|
||||||
//convert bitmap to bitplane tile
|
//convert bitmap to bitplane tile
|
||||||
void DSP2::op01() {
|
void DSP2::op01() {
|
||||||
//op01 size is always 32 bytes input and output
|
//op01 size is always 32 bytes input and output
|
||||||
@@ -171,3 +173,5 @@ uint8 pixelarray[512];
|
|||||||
status.output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1];
|
status.output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif //ifdef DSP2_CPP
|
||||||
|
34
src/chip/dsp3/dsp3.cpp
Normal file
34
src/chip/dsp3/dsp3.cpp
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#include "../../base.h"
|
||||||
|
#define DSP3_CPP
|
||||||
|
|
||||||
|
namespace DSP3i {
|
||||||
|
#define bool8 uint8
|
||||||
|
#include "dsp3emu.c"
|
||||||
|
#undef bool8
|
||||||
|
};
|
||||||
|
|
||||||
|
void DSP3::init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void DSP3::enable() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void DSP3::power() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DSP3::reset() {
|
||||||
|
DSP3i::DSP3_Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 DSP3::read(uint addr) {
|
||||||
|
DSP3i::dsp3_address = addr & 0xffff;
|
||||||
|
DSP3i::DSP3GetByte();
|
||||||
|
return DSP3i::dsp3_byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DSP3::write(uint addr, uint8 data) {
|
||||||
|
DSP3i::dsp3_address = addr & 0xffff;
|
||||||
|
DSP3i::dsp3_byte = data;
|
||||||
|
DSP3i::DSP3SetByte();
|
||||||
|
}
|
12
src/chip/dsp3/dsp3.h
Normal file
12
src/chip/dsp3/dsp3.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
class DSP3 : public Memory {
|
||||||
|
public:
|
||||||
|
void init();
|
||||||
|
void enable();
|
||||||
|
void power();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
uint8 read (uint addr);
|
||||||
|
void write(uint addr, uint8 data);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern DSP3 dsp3;
|
1146
src/chip/dsp3/dsp3emu.c
Normal file
1146
src/chip/dsp3/dsp3emu.c
Normal file
File diff suppressed because it is too large
Load Diff
54
src/chip/dsp4/dsp4.cpp
Normal file
54
src/chip/dsp4/dsp4.cpp
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#include "../../base.h"
|
||||||
|
#define DSP4_CPP
|
||||||
|
|
||||||
|
namespace DSP4i {
|
||||||
|
inline uint16 READ_WORD(uint8 *addr) {
|
||||||
|
return (addr[0]) + (addr[1] << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32 READ_DWORD(uint8 *addr) {
|
||||||
|
return (addr[0]) + (addr[1] << 8) + (addr[2] << 16) + (addr[3] << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void WRITE_WORD(uint8 *addr, uint16 data) {
|
||||||
|
addr[0] = data;
|
||||||
|
addr[1] = data >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define bool8 uint8
|
||||||
|
#include "dsp4emu.c"
|
||||||
|
#undef bool8
|
||||||
|
};
|
||||||
|
|
||||||
|
void DSP4::init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void DSP4::enable() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void DSP4::power() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DSP4::reset() {
|
||||||
|
DSP4i::InitDSP4();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 DSP4::read(uint addr) {
|
||||||
|
addr &= 0xffff;
|
||||||
|
if(addr < 0xc000) {
|
||||||
|
DSP4i::dsp4_address = addr;
|
||||||
|
DSP4i::DSP4GetByte();
|
||||||
|
return DSP4i::dsp4_byte;
|
||||||
|
}
|
||||||
|
return 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DSP4::write(uint addr, uint8 data) {
|
||||||
|
addr &= 0xffff;
|
||||||
|
if(addr < 0xc000) {
|
||||||
|
DSP4i::dsp4_address = addr;
|
||||||
|
DSP4i::dsp4_byte = data;
|
||||||
|
DSP4i::DSP4SetByte();
|
||||||
|
}
|
||||||
|
}
|
12
src/chip/dsp4/dsp4.h
Normal file
12
src/chip/dsp4/dsp4.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
class DSP4 : public Memory {
|
||||||
|
public:
|
||||||
|
void init();
|
||||||
|
void enable();
|
||||||
|
void power();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
uint8 read (uint addr);
|
||||||
|
void write(uint addr, uint8 data);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern DSP4 dsp4;
|
2150
src/chip/dsp4/dsp4emu.c
Normal file
2150
src/chip/dsp4/dsp4emu.c
Normal file
File diff suppressed because it is too large
Load Diff
108
src/chip/dsp4/dsp4emu.h
Normal file
108
src/chip/dsp4/dsp4emu.h
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
//DSP-4 emulator code
|
||||||
|
//Copyright (c) 2004-2006 Dreamer Nom, John Weidman, Kris Bleakley, Nach, z80 gaiden
|
||||||
|
|
||||||
|
#ifndef DSP4EMU_H
|
||||||
|
#define DSP4EMU_H
|
||||||
|
|
||||||
|
#undef TRUE
|
||||||
|
#undef FALSE
|
||||||
|
#define TRUE true
|
||||||
|
#define FALSE false
|
||||||
|
|
||||||
|
struct DSP4_t
|
||||||
|
{
|
||||||
|
bool8 waiting4command;
|
||||||
|
bool8 half_command;
|
||||||
|
uint16 command;
|
||||||
|
uint32 in_count;
|
||||||
|
uint32 in_index;
|
||||||
|
uint32 out_count;
|
||||||
|
uint32 out_index;
|
||||||
|
uint8 parameters[512];
|
||||||
|
uint8 output[512];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct DSP4_t DSP4;
|
||||||
|
|
||||||
|
struct DSP4_vars_t
|
||||||
|
{
|
||||||
|
// op control
|
||||||
|
int8 DSP4_Logic; // controls op flow
|
||||||
|
|
||||||
|
|
||||||
|
// projection format
|
||||||
|
int16 lcv; // loop-control variable
|
||||||
|
int16 distance; // z-position into virtual world
|
||||||
|
int16 raster; // current raster line
|
||||||
|
int16 segments; // number of raster lines drawn
|
||||||
|
|
||||||
|
// 1.15.16 or 1.15.0 [sign, integer, fraction]
|
||||||
|
int32 world_x; // line of x-projection in world
|
||||||
|
int32 world_y; // line of y-projection in world
|
||||||
|
int32 world_dx; // projection line x-delta
|
||||||
|
int32 world_dy; // projection line y-delta
|
||||||
|
int16 world_ddx; // x-delta increment
|
||||||
|
int16 world_ddy; // y-delta increment
|
||||||
|
int32 world_xenv; // world x-shaping factor
|
||||||
|
int16 world_yofs; // world y-vertical scroll
|
||||||
|
|
||||||
|
int16 view_x1; // current viewer-x
|
||||||
|
int16 view_y1; // current viewer-y
|
||||||
|
int16 view_x2; // future viewer-x
|
||||||
|
int16 view_y2; // future viewer-y
|
||||||
|
int16 view_dx; // view x-delta factor
|
||||||
|
int16 view_dy; // view y-delta factor
|
||||||
|
int16 view_xofs1; // current viewer x-vertical scroll
|
||||||
|
int16 view_yofs1; // current viewer y-vertical scroll
|
||||||
|
int16 view_xofs2; // future viewer x-vertical scroll
|
||||||
|
int16 view_yofs2; // future viewer y-vertical scroll
|
||||||
|
int16 view_yofsenv; // y-scroll shaping factor
|
||||||
|
int16 view_turnoff_x; // road turnoff data
|
||||||
|
int16 view_turnoff_dx; // road turnoff delta factor
|
||||||
|
|
||||||
|
|
||||||
|
// drawing area
|
||||||
|
|
||||||
|
int16 viewport_cx; // x-center of viewport window
|
||||||
|
int16 viewport_cy; // y-center of render window
|
||||||
|
int16 viewport_left; // x-left of viewport
|
||||||
|
int16 viewport_right; // x-right of viewport
|
||||||
|
int16 viewport_top; // y-top of viewport
|
||||||
|
int16 viewport_bottom; // y-bottom of viewport
|
||||||
|
|
||||||
|
|
||||||
|
// sprite structure
|
||||||
|
|
||||||
|
int16 sprite_x; // projected x-pos of sprite
|
||||||
|
int16 sprite_y; // projected y-pos of sprite
|
||||||
|
int16 sprite_attr; // obj attributes
|
||||||
|
bool8 sprite_size; // sprite size: 8x8 or 16x16
|
||||||
|
int16 sprite_clipy; // visible line to clip pixels off
|
||||||
|
int16 sprite_count;
|
||||||
|
|
||||||
|
// generic projection variables designed for
|
||||||
|
// two solid polygons + two polygon sides
|
||||||
|
|
||||||
|
int16 poly_clipLf[2][2]; // left clip boundary
|
||||||
|
int16 poly_clipRt[2][2]; // right clip boundary
|
||||||
|
int16 poly_ptr[2][2]; // HDMA structure pointers
|
||||||
|
int16 poly_raster[2][2]; // current raster line below horizon
|
||||||
|
int16 poly_top[2][2]; // top clip boundary
|
||||||
|
int16 poly_bottom[2][2]; // bottom clip boundary
|
||||||
|
int16 poly_cx[2][2]; // center for left/right points
|
||||||
|
int16 poly_start[2]; // current projection points
|
||||||
|
int16 poly_plane[2]; // previous z-plane distance
|
||||||
|
|
||||||
|
|
||||||
|
// OAM
|
||||||
|
int16 OAM_attr[16]; // OAM (size,MSB) data
|
||||||
|
int16 OAM_index; // index into OAM table
|
||||||
|
int16 OAM_bits; // offset into OAM table
|
||||||
|
|
||||||
|
int16 OAM_RowMax; // maximum number of tiles per 8 aligned pixels (row)
|
||||||
|
int16 OAM_Row[32]; // current number of tiles per row
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct DSP4_vars_t DSP4_vars;
|
||||||
|
|
||||||
|
#endif
|
@@ -1,7 +1,5 @@
|
|||||||
#include "../../base.h"
|
#include "../../base.h"
|
||||||
|
|
||||||
OBC1 *obc1;
|
|
||||||
|
|
||||||
void OBC1::init() {}
|
void OBC1::init() {}
|
||||||
void OBC1::enable() {}
|
void OBC1::enable() {}
|
||||||
|
|
||||||
@@ -10,81 +8,82 @@ void OBC1::power() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OBC1::reset() {
|
void OBC1::reset() {
|
||||||
memset(cartridge.ram, 0xff, 0x2000);
|
for(uint i = 0x0000; i <= 0x1fff; i++) ram_write(i, 0xff);
|
||||||
status.baseptr = (cartridge.ram[0x1ff5] & 1) ? 0x1800 : 0x1c00;
|
|
||||||
status.address = (cartridge.ram[0x1ff6] & 0x7f);
|
status.baseptr = (ram_read(0x1ff5) & 1) ? 0x1800 : 0x1c00;
|
||||||
status.shift = (cartridge.ram[0x1ff6] & 3) << 1;
|
status.address = (ram_read(0x1ff6) & 0x7f);
|
||||||
|
status.shift = (ram_read(0x1ff6) & 3) << 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 OBC1::read(uint16 addr) {
|
uint8 OBC1::read(uint addr) {
|
||||||
addr &= 0x1fff;
|
addr &= 0x1fff;
|
||||||
|
if((addr & 0x1ff8) != 0x1ff0) return ram_read(addr);
|
||||||
if((addr & 0x1ff8) != 0x1ff0) {
|
|
||||||
return cartridge.ram[addr];
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0x1ff0:
|
case 0x1ff0:
|
||||||
return cartridge.ram[status.baseptr + (status.address << 2) + 0];
|
return ram_read(status.baseptr + (status.address << 2) + 0);
|
||||||
case 0x1ff1:
|
case 0x1ff1:
|
||||||
return cartridge.ram[status.baseptr + (status.address << 2) + 1];
|
return ram_read(status.baseptr + (status.address << 2) + 1);
|
||||||
case 0x1ff2:
|
case 0x1ff2:
|
||||||
return cartridge.ram[status.baseptr + (status.address << 2) + 2];
|
return ram_read(status.baseptr + (status.address << 2) + 2);
|
||||||
case 0x1ff3:
|
case 0x1ff3:
|
||||||
return cartridge.ram[status.baseptr + (status.address << 2) + 3];
|
return ram_read(status.baseptr + (status.address << 2) + 3);
|
||||||
case 0x1ff4:
|
case 0x1ff4:
|
||||||
return cartridge.ram[status.baseptr + (status.address >> 2) + 0x200];
|
return ram_read(status.baseptr + (status.address >> 2) + 0x200);
|
||||||
case 0x1ff5:
|
case 0x1ff5:
|
||||||
case 0x1ff6:
|
case 0x1ff6:
|
||||||
case 0x1ff7:
|
case 0x1ff7:
|
||||||
return cartridge.ram[addr];
|
return ram_read(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
//never used, blocks compiler warning
|
return 0x00; //never used, avoids compiler warning
|
||||||
return 0x00;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OBC1::write(uint16 addr, uint8 data) {
|
void OBC1::write(uint addr, uint8 data) {
|
||||||
addr &= 0x1fff;
|
addr &= 0x1fff;
|
||||||
|
if((addr & 0x1ff8) != 0x1ff0) return ram_write(addr, data);
|
||||||
if((addr & 0x1ff8) != 0x1ff0) {
|
|
||||||
cartridge.ram[addr] = data;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0x1ff0:
|
case 0x1ff0:
|
||||||
cartridge.ram[status.baseptr + (status.address << 2) + 0] = data;
|
ram_write(status.baseptr + (status.address << 2) + 0, data);
|
||||||
break;
|
break;
|
||||||
case 0x1ff1:
|
case 0x1ff1:
|
||||||
cartridge.ram[status.baseptr + (status.address << 2) + 1] = data;
|
ram_write(status.baseptr + (status.address << 2) + 1, data);
|
||||||
break;
|
break;
|
||||||
case 0x1ff2:
|
case 0x1ff2:
|
||||||
cartridge.ram[status.baseptr + (status.address << 2) + 2] = data;
|
ram_write(status.baseptr + (status.address << 2) + 2, data);
|
||||||
break;
|
break;
|
||||||
case 0x1ff3:
|
case 0x1ff3:
|
||||||
cartridge.ram[status.baseptr + (status.address << 2) + 3] = data;
|
ram_write(status.baseptr + (status.address << 2) + 3, data);
|
||||||
break;
|
break;
|
||||||
case 0x1ff4: {
|
case 0x1ff4: {
|
||||||
uint8 temp;
|
uint8 temp;
|
||||||
temp = cartridge.ram[status.baseptr + (status.address >> 2) + 0x200];
|
temp = ram_read(status.baseptr + (status.address >> 2) + 0x200);
|
||||||
temp = (temp & ~(3 << status.shift)) | ((data & 3) << status.shift);
|
temp = (temp & ~(3 << status.shift)) | ((data & 3) << status.shift);
|
||||||
cartridge.ram[status.baseptr + (status.address >> 2) + 0x200] = temp;
|
ram_write(status.baseptr + (status.address >> 2) + 0x200, temp);
|
||||||
} break;
|
} break;
|
||||||
case 0x1ff5:
|
case 0x1ff5:
|
||||||
status.baseptr = (data & 1) ? 0x1800 : 0x1c00;
|
status.baseptr = (data & 1) ? 0x1800 : 0x1c00;
|
||||||
cartridge.ram[addr] = data;
|
ram_write(addr, data);
|
||||||
break;
|
break;
|
||||||
case 0x1ff6:
|
case 0x1ff6:
|
||||||
status.address = (data & 0x7f);
|
status.address = (data & 0x7f);
|
||||||
status.shift = (data & 3) << 1;
|
status.shift = (data & 3) << 1;
|
||||||
cartridge.ram[addr] = data;
|
ram_write(addr, data);
|
||||||
break;
|
break;
|
||||||
case 0x1ff7:
|
case 0x1ff7:
|
||||||
cartridge.ram[addr] = data;
|
ram_write(addr, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8 OBC1::ram_read(uint addr) {
|
||||||
|
return memory::cartram.read(addr & 0x1fff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OBC1::ram_write(uint addr, uint8 data) {
|
||||||
|
memory::cartram.write(addr & 0x1fff, data);
|
||||||
|
}
|
||||||
|
|
||||||
OBC1::OBC1() {}
|
OBC1::OBC1() {}
|
||||||
OBC1::~OBC1() {}
|
OBC1::~OBC1() {}
|
||||||
|
@@ -1,20 +1,25 @@
|
|||||||
class OBC1 {
|
class OBC1 : public Memory {
|
||||||
public:
|
public:
|
||||||
struct {
|
|
||||||
uint16 address;
|
|
||||||
uint16 baseptr;
|
|
||||||
uint16 shift;
|
|
||||||
} status;
|
|
||||||
void init();
|
void init();
|
||||||
void enable();
|
void enable();
|
||||||
void power();
|
void power();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
uint8 read (uint16 addr);
|
uint8 read(uint addr);
|
||||||
void write(uint16 addr, uint8 data);
|
void write(uint addr, uint8 data);
|
||||||
|
|
||||||
OBC1();
|
OBC1();
|
||||||
~OBC1();
|
~OBC1();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8 ram_read(uint addr);
|
||||||
|
void ram_write(uint addr, uint8 data);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint16 address;
|
||||||
|
uint16 baseptr;
|
||||||
|
uint16 shift;
|
||||||
|
} status;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern OBC1 *obc1;
|
extern OBC1 obc1;
|
||||||
|
@@ -1,15 +1,12 @@
|
|||||||
#include "../../base.h"
|
#include "../../base.h"
|
||||||
|
#define SDD1_CPP
|
||||||
SDD1 *sdd1;
|
|
||||||
|
|
||||||
#include "sdd1emu.cpp"
|
#include "sdd1emu.cpp"
|
||||||
|
|
||||||
void SDD1::init() {}
|
void SDD1::init() {}
|
||||||
|
|
||||||
void SDD1::enable() {
|
void SDD1::enable() {
|
||||||
for(int i = 0x4800; i <= 0x4807; i++) {
|
for(int i = 0x4800; i <= 0x4807; i++) memory::mmio.map(i, *this);
|
||||||
r_mem->set_mmio_mapper(i, this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDD1::power() {
|
void SDD1::power() {
|
||||||
@@ -17,59 +14,80 @@ void SDD1::power() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SDD1::reset() {
|
void SDD1::reset() {
|
||||||
sdd1.index[0] = 0x000000;
|
|
||||||
sdd1.index[1] = 0x100000;
|
|
||||||
sdd1.index[2] = 0x200000;
|
|
||||||
sdd1.index[3] = 0x300000;
|
|
||||||
|
|
||||||
for(int i=0;i<8;i++) {
|
|
||||||
sdd1.active[i] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
sdd1.dma_active = false;
|
sdd1.dma_active = false;
|
||||||
|
|
||||||
|
regs.r4800 = 0x00;
|
||||||
|
regs.r4801 = 0x00;
|
||||||
|
|
||||||
|
regs.r4804 = 0x00;
|
||||||
|
regs.r4805 = 0x01;
|
||||||
|
regs.r4806 = 0x02;
|
||||||
|
regs.r4807 = 0x03;
|
||||||
|
|
||||||
|
bus.map(Bus::MapLinear, 0xc0, 0xcf, 0x0000, 0xffff, memory::cartrom, (regs.r4804 & 7) << 20);
|
||||||
|
bus.map(Bus::MapLinear, 0xd0, 0xdf, 0x0000, 0xffff, memory::cartrom, (regs.r4805 & 7) << 20);
|
||||||
|
bus.map(Bus::MapLinear, 0xe0, 0xef, 0x0000, 0xffff, memory::cartrom, (regs.r4806 & 7) << 20);
|
||||||
|
bus.map(Bus::MapLinear, 0xf0, 0xff, 0x0000, 0xffff, memory::cartrom, (regs.r4807 & 7) << 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 SDD1::offset(uint32 addr) {
|
uint8 SDD1::mmio_read(uint addr) {
|
||||||
uint8 b = (addr >> 16) & 0xff;
|
switch(addr & 0xffff) {
|
||||||
if(b <= 0xbf)return 0;
|
case 0x4804: return regs.r4804;
|
||||||
|
case 0x4805: return regs.r4805;
|
||||||
b -= 0xc0; //b = 0x00-0x3f
|
case 0x4806: return regs.r4806;
|
||||||
b >>= 4; //b = 0-3
|
case 0x4807: return regs.r4807;
|
||||||
b &= 3; //bitmask
|
|
||||||
|
|
||||||
return sdd1.index[b] + (addr & 0x0fffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 SDD1::mmio_read(uint16 addr) {
|
|
||||||
switch(addr) {
|
|
||||||
//>>20 == 0x100000 == 1mb
|
|
||||||
case 0x4804:return (sdd1.index[0] >> 20) & 7;
|
|
||||||
case 0x4805:return (sdd1.index[1] >> 20) & 7;
|
|
||||||
case 0x4806:return (sdd1.index[2] >> 20) & 7;
|
|
||||||
case 0x4807:return (sdd1.index[3] >> 20) & 7;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return r_cpu->regs.mdr;
|
return cpu.regs.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDD1::mmio_write(uint16 addr, uint8 data) {
|
void SDD1::mmio_write(uint addr, uint8 data) {
|
||||||
switch(addr) {
|
switch(addr & 0xffff) {
|
||||||
case 0x4801:
|
case 0x4800: {
|
||||||
for(int i = 0; i < 8; i++) {
|
regs.r4800 = data;
|
||||||
sdd1.active[i] = !!(data & (1 << i));
|
} break;
|
||||||
|
|
||||||
|
case 0x4801: {
|
||||||
|
regs.r4801 = data;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x4804: {
|
||||||
|
if(regs.r4804 != data) {
|
||||||
|
regs.r4804 = data;
|
||||||
|
bus.map(Bus::MapLinear, 0xc0, 0xcf, 0x0000, 0xffff,
|
||||||
|
memory::cartrom, (regs.r4804 & 7) << 20);
|
||||||
}
|
}
|
||||||
break;
|
} break;
|
||||||
//<<20 == 0x100000 == 1mb
|
|
||||||
case 0x4804:sdd1.index[0] = (data & 7) << 20;break;
|
case 0x4805: {
|
||||||
case 0x4805:sdd1.index[1] = (data & 7) << 20;break;
|
if(regs.r4805 != data) {
|
||||||
case 0x4806:sdd1.index[2] = (data & 7) << 20;break;
|
regs.r4805 = data;
|
||||||
case 0x4807:sdd1.index[3] = (data & 7) << 20;break;
|
bus.map(Bus::MapLinear, 0xd0, 0xdf, 0x0000, 0xffff,
|
||||||
|
memory::cartrom, (regs.r4805 & 7) << 20);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x4806: {
|
||||||
|
if(regs.r4806 != data) {
|
||||||
|
regs.r4806 = data;
|
||||||
|
bus.map(Bus::MapLinear, 0xe0, 0xef, 0x0000, 0xffff,
|
||||||
|
memory::cartrom, (regs.r4806 & 7) << 20);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x4807: {
|
||||||
|
if(regs.r4807 != data) {
|
||||||
|
regs.r4807 = data;
|
||||||
|
bus.map(Bus::MapLinear, 0xf0, 0xff, 0x0000, 0xffff,
|
||||||
|
memory::cartrom, (regs.r4807 & 7) << 20);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDD1::dma_begin(uint8 channel, uint32 addr, uint16 length) {
|
void SDD1::dma_begin(uint8 channel, uint32 addr, uint16 length) {
|
||||||
if(sdd1.active[channel] == true) {
|
if(regs.r4800 & (1 << channel) && regs.r4801 & (1 << channel)) {
|
||||||
sdd1.active[channel] = false;
|
regs.r4801 &= ~(1 << channel);
|
||||||
sdd1.dma_active = true;
|
sdd1.dma_active = true;
|
||||||
sdd1.buffer_index = 0;
|
sdd1.buffer_index = 0;
|
||||||
sdd1.buffer_size = length;
|
sdd1.buffer_size = length;
|
||||||
@@ -82,9 +100,7 @@ bool SDD1::dma_active() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8 SDD1::dma_read() {
|
uint8 SDD1::dma_read() {
|
||||||
if(--sdd1.buffer_size == 0) {
|
if(--sdd1.buffer_size == 0) sdd1.dma_active = false;
|
||||||
sdd1.dma_active = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//sdd1.buffer[] is 65536 bytes, and sdd1.buffer_index
|
//sdd1.buffer[] is 65536 bytes, and sdd1.buffer_index
|
||||||
//is of type uint16, so no buffer overflow is possible
|
//is of type uint16, so no buffer overflow is possible
|
||||||
|
@@ -2,31 +2,38 @@
|
|||||||
|
|
||||||
class SDD1 : public MMIO {
|
class SDD1 : public MMIO {
|
||||||
public:
|
public:
|
||||||
SDD1emu sdd1emu;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
uint32 index[4]; //memory mapping registers
|
|
||||||
uint8 buffer[65536]; //pointer to decompressed S-DD1 data,
|
|
||||||
//max. DMA length is 65536
|
|
||||||
uint16 buffer_index; //DMA read index into S-DD1 decompression buffer
|
|
||||||
uint16 buffer_size;
|
|
||||||
bool active[8]; //true when DMA channel should pass through S-DD1
|
|
||||||
bool dma_active;
|
|
||||||
} sdd1;
|
|
||||||
void init();
|
void init();
|
||||||
void enable();
|
void enable();
|
||||||
void power();
|
void power();
|
||||||
void reset();
|
void reset();
|
||||||
uint32 offset(uint32 addr);
|
|
||||||
|
uint8 mmio_read (uint addr);
|
||||||
|
void mmio_write(uint addr, uint8 data);
|
||||||
|
|
||||||
void dma_begin(uint8 channel, uint32 addr, uint16 length);
|
void dma_begin(uint8 channel, uint32 addr, uint16 length);
|
||||||
bool dma_active();
|
bool dma_active();
|
||||||
uint8 dma_read();
|
uint8 dma_read();
|
||||||
|
|
||||||
uint8 mmio_read (uint16 addr);
|
|
||||||
void mmio_write(uint16 addr, uint8 data);
|
|
||||||
|
|
||||||
SDD1();
|
SDD1();
|
||||||
|
|
||||||
|
private:
|
||||||
|
SDD1emu sdd1emu;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint8 buffer[65536]; //pointer to decompressed S-DD1 data, max DMA length is 65536
|
||||||
|
uint16 buffer_index; //DMA read index into S-DD1 decompression buffer
|
||||||
|
uint16 buffer_size;
|
||||||
|
bool dma_active;
|
||||||
|
} sdd1;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint8 r4800;
|
||||||
|
uint8 r4801;
|
||||||
|
uint8 r4804;
|
||||||
|
uint8 r4805;
|
||||||
|
uint8 r4806;
|
||||||
|
uint8 r4807;
|
||||||
|
} regs;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SDD1 *sdd1;
|
extern SDD1 sdd1;
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef SDD1_CPP
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
|
|
||||||
S-DD1'algorithm emulation code
|
S-DD1'algorithm emulation code
|
||||||
@@ -28,7 +30,7 @@ understood.
|
|||||||
|
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
|
||||||
#define SDD1_read(__addr) (r_mem->read(__addr))
|
#define SDD1_read(__addr) (bus.read(__addr))
|
||||||
|
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -445,3 +447,5 @@ SDD1emu::SDD1emu() :
|
|||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif //ifdef SDD1_CPP
|
||||||
|
@@ -52,8 +52,6 @@
|
|||||||
|
|
||||||
#include "../../base.h"
|
#include "../../base.h"
|
||||||
|
|
||||||
SRTC *srtc;
|
|
||||||
|
|
||||||
void SRTC::set_time() {
|
void SRTC::set_time() {
|
||||||
time_t rawtime;
|
time_t rawtime;
|
||||||
tm *t;
|
tm *t;
|
||||||
@@ -79,8 +77,8 @@ tm *t;
|
|||||||
void SRTC::init() {}
|
void SRTC::init() {}
|
||||||
|
|
||||||
void SRTC::enable() {
|
void SRTC::enable() {
|
||||||
r_mem->set_mmio_mapper(0x2800, this);
|
memory::mmio.map(0x2800, *this);
|
||||||
r_mem->set_mmio_mapper(0x2801, this);
|
memory::mmio.map(0x2801, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SRTC::power() {
|
void SRTC::power() {
|
||||||
@@ -93,8 +91,8 @@ void SRTC::reset() {
|
|||||||
srtc.mode = SRTC_READ;
|
srtc.mode = SRTC_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SRTC::mmio_read(uint16 addr) {
|
uint8 SRTC::mmio_read(uint addr) {
|
||||||
switch(addr) {
|
switch(addr & 0xffff) {
|
||||||
|
|
||||||
case 0x2800: {
|
case 0x2800: {
|
||||||
if(srtc.mode == SRTC_READ) {
|
if(srtc.mode == SRTC_READ) {
|
||||||
@@ -118,7 +116,7 @@ uint8 SRTC::mmio_read(uint16 addr) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return r_cpu->regs.mdr;
|
return cpu.regs.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Please see notes above about the implementation of the S-RTC
|
//Please see notes above about the implementation of the S-RTC
|
||||||
@@ -126,8 +124,8 @@ uint8 SRTC::mmio_read(uint16 addr) {
|
|||||||
//as reads will refresh the data array with the current system
|
//as reads will refresh the data array with the current system
|
||||||
//time. The write method is only here for the sake of faux
|
//time. The write method is only here for the sake of faux
|
||||||
//emulation of the real hardware.
|
//emulation of the real hardware.
|
||||||
void SRTC::mmio_write(uint16 addr, uint8 data) {
|
void SRTC::mmio_write(uint addr, uint8 data) {
|
||||||
switch(addr) {
|
switch(addr & 0xffff) {
|
||||||
|
|
||||||
case 0x2800: {
|
case 0x2800: {
|
||||||
} break;
|
} break;
|
||||||
|
@@ -43,10 +43,10 @@ struct {
|
|||||||
void power();
|
void power();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
uint8 mmio_read (uint16 addr);
|
uint8 mmio_read (uint addr);
|
||||||
void mmio_write(uint16 addr, uint8 data);
|
void mmio_write(uint addr, uint8 data);
|
||||||
|
|
||||||
SRTC();
|
SRTC();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SRTC *srtc;
|
extern SRTC srtc;
|
||||||
|
86
src/chip/st010/st010.cpp
Normal file
86
src/chip/st010/st010.cpp
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
#include "../../base.h"
|
||||||
|
#define ST010_CPP
|
||||||
|
|
||||||
|
#include "st010_data.h"
|
||||||
|
#include "st010_op.cpp"
|
||||||
|
|
||||||
|
int16 ST010::sin(int16 theta) {
|
||||||
|
return sin_table[(theta >> 8) & 0xff];
|
||||||
|
}
|
||||||
|
|
||||||
|
int16 ST010::cos(int16 theta) {
|
||||||
|
return sin_table[((theta + 0x4000) >> 8) & 0xff];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 ST010::readb(uint16 addr) {
|
||||||
|
return ram[addr & 0xfff];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 ST010::readw(uint16 addr) {
|
||||||
|
return (readb(addr + 0) << 0) |
|
||||||
|
(readb(addr + 1) << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 ST010::readd(uint16 addr) {
|
||||||
|
return (readb(addr + 0) << 0) |
|
||||||
|
(readb(addr + 1) << 8) |
|
||||||
|
(readb(addr + 2) << 16) |
|
||||||
|
(readb(addr + 3) << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ST010::writeb(uint16 addr, uint8 data) {
|
||||||
|
ram[addr & 0xfff] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ST010::writew(uint16 addr, uint16 data) {
|
||||||
|
writeb(addr + 0, data);
|
||||||
|
writeb(addr + 1, data >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ST010::writed(uint16 addr, uint32 data) {
|
||||||
|
writeb(addr + 0, data);
|
||||||
|
writeb(addr + 1, data >> 8);
|
||||||
|
writeb(addr + 2, data >> 16);
|
||||||
|
writeb(addr + 3, data >> 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
void ST010::init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void ST010::enable() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void ST010::power() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ST010::reset() {
|
||||||
|
memset(ram, 0x00, sizeof ram);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
uint8 ST010::read(uint addr) {
|
||||||
|
return readb(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ST010::write(uint addr, uint8 data) {
|
||||||
|
writeb(addr, data);
|
||||||
|
|
||||||
|
if((addr & 0xfff) == 0x0021 && (data & 0x80)) {
|
||||||
|
switch(ram[0x0020]) {
|
||||||
|
case 0x01: op_01(); break;
|
||||||
|
case 0x02: op_02(); break;
|
||||||
|
case 0x03: op_03(); break;
|
||||||
|
case 0x04: op_04(); break;
|
||||||
|
case 0x05: op_05(); break;
|
||||||
|
case 0x06: op_06(); break;
|
||||||
|
case 0x07: op_07(); break;
|
||||||
|
case 0x08: op_08(); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ram[0x0021] &= ~0x80;
|
||||||
|
}
|
||||||
|
}
|
42
src/chip/st010/st010.h
Normal file
42
src/chip/st010/st010.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
class ST010 : public Memory {
|
||||||
|
public:
|
||||||
|
void init();
|
||||||
|
void enable();
|
||||||
|
void power();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
uint8 read (uint addr);
|
||||||
|
void write(uint addr, uint8 data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8 ram[0x1000];
|
||||||
|
static const int16 sin_table[256];
|
||||||
|
static const int16 mode7_scale[176];
|
||||||
|
static const uint8 arctan[32][32];
|
||||||
|
|
||||||
|
//interfaces to sin table
|
||||||
|
int16 sin(int16 theta);
|
||||||
|
int16 cos(int16 theta);
|
||||||
|
|
||||||
|
//interfaces to ram buffer
|
||||||
|
uint8 readb (uint16 addr);
|
||||||
|
uint16 readw (uint16 addr);
|
||||||
|
uint32 readd (uint16 addr);
|
||||||
|
void writeb(uint16 addr, uint8 data);
|
||||||
|
void writew(uint16 addr, uint16 data);
|
||||||
|
void writed(uint16 addr, uint32 data);
|
||||||
|
|
||||||
|
//opcodes
|
||||||
|
void op_01();
|
||||||
|
void op_02();
|
||||||
|
void op_03();
|
||||||
|
void op_04();
|
||||||
|
void op_05();
|
||||||
|
void op_06();
|
||||||
|
void op_07();
|
||||||
|
void op_08();
|
||||||
|
|
||||||
|
void op_01(int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &quadrant, int16 &theta);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern ST010 st010;
|
126
src/chip/st010/st010_data.h
Normal file
126
src/chip/st010/st010_data.h
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
const int16 ST010::sin_table[256] = {
|
||||||
|
0x0000, 0x0324, 0x0648, 0x096a, 0x0c8c, 0x0fab, 0x12c8, 0x15e2,
|
||||||
|
0x18f9, 0x1c0b, 0x1f1a, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11,
|
||||||
|
0x30fb, 0x33df, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a,
|
||||||
|
0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842,
|
||||||
|
0x5a82, 0x5cb3, 0x5ed7, 0x60eb, 0x62f1, 0x64e8, 0x66cf, 0x68a6,
|
||||||
|
0x6a6d, 0x6c23, 0x6dc9, 0x6f5e, 0x70e2, 0x7254, 0x73b5, 0x7504,
|
||||||
|
0x7641, 0x776b, 0x7884, 0x7989, 0x7a7c, 0x7b5c, 0x7c29, 0x7ce3,
|
||||||
|
0x7d89, 0x7e1d, 0x7e9c, 0x7f09, 0x7f61, 0x7fa6, 0x7fd8, 0x7ff5,
|
||||||
|
0x7fff, 0x7ff5, 0x7fd8, 0x7fa6, 0x7f61, 0x7f09, 0x7e9c, 0x7e1d,
|
||||||
|
0x7d89, 0x7ce3, 0x7c29, 0x7b5c, 0x7a7c, 0x7989, 0x7884, 0x776b,
|
||||||
|
0x7641, 0x7504, 0x73b5, 0x7254, 0x70e2, 0x6f5e, 0x6dc9, 0x6c23,
|
||||||
|
0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f1, 0x60eb, 0x5ed7, 0x5cb3,
|
||||||
|
0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4,
|
||||||
|
0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33df,
|
||||||
|
0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f1a, 0x1c0b,
|
||||||
|
0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8c, 0x096a, 0x0648, 0x0324,
|
||||||
|
0x0000, -0x0324, -0x0648, -0x096b, -0x0c8c, -0x0fab, -0x12c8, -0x15e2,
|
||||||
|
-0x18f9, -0x1c0b, -0x1f1a, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11,
|
||||||
|
-0x30fb, -0x33df, -0x36ba, -0x398d, -0x3c56, -0x3f17, -0x41ce, -0x447a,
|
||||||
|
-0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842,
|
||||||
|
-0x5a82, -0x5cb3, -0x5ed7, -0x60ec, -0x62f1, -0x64e8, -0x66cf, -0x68a6,
|
||||||
|
-0x6a6d, -0x6c23, -0x6dc9, -0x6f5e, -0x70e2, -0x7254, -0x73b5, -0x7504,
|
||||||
|
-0x7641, -0x776b, -0x7884, -0x7989, -0x7a7c, -0x7b5c, -0x7c29, -0x7ce3,
|
||||||
|
-0x7d89, -0x7e1d, -0x7e9c, -0x7f09, -0x7f61, -0x7fa6, -0x7fd8, -0x7ff5,
|
||||||
|
-0x7fff, -0x7ff5, -0x7fd8, -0x7fa6, -0x7f61, -0x7f09, -0x7e9c, -0x7e1d,
|
||||||
|
-0x7d89, -0x7ce3, -0x7c29, -0x7b5c, -0x7a7c, -0x7989, -0x7883, -0x776b,
|
||||||
|
-0x7641, -0x7504, -0x73b5, -0x7254, -0x70e2, -0x6f5e, -0x6dc9, -0x6c23,
|
||||||
|
-0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f1, -0x60eb, -0x5ed7, -0x5cb3,
|
||||||
|
-0x5a82, -0x5842, -0x55f5, -0x539a, -0x5133, -0x4ebf, -0x4c3f, -0x49b3,
|
||||||
|
-0x471c, -0x447a, -0x41cd, -0x3f17, -0x3c56, -0x398c, -0x36b9, -0x33de,
|
||||||
|
-0x30fb, -0x2e10, -0x2b1f, -0x2826, -0x2527, -0x2223, -0x1f19, -0x1c0b,
|
||||||
|
-0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324
|
||||||
|
};
|
||||||
|
|
||||||
|
const int16 ST010::mode7_scale[176] = {
|
||||||
|
0x0380, 0x0325, 0x02da, 0x029c, 0x0268, 0x023b, 0x0215, 0x01f3,
|
||||||
|
0x01d5, 0x01bb, 0x01a3, 0x018e, 0x017b, 0x016a, 0x015a, 0x014b,
|
||||||
|
0x013e, 0x0132, 0x0126, 0x011c, 0x0112, 0x0109, 0x0100, 0x00f8,
|
||||||
|
0x00f0, 0x00e9, 0x00e3, 0x00dc, 0x00d6, 0x00d1, 0x00cb, 0x00c6,
|
||||||
|
0x00c1, 0x00bd, 0x00b8, 0x00b4, 0x00b0, 0x00ac, 0x00a8, 0x00a5,
|
||||||
|
0x00a2, 0x009e, 0x009b, 0x0098, 0x0095, 0x0093, 0x0090, 0x008d,
|
||||||
|
0x008b, 0x0088, 0x0086, 0x0084, 0x0082, 0x0080, 0x007e, 0x007c,
|
||||||
|
0x007a, 0x0078, 0x0076, 0x0074, 0x0073, 0x0071, 0x006f, 0x006e,
|
||||||
|
0x006c, 0x006b, 0x0069, 0x0068, 0x0067, 0x0065, 0x0064, 0x0063,
|
||||||
|
0x0062, 0x0060, 0x005f, 0x005e, 0x005d, 0x005c, 0x005b, 0x005a,
|
||||||
|
0x0059, 0x0058, 0x0057, 0x0056, 0x0055, 0x0054, 0x0053, 0x0052,
|
||||||
|
0x0051, 0x0051, 0x0050, 0x004f, 0x004e, 0x004d, 0x004d, 0x004c,
|
||||||
|
0x004b, 0x004b, 0x004a, 0x0049, 0x0048, 0x0048, 0x0047, 0x0047,
|
||||||
|
0x0046, 0x0045, 0x0045, 0x0044, 0x0044, 0x0043, 0x0042, 0x0042,
|
||||||
|
0x0041, 0x0041, 0x0040, 0x0040, 0x003f, 0x003f, 0x003e, 0x003e,
|
||||||
|
0x003d, 0x003d, 0x003c, 0x003c, 0x003b, 0x003b, 0x003a, 0x003a,
|
||||||
|
0x003a, 0x0039, 0x0039, 0x0038, 0x0038, 0x0038, 0x0037, 0x0037,
|
||||||
|
0x0036, 0x0036, 0x0036, 0x0035, 0x0035, 0x0035, 0x0034, 0x0034,
|
||||||
|
0x0034, 0x0033, 0x0033, 0x0033, 0x0032, 0x0032, 0x0032, 0x0031,
|
||||||
|
0x0031, 0x0031, 0x0030, 0x0030, 0x0030, 0x0030, 0x002f, 0x002f,
|
||||||
|
0x002f, 0x002e, 0x002e, 0x002e, 0x002e, 0x002d, 0x002d, 0x002d,
|
||||||
|
0x002d, 0x002c, 0x002c, 0x002c, 0x002c, 0x002b, 0x002b, 0x002b
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8 ST010::arctan[32][32] = {
|
||||||
|
{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 },
|
||||||
|
{ 0x80, 0xa0, 0xad, 0xb3, 0xb6, 0xb8, 0xb9, 0xba, 0xbb, 0xbb, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd,
|
||||||
|
0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf },
|
||||||
|
{ 0x80, 0x93, 0xa0, 0xa8, 0xad, 0xb0, 0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb,
|
||||||
|
0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd },
|
||||||
|
{ 0x80, 0x8d, 0x98, 0xa0, 0xa6, 0xaa, 0xad, 0xb0, 0xb1, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb7, 0xb8,
|
||||||
|
0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc },
|
||||||
|
{ 0x80, 0x8a, 0x93, 0x9a, 0xa0, 0xa5, 0xa8, 0xab, 0xad, 0xaf, 0xb0, 0xb2, 0xb3, 0xb4, 0xb5, 0xb5,
|
||||||
|
0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb },
|
||||||
|
{ 0x80, 0x88, 0x90, 0x96, 0x9b, 0xa0, 0xa4, 0xa7, 0xa9, 0xab, 0xad, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
|
||||||
|
0xb4, 0xb4, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9 },
|
||||||
|
{ 0x80, 0x87, 0x8d, 0x93, 0x98, 0x9c, 0xa0, 0xa3, 0xa6, 0xa8, 0xaa, 0xac, 0xad, 0xae, 0xb0, 0xb0,
|
||||||
|
0xb1, 0xb2, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8 },
|
||||||
|
{ 0x80, 0x86, 0x8b, 0x90, 0x95, 0x99, 0x9d, 0xa0, 0xa3, 0xa5, 0xa7, 0xa9, 0xaa, 0xac, 0xad, 0xae,
|
||||||
|
0xaf, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7 },
|
||||||
|
{ 0x80, 0x85, 0x8a, 0x8f, 0x93, 0x97, 0x9a, 0x9d, 0xa0, 0xa2, 0xa5, 0xa6, 0xa8, 0xaa, 0xab, 0xac,
|
||||||
|
0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb5 },
|
||||||
|
{ 0x80, 0x85, 0x89, 0x8d, 0x91, 0x95, 0x98, 0x9b, 0x9e, 0xa0, 0xa0, 0xa4, 0xa6, 0xa7, 0xa9, 0xaa,
|
||||||
|
0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4 },
|
||||||
|
{ 0x80, 0x84, 0x88, 0x8c, 0x90, 0x93, 0x96, 0x99, 0x9b, 0x9e, 0xa0, 0xa2, 0xa4, 0xa5, 0xa7, 0xa8,
|
||||||
|
0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3 },
|
||||||
|
{ 0x80, 0x84, 0x87, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa5, 0xa6,
|
||||||
|
0xa7, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2 },
|
||||||
|
{ 0x80, 0x83, 0x87, 0x8a, 0x8d, 0x90, 0x93, 0x96, 0x98, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa5,
|
||||||
|
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1 },
|
||||||
|
{ 0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x94, 0x96, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa2, 0xa3,
|
||||||
|
0xa4, 0xa5, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xb0 },
|
||||||
|
{ 0x80, 0x83, 0x86, 0x89, 0x8b, 0x8e, 0x90, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa1,
|
||||||
|
0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf },
|
||||||
|
{ 0x80, 0x83, 0x85, 0x88, 0x8b, 0x8d, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9b, 0x9d, 0x9f, 0xa0,
|
||||||
|
0xa1, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae },
|
||||||
|
{ 0x80, 0x83, 0x85, 0x88, 0x8a, 0x8c, 0x8f, 0x91, 0x93, 0x95, 0x97, 0x99, 0x9a, 0x9c, 0x9d, 0x9f,
|
||||||
|
0xa0, 0xa1, 0xa2, 0xa3, 0xa5, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xab, 0xac, 0xad },
|
||||||
|
{ 0x80, 0x82, 0x85, 0x87, 0x89, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x97, 0x99, 0x9b, 0x9c, 0x9d,
|
||||||
|
0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac },
|
||||||
|
{ 0x80, 0x82, 0x85, 0x87, 0x89, 0x8b, 0x8d, 0x8f, 0x91, 0x93, 0x95, 0x96, 0x98, 0x99, 0x9b, 0x9c,
|
||||||
|
0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab },
|
||||||
|
{ 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x95, 0x97, 0x98, 0x9a, 0x9b,
|
||||||
|
0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa },
|
||||||
|
{ 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x99, 0x9a,
|
||||||
|
0x9b, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9 },
|
||||||
|
{ 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8f, 0x90, 0x92, 0x94, 0x95, 0x97, 0x98, 0x99,
|
||||||
|
0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8 },
|
||||||
|
{ 0x80, 0x82, 0x84, 0x86, 0x87, 0x89, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x98,
|
||||||
|
0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7 },
|
||||||
|
{ 0x80, 0x82, 0x84, 0x85, 0x87, 0x89, 0x8a, 0x8c, 0x8e, 0x8f, 0x91, 0x92, 0x94, 0x95, 0x96, 0x98,
|
||||||
|
0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6 },
|
||||||
|
{ 0x80, 0x82, 0x83, 0x85, 0x87, 0x88, 0x8a, 0x8c, 0x8d, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x96, 0x97,
|
||||||
|
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5 },
|
||||||
|
{ 0x80, 0x82, 0x83, 0x85, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x94, 0x95, 0x96,
|
||||||
|
0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4 },
|
||||||
|
{ 0x80, 0x82, 0x83, 0x85, 0x86, 0x88, 0x89, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x95,
|
||||||
|
0x96, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4 },
|
||||||
|
{ 0x80, 0x82, 0x83, 0x85, 0x86, 0x87, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93, 0x95,
|
||||||
|
0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2, 0xa3 },
|
||||||
|
{ 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x89, 0x8a, 0x8b, 0x8d, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94,
|
||||||
|
0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2 },
|
||||||
|
{ 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x88, 0x8a, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93,
|
||||||
|
0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1, 0xa1 },
|
||||||
|
{ 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8b, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93,
|
||||||
|
0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1 },
|
||||||
|
{ 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92,
|
||||||
|
0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0 }
|
||||||
|
};
|
261
src/chip/st010/st010_op.cpp
Normal file
261
src/chip/st010/st010_op.cpp
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
#ifdef ST010_CPP
|
||||||
|
|
||||||
|
//ST-010 emulation code - Copyright (C) 2003 The Dumper, Matthew Kendora, Overload, Feather
|
||||||
|
//bsnes port - Copyright (C) 2007 byuu
|
||||||
|
|
||||||
|
void ST010::op_01(int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &quadrant, int16 &theta) {
|
||||||
|
if((x0 < 0) && (y0 < 0)) {
|
||||||
|
x1 = -x0;
|
||||||
|
y1 = -y0;
|
||||||
|
quadrant = -0x8000;
|
||||||
|
} else if(x0 < 0) {
|
||||||
|
x1 = y0;
|
||||||
|
y1 = -x0;
|
||||||
|
quadrant = -0x4000;
|
||||||
|
} else if(y0 < 0) {
|
||||||
|
x1 = -y0;
|
||||||
|
y1 = x0;
|
||||||
|
quadrant = 0x4000;
|
||||||
|
} else {
|
||||||
|
x1 = x0;
|
||||||
|
y1 = y0;
|
||||||
|
quadrant = 0x0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
while((x1 > 0x1f) || (y1 > 0x1f)) {
|
||||||
|
if(x1 > 1) { x1 >>= 1; }
|
||||||
|
if(y1 > 1) { y1 >>= 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if(y1 == 0) { quadrant += 0x4000; }
|
||||||
|
|
||||||
|
theta = (arctan[y1][x1] << 8) ^ quadrant;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
void ST010::op_01() {
|
||||||
|
int16 x0 = readw(0x0000);
|
||||||
|
int16 y0 = readw(0x0002);
|
||||||
|
int16 x1, y1, quadrant, theta;
|
||||||
|
|
||||||
|
op_01(x0, y0, x1, y1, quadrant, theta);
|
||||||
|
|
||||||
|
writew(0x0000, x1);
|
||||||
|
writew(0x0002, y1);
|
||||||
|
writew(0x0004, quadrant);
|
||||||
|
//writew(0x0006, y0); //Overload's docs note this write occurs, SNES9x disagrees
|
||||||
|
writew(0x0010, theta);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ST010::op_02() {
|
||||||
|
int16 positions = readw(0x0024);
|
||||||
|
uint16 *places = (uint16*)(ram + 0x0040);
|
||||||
|
uint16 *drivers = (uint16*)(ram + 0x0080);
|
||||||
|
|
||||||
|
bool sorted;
|
||||||
|
uint16 temp;
|
||||||
|
if(positions > 1) {
|
||||||
|
do {
|
||||||
|
sorted = true;
|
||||||
|
for(int i = 0; i < positions - 1; i++) {
|
||||||
|
if(places[i] < places[i + 1]) {
|
||||||
|
temp = places[i + 1];
|
||||||
|
places[i + 1] = places[i];
|
||||||
|
places[i] = temp;
|
||||||
|
|
||||||
|
temp = drivers[i + 1];
|
||||||
|
drivers[i + 1] = drivers[i];
|
||||||
|
drivers[i] = temp;
|
||||||
|
|
||||||
|
sorted = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
positions--;
|
||||||
|
} while(!sorted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ST010::op_03() {
|
||||||
|
int16 x0 = readw(0x0000);
|
||||||
|
int16 y0 = readw(0x0002);
|
||||||
|
int16 multiplier = readw(0x0004);
|
||||||
|
int32 x1, y1;
|
||||||
|
|
||||||
|
x1 = x0 * multiplier << 1;
|
||||||
|
y1 = y0 * multiplier << 1;
|
||||||
|
|
||||||
|
writed(0x0010, x1);
|
||||||
|
writed(0x0014, y1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ST010::op_04() {
|
||||||
|
int16 x = readw(0x0000);
|
||||||
|
int16 y = readw(0x0002);
|
||||||
|
int16 square;
|
||||||
|
//calculate the vector length of (x,y)
|
||||||
|
square = (int16)sqrt((double)(y * y + x * x));
|
||||||
|
|
||||||
|
writew(0x0010, square);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ST010::op_05() {
|
||||||
|
int32 dx, dy;
|
||||||
|
int16 a1, b1, c1;
|
||||||
|
uint16 o1;
|
||||||
|
bool wrap = false;
|
||||||
|
|
||||||
|
//target (x,y) coordinates
|
||||||
|
int16 ypos_max = readw(0x00c0);
|
||||||
|
int16 xpos_max = readw(0x00c2);
|
||||||
|
|
||||||
|
//current coordinates and direction
|
||||||
|
int32 ypos = readd(0x00c4);
|
||||||
|
int32 xpos = readd(0x00c8);
|
||||||
|
uint16 rot = readw(0x00cc);
|
||||||
|
|
||||||
|
//physics
|
||||||
|
uint16 speed = readw(0x00d4);
|
||||||
|
uint16 accel = readw(0x00d6);
|
||||||
|
uint16 speed_max = readw(0x00d8);
|
||||||
|
|
||||||
|
//special condition acknowledgement
|
||||||
|
int16 system = readw(0x00da);
|
||||||
|
int16 flags = readw(0x00dc);
|
||||||
|
|
||||||
|
//new target coordinates
|
||||||
|
int16 ypos_new = readw(0x00de);
|
||||||
|
int16 xpos_new = readw(0x00e0);
|
||||||
|
|
||||||
|
//mask upper bit
|
||||||
|
xpos_new &= 0x7fff;
|
||||||
|
|
||||||
|
//get the current distance
|
||||||
|
dx = xpos_max - (xpos >> 16);
|
||||||
|
dy = ypos_max - (ypos >> 16);
|
||||||
|
|
||||||
|
//quirk: clear and move in9
|
||||||
|
writew(0x00d2, 0xffff);
|
||||||
|
writew(0x00da, 0x0000);
|
||||||
|
|
||||||
|
//grab the target angle
|
||||||
|
op_01(dy, dx, a1, b1, c1, (int16&)o1);
|
||||||
|
|
||||||
|
//check for wrapping
|
||||||
|
if(abs(o1 - rot) > 0x8000) {
|
||||||
|
o1 += 0x8000;
|
||||||
|
rot += 0x8000;
|
||||||
|
wrap = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 old_speed = speed;
|
||||||
|
|
||||||
|
//special case
|
||||||
|
if(abs(o1 - rot) == 0x8000) {
|
||||||
|
speed = 0x100;
|
||||||
|
}
|
||||||
|
|
||||||
|
//slow down for sharp curves
|
||||||
|
else if(abs(o1 - rot) >= 0x1000) {
|
||||||
|
uint32 slow = abs(o1 - rot);
|
||||||
|
slow >>= 4; //scaling
|
||||||
|
speed -= slow;
|
||||||
|
}
|
||||||
|
|
||||||
|
//otherwise accelerate
|
||||||
|
else {
|
||||||
|
speed += accel;
|
||||||
|
if(speed > speed_max) {
|
||||||
|
speed = speed_max; //clip speed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//prevent negative/positive overflow
|
||||||
|
if(abs(old_speed - speed) > 0x8000) {
|
||||||
|
if(old_speed < speed) { speed = 0; }
|
||||||
|
else speed = 0xff00;
|
||||||
|
}
|
||||||
|
|
||||||
|
//adjust direction by so many degrees
|
||||||
|
//be careful of negative adjustments
|
||||||
|
if((o1 > rot && (o1 - rot) > 0x80) || (o1 < rot && (rot - o1) >= 0x80)) {
|
||||||
|
if(o1 < rot) { rot -= 0x280; }
|
||||||
|
else if(o1 > rot) { rot += 0x280; }
|
||||||
|
}
|
||||||
|
|
||||||
|
//turn of wrapping
|
||||||
|
if(wrap) { rot -= 0x8000; }
|
||||||
|
|
||||||
|
//now check the distances (store for later)
|
||||||
|
dx = (xpos_max << 16) - xpos;
|
||||||
|
dy = (ypos_max << 16) - ypos;
|
||||||
|
dx >>= 16;
|
||||||
|
dy >>= 16;
|
||||||
|
|
||||||
|
//if we're in so many units of the target, signal it
|
||||||
|
if((system && (dy <= 6 && dy >= -8) && (dx <= 126 && dx >= -128)) || (!system && (dx <= 6 && dx >= -8) && (dy <= 126 && dy >= -128))) {
|
||||||
|
//announce our new destination and flag it
|
||||||
|
xpos_max = xpos_new & 0x7fff;
|
||||||
|
ypos_max = ypos_new;
|
||||||
|
flags |= 0x08;
|
||||||
|
}
|
||||||
|
|
||||||
|
//update position
|
||||||
|
xpos -= (cos(rot) * 0x400 >> 15) * (speed >> 8) << 1;
|
||||||
|
ypos -= (sin(rot) * 0x400 >> 15) * (speed >> 8) << 1;
|
||||||
|
|
||||||
|
//quirk: mask upper byte
|
||||||
|
xpos &= 0x1fffffff;
|
||||||
|
ypos &= 0x1fffffff;
|
||||||
|
|
||||||
|
writew(0x00c0, ypos_max);
|
||||||
|
writew(0x00c2, xpos_max);
|
||||||
|
writed(0x00c4, ypos);
|
||||||
|
writed(0x00c8, xpos);
|
||||||
|
writew(0x00cc, rot);
|
||||||
|
writew(0x00d4, speed);
|
||||||
|
writew(0x00dc, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ST010::op_06() {
|
||||||
|
int16 multiplicand = readw(0x0000);
|
||||||
|
int16 multiplier = readw(0x0002);
|
||||||
|
int32 product;
|
||||||
|
|
||||||
|
product = multiplicand * multiplier << 1;
|
||||||
|
|
||||||
|
writed(0x0010, product);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ST010::op_07() {
|
||||||
|
int16 theta = readw(0x0000);
|
||||||
|
|
||||||
|
int16 data;
|
||||||
|
for(int i = 0, offset = 0; i < 176; i++) {
|
||||||
|
data = mode7_scale[i] * cos(theta) >> 15;
|
||||||
|
writew(0x00f0 + offset, data);
|
||||||
|
writew(0x0510 + offset, data);
|
||||||
|
|
||||||
|
data = mode7_scale[i] * sin(theta) >> 15;
|
||||||
|
writew(0x0250 + offset, data);
|
||||||
|
if(data) { data = ~data; }
|
||||||
|
writew(0x03b0 + offset, data);
|
||||||
|
|
||||||
|
offset += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ST010::op_08() {
|
||||||
|
int16 x0 = readw(0x0000);
|
||||||
|
int16 y0 = readw(0x0002);
|
||||||
|
int16 theta = readw(0x0004);
|
||||||
|
int16 x1, y1;
|
||||||
|
|
||||||
|
x1 = (y0 * sin(theta) >> 15) + (x0 * cos(theta) >> 15);
|
||||||
|
y1 = (y0 * cos(theta) >> 15) - (x0 * sin(theta) >> 15);
|
||||||
|
|
||||||
|
writew(0x0010, x1);
|
||||||
|
writew(0x0012, y1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //ifdef ST010_CPP
|
@@ -1 +1 @@
|
|||||||
@make PLATFORM=win-visualc-lui clean
|
@make platform=win compiler=mingw32-gcc clean
|
||||||
|
@@ -1,2 +1 @@
|
|||||||
#!/bin/sh
|
make platform=x compiler=gcc clean
|
||||||
make PLATFORM=x-gcc-lui clean
|
|
||||||
|
@@ -1,122 +1,119 @@
|
|||||||
Config config_file;
|
|
||||||
|
|
||||||
namespace config {
|
namespace config {
|
||||||
|
|
||||||
|
configuration& config() {
|
||||||
|
static configuration config;
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
integral_setting File::autodetect_type(config(), "file.autodetect_type",
|
||||||
|
"Auto-detect file type by inspecting file header, rather than by file extension.\n"
|
||||||
|
"In other words, if a .zip file is renamed to .smc, it will still be correctly\n"
|
||||||
|
"identified as a .zip file. However, there is an infinitesimal (1:~500,000,000)\n"
|
||||||
|
"chance of a false detection when loading an uncompressed image file, if this\n"
|
||||||
|
"option is enabled.",
|
||||||
|
integral_setting::boolean, false);
|
||||||
|
|
||||||
string file_updatepath(const char *req_file, const char *req_path) {
|
string file_updatepath(const char *req_file, const char *req_path) {
|
||||||
string file(req_file);
|
string file(req_file);
|
||||||
replace(file, "\\", "/");
|
replace(file, "\\", "/");
|
||||||
if(!req_path || strlen(req_path) == 0) { return file; }
|
if(!req_path || strlen(req_path) == 0) { return file; }
|
||||||
|
|
||||||
string path(req_path);
|
string path(req_path);
|
||||||
replace(path, "\\", "/");
|
replace(path, "\\", "/");
|
||||||
if(!strend(path, "/")) { strcat(path, "/"); }
|
if(!strend(path, "/")) { strcat(path, "/"); }
|
||||||
|
|
||||||
if(strbegin(path, "./")) {
|
if(strbegin(path, "./")) {
|
||||||
strltrim(path, "./");
|
ltrim(path(), "./");
|
||||||
string temp;
|
string temp;
|
||||||
strcpy(temp, config::path.base);
|
strcpy(temp, config::path.base);
|
||||||
strcat(temp, path);
|
strcat(temp, path);
|
||||||
strcpy(path, temp);
|
strcpy(path, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
stringarray part;
|
lstring part;
|
||||||
split(part, "/", file);
|
split(part, "/", file);
|
||||||
strcat(path, part[count(part) - 1]);
|
strcat(path, part[count(part) - 1]);
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringSetting Path::base(0, "fs.base_path",
|
string_setting Path::base("path.base",
|
||||||
"Path that bsnes resides in", "");
|
"Path that bsnes resides in", "");
|
||||||
StringSetting Path::rom(&config_file, "path.rom",
|
string_setting Path::rom(config(), "path.rom",
|
||||||
"Default path to look for ROM files in (\"\" = use default directory)", "");
|
"Default path to look for ROM files in (\"\" = use default directory)", "");
|
||||||
StringSetting Path::save(&config_file, "path.save",
|
string_setting Path::save(config(), "path.save",
|
||||||
"Default path for all save RAM and cheat files (\"\" = use current directory)", "");
|
"Default path for all save RAM files (\"\" = use current directory)", "");
|
||||||
StringSetting Path::bios(&config_file, "path.bios",
|
string_setting Path::cheat(config(), "path.cheat",
|
||||||
"Path where BIOS file(s) are located\n"
|
"Default path for all cheat files (\"\" = use current directory)", "");
|
||||||
"Supported BIOS files:\n"
|
string_setting Path::bsx(config(), "path.bsx", "", "");
|
||||||
"stbios.bin - Bandai Sufami Turbo"
|
string_setting Path::st(config(), "path.st", "", "");
|
||||||
"", "./bios");
|
|
||||||
|
|
||||||
StringSetting Path::save_ext(&config_file, "path.save_ext",
|
integral_setting SNES::controller_port0(config(), "snes.controller_port_1",
|
||||||
"Extension to be used for all save RAM files", "srm");
|
"Controller attached to SNES port 1", integral_setting::decimal, ::SNES::Input::DeviceIDJoypad1);
|
||||||
|
integral_setting SNES::controller_port1(config(), "snes.controller_port_2",
|
||||||
|
"Controller attached to SNES port 2", integral_setting::decimal, ::SNES::Input::DeviceIDJoypad2);
|
||||||
|
|
||||||
IntegerSetting SNES::gamma_ramp(&config_file, "snes.colorfilter.gamma_ramp",
|
integral_setting CPU::ntsc_clock_rate(config(), "cpu.ntsc_clock_rate",
|
||||||
"Use precalculated TV-style gamma ramp", IntegerSetting::Boolean, true);
|
"NTSC S-CPU clock rate (in hz)", integral_setting::decimal, 21477272);
|
||||||
IntegerSetting SNES::sepia(&config_file, "snes.colorfilter.sepia",
|
integral_setting CPU::pal_clock_rate(config(), "cpu.pal_clock_rate",
|
||||||
"Convert color to sepia tone", IntegerSetting::Boolean, false);
|
"PAL S-CPU clock rate (in hz)", integral_setting::decimal, 21281370);
|
||||||
IntegerSetting SNES::grayscale(&config_file, "snes.colorfilter.grayscale",
|
integral_setting CPU::wram_init_value(config(), "cpu.wram_init_value",
|
||||||
"Convert color to grayscale tone", IntegerSetting::Boolean, false);
|
"Value to initialize 128k WRAM to upon power cycle.\n"
|
||||||
IntegerSetting SNES::invert(&config_file, "snes.colorfilter.invert",
|
"Note that on real hardware, this value is undefined; meaning it can vary\n"
|
||||||
"Invert output image colors", IntegerSetting::Boolean, false);
|
"per power-on, and per SNES unit. Such randomness is undesirable for an\n"
|
||||||
IntegerSetting SNES::contrast(&config_file, "snes.colorfilter.contrast",
|
"emulator, so a static value is needed. There is also some form of pattern\n"
|
||||||
"Contrast", IntegerSetting::Decimal, 0);
|
"to the randomness that has yet to be determined, which some games rely upon.\n"
|
||||||
IntegerSetting SNES::brightness(&config_file, "snes.colorfilter.brightness",
|
"A value of 0x55 is safe for all known commercial software, and should be used.\n"
|
||||||
"Brightness", IntegerSetting::Decimal, 0);
|
"However, some software written for SNES copiers, or backup units, relies on\n"
|
||||||
IntegerSetting SNES::gamma(&config_file, "snes.colorfilter.gamma",
|
"WRAM being initialized to 0x00; which was a side-effect of the BIOS program\n"
|
||||||
"Gamma", IntegerSetting::Decimal, 80);
|
"which executed on these copiers. Using 0x00 will therefore fix many homebrew\n"
|
||||||
|
"programs, but *will* break some poorly programmed commercial software titles,\n"
|
||||||
|
"which do not properly initialize WRAM upon power cycle.\n",
|
||||||
|
integral_setting::hex, 0x55);
|
||||||
|
|
||||||
IntegerSetting SNES::ntsc_merge_fields(&config_file, "snes.ntsc_merge_fields",
|
integral_setting CPU::hdma_enable("cpu.hdma_enable",
|
||||||
"Merge fields in NTSC video filter\n"
|
"Enable HDMA effects", integral_setting::boolean, true);
|
||||||
"Set to true if using filter at any refresh rate other than 60hz\n"
|
|
||||||
"", IntegerSetting::Boolean, true);
|
|
||||||
|
|
||||||
IntegerSetting SNES::mute(&config_file, "snes.mute", "Mutes SNES audio output when enabled",
|
integral_setting SMP::ntsc_clock_rate(config(), "smp.ntsc_clock_rate",
|
||||||
IntegerSetting::Boolean, false);
|
"NTSC S-SMP clock rate (in hz)", integral_setting::decimal, 24606720);
|
||||||
|
integral_setting SMP::pal_clock_rate(config(), "smp.pal_clock_rate",
|
||||||
|
"PAL S-SMP clock rate (in hz)", integral_setting::decimal, 24606720);
|
||||||
|
|
||||||
IntegerSetting SNES::controller_port0(&config_file, "snes.controller_port_1",
|
integral_setting PPU::Hack::render_scanline_position(config(), "ppu.hack.render_scanline_position",
|
||||||
"Controller attached to SNES port 1", IntegerSetting::Decimal, ::SNES::DEVICEID_JOYPAD1);
|
|
||||||
IntegerSetting SNES::controller_port1(&config_file, "snes.controller_port_2",
|
|
||||||
"Controller attached to SNES port 2", IntegerSetting::Decimal, ::SNES::DEVICEID_JOYPAD2);
|
|
||||||
|
|
||||||
IntegerSetting CPU::ntsc_clock_rate(&config_file, "cpu.ntsc_clock_rate",
|
|
||||||
"NTSC S-CPU clock rate (in hz)", IntegerSetting::Decimal, 21477272);
|
|
||||||
IntegerSetting CPU::pal_clock_rate(&config_file, "cpu.pal_clock_rate",
|
|
||||||
"PAL S-CPU clock rate (in hz)", IntegerSetting::Decimal, 21281370);
|
|
||||||
|
|
||||||
IntegerSetting CPU::hdma_enable(0, "cpu.hdma_enable",
|
|
||||||
"Enable HDMA effects", IntegerSetting::Boolean, true);
|
|
||||||
|
|
||||||
IntegerSetting SMP::ntsc_clock_rate(&config_file, "smp.ntsc_clock_rate",
|
|
||||||
"NTSC S-SMP clock rate (in hz)", IntegerSetting::Decimal, 24606720);
|
|
||||||
IntegerSetting SMP::pal_clock_rate(&config_file, "smp.pal_clock_rate",
|
|
||||||
"PAL S-SMP clock rate (in hz)", IntegerSetting::Decimal, 24606720);
|
|
||||||
|
|
||||||
IntegerSetting PPU::Hack::render_scanline_position(&config_file, "ppu.hack.render_scanline_position",
|
|
||||||
"Approximate HCLOCK position to render at for scanline-based renderers",
|
"Approximate HCLOCK position to render at for scanline-based renderers",
|
||||||
IntegerSetting::Decimal, 512);
|
integral_setting::decimal, 512);
|
||||||
IntegerSetting PPU::Hack::obj_cache(&config_file, "ppu.hack.obj_cache",
|
integral_setting PPU::Hack::obj_cache(config(), "ppu.hack.obj_cache",
|
||||||
"Cache OAM OBJ attributes one scanline before rendering\n"
|
"Cache OAM OBJ attributes one scanline before rendering\n"
|
||||||
"This is technically closer to the actual operation of the SNES,\n"
|
"This is technically closer to the actual operation of the SNES,\n"
|
||||||
"but can cause problems in some games if enabled",
|
"but can cause problems in some games if enabled",
|
||||||
IntegerSetting::Boolean, false);
|
integral_setting::boolean, false);
|
||||||
IntegerSetting PPU::Hack::oam_address_invalidation(&config_file, "ppu.hack.oam_address_invalidation",
|
integral_setting PPU::Hack::oam_address_invalidation(config(), "ppu.hack.oam_address_invalidation",
|
||||||
"OAM access address changes during active display, as the S-PPU reads\n"
|
"OAM access address changes during active display, as the S-PPU reads\n"
|
||||||
"data to render the display. Thusly, the address retrieved when accessing\n"
|
"data to render the display. Thusly, the address retrieved when accessing\n"
|
||||||
"OAM during active display is unpredictable. Unfortunately, the exact\n"
|
"OAM during active display is unpredictable. Unfortunately, the exact\n"
|
||||||
"algorithm for this is completely unknown at this time. It is more hardware\n"
|
"algorithm for this is completely unknown at this time. It is more hardware\n"
|
||||||
"accurate to enable this setting, but one must *not* rely on the actual\n"
|
"accurate to enable this setting, but one must *not* rely on the actual\n"
|
||||||
"address to match hardware under emulation.",
|
"address to match hardware under emulation.",
|
||||||
IntegerSetting::Boolean, true);
|
integral_setting::boolean, true);
|
||||||
IntegerSetting PPU::Hack::cgram_address_invalidation(&config_file, "ppu.hack.cgram_address_invalidation",
|
integral_setting PPU::Hack::cgram_address_invalidation(config(), "ppu.hack.cgram_address_invalidation",
|
||||||
"CGRAM access address changes during active display (excluding hblank), as\n"
|
"CGRAM access address changes during active display (excluding hblank), as\n"
|
||||||
"the S-PPU reads data to render the display. Thusly, as with OAM, the access\n"
|
"the S-PPU reads data to render the display. Thusly, as with OAM, the access\n"
|
||||||
"address is unpredictable. Again, enabling this setting is more hardware\n"
|
"address is unpredictable. Again, enabling this setting is more hardware\n"
|
||||||
"accurate, but one must *not* rely on the actual address to match hardware\n"
|
"accurate, but one must *not* rely on the actual address to match hardware\n"
|
||||||
"under emulation.",
|
"under emulation.",
|
||||||
IntegerSetting::Boolean, true);
|
integral_setting::boolean, true);
|
||||||
|
|
||||||
IntegerSetting PPU::opt_enable(0, "ppu.opt_enable", "Enable offset-per-tile effects", IntegerSetting::Boolean, true);
|
integral_setting PPU::opt_enable("ppu.opt_enable", "Enable offset-per-tile effects", integral_setting::boolean, true);
|
||||||
IntegerSetting PPU::bg1_pri0_enable(0, "ppu.bg1_pri0_enable", "Enable BG1 Priority 0", IntegerSetting::Boolean, true);
|
integral_setting PPU::bg1_pri0_enable("ppu.bg1_pri0_enable", "Enable BG1 Priority 0", integral_setting::boolean, true);
|
||||||
IntegerSetting PPU::bg1_pri1_enable(0, "ppu.bg1_pri1_enable", "Enable BG1 Priority 1", IntegerSetting::Boolean, true);
|
integral_setting PPU::bg1_pri1_enable("ppu.bg1_pri1_enable", "Enable BG1 Priority 1", integral_setting::boolean, true);
|
||||||
IntegerSetting PPU::bg2_pri0_enable(0, "ppu.bg2_pri0_enable", "Enable BG2 Priority 0", IntegerSetting::Boolean, true);
|
integral_setting PPU::bg2_pri0_enable("ppu.bg2_pri0_enable", "Enable BG2 Priority 0", integral_setting::boolean, true);
|
||||||
IntegerSetting PPU::bg2_pri1_enable(0, "ppu.bg2_pri1_enable", "Enable BG2 Priority 1", IntegerSetting::Boolean, true);
|
integral_setting PPU::bg2_pri1_enable("ppu.bg2_pri1_enable", "Enable BG2 Priority 1", integral_setting::boolean, true);
|
||||||
IntegerSetting PPU::bg3_pri0_enable(0, "ppu.bg3_pri0_enable", "Enable BG3 Priority 0", IntegerSetting::Boolean, true);
|
integral_setting PPU::bg3_pri0_enable("ppu.bg3_pri0_enable", "Enable BG3 Priority 0", integral_setting::boolean, true);
|
||||||
IntegerSetting PPU::bg3_pri1_enable(0, "ppu.bg3_pri1_enable", "Enable BG3 Priority 1", IntegerSetting::Boolean, true);
|
integral_setting PPU::bg3_pri1_enable("ppu.bg3_pri1_enable", "Enable BG3 Priority 1", integral_setting::boolean, true);
|
||||||
IntegerSetting PPU::bg4_pri0_enable(0, "ppu.bg4_pri0_enable", "Enable BG4 Priority 0", IntegerSetting::Boolean, true);
|
integral_setting PPU::bg4_pri0_enable("ppu.bg4_pri0_enable", "Enable BG4 Priority 0", integral_setting::boolean, true);
|
||||||
IntegerSetting PPU::bg4_pri1_enable(0, "ppu.bg4_pri1_enable", "Enable BG4 Priority 1", IntegerSetting::Boolean, true);
|
integral_setting PPU::bg4_pri1_enable("ppu.bg4_pri1_enable", "Enable BG4 Priority 1", integral_setting::boolean, true);
|
||||||
IntegerSetting PPU::oam_pri0_enable(0, "ppu.oam_pri0_enable", "Enable OAM Priority 0", IntegerSetting::Boolean, true);
|
integral_setting PPU::oam_pri0_enable("ppu.oam_pri0_enable", "Enable OAM Priority 0", integral_setting::boolean, true);
|
||||||
IntegerSetting PPU::oam_pri1_enable(0, "ppu.oam_pri1_enable", "Enable OAM Priority 1", IntegerSetting::Boolean, true);
|
integral_setting PPU::oam_pri1_enable("ppu.oam_pri1_enable", "Enable OAM Priority 1", integral_setting::boolean, true);
|
||||||
IntegerSetting PPU::oam_pri2_enable(0, "ppu.oam_pri2_enable", "Enable OAM Priority 2", IntegerSetting::Boolean, true);
|
integral_setting PPU::oam_pri2_enable("ppu.oam_pri2_enable", "Enable OAM Priority 2", integral_setting::boolean, true);
|
||||||
IntegerSetting PPU::oam_pri3_enable(0, "ppu.oam_pri3_enable", "Enable OAM Priority 3", IntegerSetting::Boolean, true);
|
integral_setting PPU::oam_pri3_enable("ppu.oam_pri3_enable", "Enable OAM Priority 3", integral_setting::boolean, true);
|
||||||
|
|
||||||
};
|
} //namespace config
|
||||||
|
@@ -1,46 +1,48 @@
|
|||||||
extern Config config_file;
|
|
||||||
|
|
||||||
namespace config {
|
namespace config {
|
||||||
|
|
||||||
string file_updatepath(const char *, const char *);
|
extern configuration& config();
|
||||||
|
|
||||||
|
string file_updatepath(const char*, const char*);
|
||||||
|
|
||||||
|
extern struct File {
|
||||||
|
static integral_setting autodetect_type;
|
||||||
|
} file;
|
||||||
|
|
||||||
extern struct Path {
|
extern struct Path {
|
||||||
static StringSetting base, rom, save, bios;
|
static string_setting base, rom, save, cheat;
|
||||||
static StringSetting save_ext;
|
static string_setting bsx, st;
|
||||||
} path;
|
} path;
|
||||||
|
|
||||||
extern struct SNES {
|
extern struct SNES {
|
||||||
static IntegerSetting gamma_ramp, sepia, grayscale, invert, contrast, brightness, gamma;
|
static integral_setting controller_port0;
|
||||||
static IntegerSetting ntsc_merge_fields;
|
static integral_setting controller_port1;
|
||||||
static IntegerSetting mute;
|
|
||||||
static IntegerSetting controller_port0;
|
|
||||||
static IntegerSetting controller_port1;
|
|
||||||
} snes;
|
} snes;
|
||||||
|
|
||||||
extern struct CPU {
|
extern struct CPU {
|
||||||
static IntegerSetting ntsc_clock_rate, pal_clock_rate;
|
static integral_setting ntsc_clock_rate, pal_clock_rate;
|
||||||
static IntegerSetting hdma_enable;
|
static integral_setting wram_init_value;
|
||||||
|
static integral_setting hdma_enable;
|
||||||
} cpu;
|
} cpu;
|
||||||
|
|
||||||
extern struct SMP {
|
extern struct SMP {
|
||||||
static IntegerSetting ntsc_clock_rate, pal_clock_rate;
|
static integral_setting ntsc_clock_rate, pal_clock_rate;
|
||||||
} smp;
|
} smp;
|
||||||
|
|
||||||
extern struct PPU {
|
extern struct PPU {
|
||||||
struct Hack {
|
struct Hack {
|
||||||
static IntegerSetting render_scanline_position;
|
static integral_setting render_scanline_position;
|
||||||
static IntegerSetting obj_cache;
|
static integral_setting obj_cache;
|
||||||
static IntegerSetting oam_address_invalidation;
|
static integral_setting oam_address_invalidation;
|
||||||
static IntegerSetting cgram_address_invalidation;
|
static integral_setting cgram_address_invalidation;
|
||||||
} hack;
|
} hack;
|
||||||
|
|
||||||
static IntegerSetting opt_enable;
|
static integral_setting opt_enable;
|
||||||
static IntegerSetting bg1_pri0_enable, bg1_pri1_enable;
|
static integral_setting bg1_pri0_enable, bg1_pri1_enable;
|
||||||
static IntegerSetting bg2_pri0_enable, bg2_pri1_enable;
|
static integral_setting bg2_pri0_enable, bg2_pri1_enable;
|
||||||
static IntegerSetting bg3_pri0_enable, bg3_pri1_enable;
|
static integral_setting bg3_pri0_enable, bg3_pri1_enable;
|
||||||
static IntegerSetting bg4_pri0_enable, bg4_pri1_enable;
|
static integral_setting bg4_pri0_enable, bg4_pri1_enable;
|
||||||
static IntegerSetting oam_pri0_enable, oam_pri1_enable;
|
static integral_setting oam_pri0_enable, oam_pri1_enable;
|
||||||
static IntegerSetting oam_pri2_enable, oam_pri3_enable;
|
static integral_setting oam_pri2_enable, oam_pri3_enable;
|
||||||
} ppu;
|
} ppu;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
#include "../base.h"
|
#include "../base.h"
|
||||||
|
#define CPU_CPP
|
||||||
|
|
||||||
#include "dcpu.cpp"
|
#include "dcpu.cpp"
|
||||||
|
|
||||||
CPU::CPU() {
|
CPU::CPU() {
|
||||||
|
@@ -4,41 +4,35 @@ class CPU : public MMIO {
|
|||||||
public:
|
public:
|
||||||
virtual void enter() = 0;
|
virtual void enter() = 0;
|
||||||
|
|
||||||
public:
|
//CPU version number
|
||||||
//CPU version number
|
//* 1 and 2 are known
|
||||||
//* 1 and 2 are known
|
//* reported by $4210
|
||||||
//* reported by $4210
|
//* affects DRAM refresh behavior
|
||||||
//* affects DRAM refresh behavior
|
uint8 cpu_version;
|
||||||
uint8 cpu_version;
|
|
||||||
|
|
||||||
//timing
|
//timing
|
||||||
virtual uint16 vcounter() = 0;
|
virtual uint16 vcounter() = 0;
|
||||||
virtual uint16 hcounter() = 0;
|
virtual uint16 hcounter() = 0;
|
||||||
virtual uint16 hclock() = 0;
|
virtual uint16 hdot() = 0;
|
||||||
virtual bool interlace() = 0;
|
|
||||||
virtual bool interlace_field() = 0;
|
|
||||||
virtual bool overscan() = 0;
|
|
||||||
virtual uint16 region_scanlines() = 0;
|
|
||||||
virtual void set_interlace(bool r) = 0;
|
|
||||||
virtual void set_overscan (bool r) = 0;
|
|
||||||
|
|
||||||
CPURegs regs;
|
virtual uint8 pio_status() = 0;
|
||||||
virtual uint8 port_read (uint8 port) = 0;
|
virtual uint8 port_read(uint8 port) = 0;
|
||||||
virtual void port_write(uint8 port, uint8 value) = 0;
|
virtual void port_write(uint8 port, uint8 value) = 0;
|
||||||
|
|
||||||
|
CPURegs regs;
|
||||||
enum {
|
enum {
|
||||||
FLAG_N = 0x80, FLAG_V = 0x40,
|
FLAG_N = 0x80, FLAG_V = 0x40,
|
||||||
FLAG_M = 0x20, FLAG_X = 0x10,
|
FLAG_M = 0x20, FLAG_X = 0x10,
|
||||||
FLAG_D = 0x08, FLAG_I = 0x04,
|
FLAG_D = 0x08, FLAG_I = 0x04,
|
||||||
FLAG_Z = 0x02, FLAG_C = 0x01
|
FLAG_Z = 0x02, FLAG_C = 0x01
|
||||||
};
|
};
|
||||||
virtual uint8 pio_status() = 0;
|
|
||||||
virtual void scanline() = 0;
|
virtual void scanline() = 0;
|
||||||
virtual void frame() = 0;
|
virtual void frame() = 0;
|
||||||
virtual void power() = 0;
|
virtual void power() = 0;
|
||||||
virtual void reset() = 0;
|
virtual void reset() = 0;
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
* in opcode-based CPU emulators, the main emulation routine
|
* in opcode-based CPU emulators, the main emulation routine
|
||||||
* will only be able to call the disassemble_opcode() function
|
* will only be able to call the disassemble_opcode() function
|
||||||
* on clean opcode edges. but with cycle-based CPU emulators,
|
* on clean opcode edges. but with cycle-based CPU emulators,
|
||||||
@@ -53,10 +47,10 @@ CPURegs regs;
|
|||||||
*****/
|
*****/
|
||||||
virtual bool in_opcode() { return false; }
|
virtual bool in_opcode() { return false; }
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
* opcode disassembler
|
* opcode disassembler
|
||||||
*****/
|
*****/
|
||||||
enum {
|
enum {
|
||||||
OPTYPE_DP = 0, //dp
|
OPTYPE_DP = 0, //dp
|
||||||
OPTYPE_DPX, //dp,x
|
OPTYPE_DPX, //dp,x
|
||||||
OPTYPE_DPY, //dp,y
|
OPTYPE_DPY, //dp,y
|
||||||
@@ -78,7 +72,7 @@ enum {
|
|||||||
OPTYPE_IADDR_PC, //pbr:(addr)
|
OPTYPE_IADDR_PC, //pbr:(addr)
|
||||||
OPTYPE_RELB, //relb
|
OPTYPE_RELB, //relb
|
||||||
OPTYPE_RELW, //relw
|
OPTYPE_RELW, //relw
|
||||||
};
|
};
|
||||||
|
|
||||||
void disassemble_opcode(char *output);
|
void disassemble_opcode(char *output);
|
||||||
uint8 dreadb(uint32 addr);
|
uint8 dreadb(uint32 addr);
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
class CPURegFlags {
|
class CPURegFlags {
|
||||||
public:
|
public:
|
||||||
union {
|
union {
|
||||||
uint8 data;
|
uint8 data;
|
||||||
struct {
|
struct {
|
||||||
bool order_msb8(n:1, v:1, m:1, x:1, d:1, i:1, z:1, c:1);
|
bool order_msb8(n:1, v:1, m:1, x:1, d:1, i:1, z:1, c:1);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
inline operator unsigned() const { return data; }
|
inline operator unsigned() const { return data; }
|
||||||
template<typename T> inline unsigned operator = (const T i) { data = i; return data; }
|
template<typename T> inline unsigned operator = (const T i) { data = i; return data; }
|
||||||
@@ -18,10 +18,10 @@ union {
|
|||||||
|
|
||||||
class CPUReg16 {
|
class CPUReg16 {
|
||||||
public:
|
public:
|
||||||
union {
|
union {
|
||||||
uint16 w;
|
uint16 w;
|
||||||
struct { uint8 order_lsb2(l, h); };
|
struct { uint8 order_lsb2(l, h); };
|
||||||
};
|
};
|
||||||
|
|
||||||
inline operator unsigned() const { return w; }
|
inline operator unsigned() const { return w; }
|
||||||
template<typename T> inline unsigned operator = (const T i) { w = i; return w; }
|
template<typename T> inline unsigned operator = (const T i) { w = i; return w; }
|
||||||
@@ -41,11 +41,11 @@ union {
|
|||||||
|
|
||||||
class CPUReg24 {
|
class CPUReg24 {
|
||||||
public:
|
public:
|
||||||
union {
|
union {
|
||||||
uint32 d;
|
uint32 d;
|
||||||
struct { uint16 order_lsb2(w, wh); };
|
struct { uint16 order_lsb2(w, wh); };
|
||||||
struct { uint8 order_lsb4(l, h, b, bh); };
|
struct { uint8 order_lsb4(l, h, b, bh); };
|
||||||
};
|
};
|
||||||
|
|
||||||
inline operator unsigned() const { return d; }
|
inline operator unsigned() const { return d; }
|
||||||
template<typename T> inline unsigned operator = (const T i) { d = uclip<24>(i); return d; }
|
template<typename T> inline unsigned operator = (const T i) { d = uclip<24>(i); return d; }
|
||||||
@@ -65,11 +65,11 @@ union {
|
|||||||
|
|
||||||
class CPURegs {
|
class CPURegs {
|
||||||
public:
|
public:
|
||||||
CPUReg24 pc;
|
CPUReg24 pc;
|
||||||
CPUReg16 a, x, y, s, d;
|
CPUReg16 a, x, y, s, d;
|
||||||
CPURegFlags p;
|
CPURegFlags p;
|
||||||
uint8 db;
|
uint8 db;
|
||||||
uint8 mdr;
|
uint8 mdr;
|
||||||
bool e;
|
bool e;
|
||||||
CPURegs() : db(0), mdr(0x00), e(false) {}
|
CPURegs() : db(0), mdr(0x00), e(false) {}
|
||||||
};
|
};
|
||||||
|
@@ -1,10 +1,12 @@
|
|||||||
|
#ifdef CPU_CPP
|
||||||
|
|
||||||
uint8 CPU::dreadb(uint32 addr) {
|
uint8 CPU::dreadb(uint32 addr) {
|
||||||
if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) {
|
if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) {
|
||||||
//$[00-3f|80-bf]:[2000-5fff]
|
//$[00-3f|80-bf]:[2000-5fff]
|
||||||
//do not read MMIO registers within debugger
|
//do not read MMIO registers within debugger
|
||||||
return 0x00;
|
return 0x00;
|
||||||
}
|
}
|
||||||
return r_mem->read(addr);
|
return bus.read(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 CPU::dreadw(uint32 addr) {
|
uint16 CPU::dreadw(uint32 addr) {
|
||||||
@@ -423,7 +425,7 @@ uint8 op2 = dreadb(pc.d);
|
|||||||
strcat(s, t);
|
strcat(s, t);
|
||||||
strcat(s, " ");
|
strcat(s, " ");
|
||||||
|
|
||||||
sprintf(t, "V:%3d H:%4d", vcounter(), hclock());
|
sprintf(t, "V:%3d H:%4d", vcounter(), hcounter());
|
||||||
strcat(s, t);
|
strcat(s, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,3 +475,5 @@ static uint8 op_len_tbl[256] = {
|
|||||||
if(len == 6)return (regs.e || regs.p.x) ? 2 : 3;
|
if(len == 6)return (regs.e || regs.p.x) ? 2 : 3;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif //ifdef CPU_CPP
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef SCPU_CPP
|
||||||
|
|
||||||
#include "opfn.cpp"
|
#include "opfn.cpp"
|
||||||
|
|
||||||
#include "op_read.cpp"
|
#include "op_read.cpp"
|
||||||
@@ -43,8 +45,6 @@ void sCPU::op_irq() {
|
|||||||
regs.pc.w = rd.w;
|
regs.pc.w = rd.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
alwaysinline void sCPU::op_io_cond2() {
|
alwaysinline void sCPU::op_io_cond2() {
|
||||||
if(regs.d.l != 0x00) {
|
if(regs.d.l != 0x00) {
|
||||||
op_io();
|
op_io();
|
||||||
@@ -62,3 +62,5 @@ alwaysinline void sCPU::op_io_cond6(uint16 addr) {
|
|||||||
op_io();
|
op_io();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif //ifdef SCPU_CPP
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
void (sCPU::*optbl[256])();
|
void (sCPU::*optbl[256])();
|
||||||
|
|
||||||
CPUReg24 aa, rd;
|
CPUReg24 aa, rd;
|
||||||
uint8 dp, sp;
|
uint8_t dp, sp;
|
||||||
|
|
||||||
void op_irq();
|
void op_irq();
|
||||||
|
|
||||||
inline bool in_opcode() { return status.in_opcode; }
|
inline bool in_opcode() { return status.in_opcode; }
|
||||||
|
|
||||||
//op_read
|
//op_read
|
||||||
void op_adc_b();
|
void op_adc_b();
|
||||||
void op_adc_w();
|
void op_adc_w();
|
||||||
void op_and_b();
|
void op_and_b();
|
||||||
@@ -32,7 +32,7 @@ uint8 dp, sp;
|
|||||||
void op_ora_w();
|
void op_ora_w();
|
||||||
void op_sbc_b();
|
void op_sbc_b();
|
||||||
void op_sbc_w();
|
void op_sbc_w();
|
||||||
//op_rmw
|
//op_rmw
|
||||||
void op_inc_b();
|
void op_inc_b();
|
||||||
void op_inc_w();
|
void op_inc_w();
|
||||||
void op_dec_b();
|
void op_dec_b();
|
||||||
@@ -54,4 +54,4 @@ uint8 dp, sp;
|
|||||||
void op_io_cond4(uint16 x, uint16 y);
|
void op_io_cond4(uint16 x, uint16 y);
|
||||||
void op_io_cond6(uint16 addr);
|
void op_io_cond6(uint16 addr);
|
||||||
|
|
||||||
#include "op.h"
|
#include "op.h"
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef SCPU_CPP
|
||||||
|
|
||||||
//op_read
|
//op_read
|
||||||
inline void sCPU::op_adc_b() {
|
inline void sCPU::op_adc_b() {
|
||||||
int32 r = regs.a.l + rd.l + regs.p.c;
|
int32 r = regs.a.l + rd.l + regs.p.c;
|
||||||
@@ -371,3 +373,5 @@ inline void sCPU::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 //ifdef SCPU_CPP
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef SCPU_CPP
|
||||||
|
|
||||||
void sCPU::dma_add_clocks(uint clocks) {
|
void sCPU::dma_add_clocks(uint clocks) {
|
||||||
status.dma_clocks += clocks;
|
status.dma_clocks += clocks;
|
||||||
add_clocks(clocks);
|
add_clocks(clocks);
|
||||||
@@ -10,30 +12,44 @@ void sCPU::dma_add_clocks(uint clocks) {
|
|||||||
* $[00-3f|80-bf]:43[00-7f] <DMA control registers>
|
* $[00-3f|80-bf]:43[00-7f] <DMA control registers>
|
||||||
* $[00-3f|80-bf]:420b <DMA enable register>
|
* $[00-3f|80-bf]:420b <DMA enable register>
|
||||||
* $[00-3f|80-bf]:420c <HDMA enable register>
|
* $[00-3f|80-bf]:420c <HDMA enable register>
|
||||||
* WRAM<>WRAM transfers via $2180
|
*
|
||||||
|
* WRAM<>WRAM transfers via $2180 are also illegal
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
void sCPU::dma_transfer(bool direction, uint8 bbus, uint32 abus) {
|
void sCPU::dma_transfer(bool direction, uint8 bbus, uint32 abus) {
|
||||||
uint8 r;
|
if(direction == 0) {
|
||||||
if(direction == 0) { //a->b
|
//a->b transfer (to $21xx)
|
||||||
if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300 ||
|
if(bbus == 0x80 && ((abus & 0xfe0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) {
|
||||||
(abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c) {
|
//illegal WRAM->WRAM transfer
|
||||||
r = regs.mdr;
|
//read most likely occurs; no write occurs
|
||||||
|
//read is irrelevant, as it has no observable effect on emulation
|
||||||
|
} else if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300
|
||||||
|
|| (abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c) {
|
||||||
|
//illegal register access
|
||||||
|
bus.write(0x2100 | bbus, regs.mdr); //TODO: verify if MDR is written here
|
||||||
} else {
|
} else {
|
||||||
r = r_mem->read(abus);
|
//valid transfer
|
||||||
|
bus.write(0x2100 | bbus, bus.read(abus));
|
||||||
}
|
}
|
||||||
r_mem->write(0x2100 | bbus, r);
|
|
||||||
} else { //b->a
|
|
||||||
if(bbus == 0x80 && ((abus & 0x7e0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) {
|
|
||||||
//prevent WRAM->WRAM transfers
|
|
||||||
r = regs.mdr;
|
|
||||||
} else {
|
} else {
|
||||||
r = r_mem->read(0x2100 | bbus);
|
//b->a transfer (from $21xx)
|
||||||
|
if(bbus == 0x80 && ((abus & 0xfe0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) {
|
||||||
|
//illegal WRAM->WRAM transfer
|
||||||
|
//no read occurs; write does occur
|
||||||
|
//does not write MDR as expected
|
||||||
|
//TODO: 0x00 was observed on hardware; verify if other values are possible
|
||||||
|
bus.write(abus, 0x00);
|
||||||
|
} else if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300
|
||||||
|
|| (abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c) {
|
||||||
|
//illegal register access
|
||||||
|
bus.write(abus, regs.mdr); //TODO: verify if MDR is written here
|
||||||
|
} else {
|
||||||
|
//valid transfer
|
||||||
|
bus.write(abus, bus.read(0x2100 | bbus));
|
||||||
}
|
}
|
||||||
if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300 ||
|
|
||||||
(abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c)return;
|
|
||||||
r_mem->write(abus, r);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//each byte *always* consumes 8 clocks, even if transfer is invalid and no read and/or write occurs
|
||||||
dma_add_clocks(8);
|
dma_add_clocks(8);
|
||||||
cycle_edge();
|
cycle_edge();
|
||||||
}
|
}
|
||||||
@@ -43,21 +59,20 @@ uint8 r;
|
|||||||
*****/
|
*****/
|
||||||
|
|
||||||
uint8 sCPU::dma_bbus(uint8 i, uint8 index) {
|
uint8 sCPU::dma_bbus(uint8 i, uint8 index) {
|
||||||
switch(channel[i].xfermode) {
|
switch(channel[i].xfermode) { default:
|
||||||
default:
|
case 0: return (channel[i].destaddr); //0
|
||||||
case 0: return (channel[i].destaddr); break; //0
|
case 1: return (channel[i].destaddr + (index & 1)); //0,1
|
||||||
case 1: return (channel[i].destaddr + (index & 1)); break; //0,1
|
case 2: return (channel[i].destaddr); //0,0
|
||||||
case 2: return (channel[i].destaddr); break; //0,0
|
case 3: return (channel[i].destaddr + ((index >> 1) & 1)); //0,0,1,1
|
||||||
case 3: return (channel[i].destaddr + ((index >> 1) & 1)); break; //0,0,1,1
|
case 4: return (channel[i].destaddr + (index & 3)); //0,1,2,3
|
||||||
case 4: return (channel[i].destaddr + (index & 3)); break; //0,1,2,3
|
case 5: return (channel[i].destaddr + (index & 1)); //0,1,0,1
|
||||||
case 5: return (channel[i].destaddr + (index & 1)); break; //0,1,0,1
|
case 6: return (channel[i].destaddr); //0,0 [2]
|
||||||
case 6: return (channel[i].destaddr); break; //0,0 [2]
|
case 7: return (channel[i].destaddr + ((index >> 1) & 1)); //0,0,1,1 [3]
|
||||||
case 7: return (channel[i].destaddr + ((index >> 1) & 1)); break; //0,0,1,1 [3]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32 sCPU::dma_addr(uint8 i) {
|
inline uint32 sCPU::dma_addr(uint8 i) {
|
||||||
uint32 r = (channel[i].srcbank << 16) | (channel[i].srcaddr);
|
uint32 r = (channel[i].srcbank << 16) | (channel[i].srcaddr);
|
||||||
|
|
||||||
if(channel[i].fixedxfer == false) {
|
if(channel[i].fixedxfer == false) {
|
||||||
if(channel[i].reversexfer == false) {
|
if(channel[i].reversexfer == false) {
|
||||||
@@ -83,8 +98,8 @@ inline uint32 sCPU::hdma_iaddr(uint8 i) {
|
|||||||
*****/
|
*****/
|
||||||
|
|
||||||
void sCPU::dma_transfertobusb(uint8 i, uint8 bbus) {
|
void sCPU::dma_transfertobusb(uint8 i, uint8 bbus) {
|
||||||
if(cartridge.info.sdd1 == true && sdd1->dma_active() == true) {
|
if(cartridge.info.sdd1 == true && sdd1.dma_active() == true) {
|
||||||
r_mem->write(0x2100 | bbus, sdd1->dma_read());
|
bus.write(0x2100 | bbus, sdd1.dma_read());
|
||||||
} else {
|
} else {
|
||||||
dma_transfer(0, bbus, dma_addr(i));
|
dma_transfer(0, bbus, dma_addr(i));
|
||||||
}
|
}
|
||||||
@@ -97,7 +112,7 @@ void sCPU::dma_transfertobusa(uint8 i, uint8 bbus) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::dma_write(uint8 i, uint8 index) {
|
inline void sCPU::dma_write(uint8 i, uint8 index) {
|
||||||
//cannot use dma_transfer() directly, due to current S-DD1 implementation
|
//cannot use dma_transfer() directly, due to current S-DD1 implementation
|
||||||
if(channel[i].direction == 0) {
|
if(channel[i].direction == 0) {
|
||||||
dma_transfertobusb(i, index);
|
dma_transfertobusb(i, index);
|
||||||
} else {
|
} else {
|
||||||
@@ -107,12 +122,11 @@ inline void sCPU::dma_write(uint8 i, uint8 index) {
|
|||||||
|
|
||||||
void sCPU::dma_run() {
|
void sCPU::dma_run() {
|
||||||
for(int i = 0; i < 8; i++) {
|
for(int i = 0; i < 8; i++) {
|
||||||
if(channel[i].dma_enabled == false)continue;
|
if(channel[i].dma_enabled == false) continue;
|
||||||
dma_add_clocks(8);
|
dma_add_clocks(8);
|
||||||
|
|
||||||
if(cartridge.info.sdd1 == true) {
|
if(cartridge.info.sdd1 == true) {
|
||||||
sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr),
|
sdd1.dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr), channel[i].xfersize);
|
||||||
channel[i].xfersize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tracer.enabled() == true && tracer.cpudma_enabled() == true) {
|
if(tracer.enabled() == true && tracer.cpudma_enabled() == true) {
|
||||||
@@ -145,51 +159,50 @@ inline bool sCPU::hdma_active(uint8 i) {
|
|||||||
|
|
||||||
inline bool sCPU::hdma_active_after(uint8 i) {
|
inline bool sCPU::hdma_active_after(uint8 i) {
|
||||||
for(int n = i + 1; n < 8; n++) {
|
for(int n = i + 1; n < 8; n++) {
|
||||||
if(hdma_active(n) == true) { return true; }
|
if(hdma_active(n) == true) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint8 sCPU::hdma_enabled_channels() {
|
inline uint8 sCPU::hdma_enabled_channels() {
|
||||||
uint8 r = 0;
|
uint8 r = 0;
|
||||||
for(int i = 0; i < 8; i++) {
|
for(int i = 0; i < 8; i++) {
|
||||||
if(channel[i].hdma_enabled)r++;
|
if(channel[i].hdma_enabled) r++;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint8 sCPU::hdma_active_channels() {
|
inline uint8 sCPU::hdma_active_channels() {
|
||||||
uint8 r = 0;
|
uint8 r = 0;
|
||||||
for(int i = 0; i < 8; i++) {
|
for(int i = 0; i < 8; i++) {
|
||||||
if(hdma_active(i) == true)r++;
|
if(hdma_active(i) == true) r++;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sCPU::hdma_update(uint8 i) {
|
void sCPU::hdma_update(uint8 i) {
|
||||||
channel[i].hdma_line_counter = r_mem->read(hdma_addr(i));
|
channel[i].hdma_line_counter = bus.read(hdma_addr(i));
|
||||||
dma_add_clocks(8);
|
dma_add_clocks(8);
|
||||||
|
|
||||||
channel[i].hdma_completed = (channel[i].hdma_line_counter == 0);
|
channel[i].hdma_completed = (channel[i].hdma_line_counter == 0);
|
||||||
channel[i].hdma_do_transfer = !channel[i].hdma_completed;
|
channel[i].hdma_do_transfer = !channel[i].hdma_completed;
|
||||||
|
|
||||||
if(channel[i].hdma_indirect) {
|
if(channel[i].hdma_indirect) {
|
||||||
channel[i].hdma_iaddr = r_mem->read(hdma_addr(i)) << 8;
|
channel[i].hdma_iaddr = bus.read(hdma_addr(i)) << 8;
|
||||||
dma_add_clocks(8);
|
dma_add_clocks(8);
|
||||||
|
|
||||||
if(!channel[i].hdma_completed || hdma_active_after(i)) {
|
if(!channel[i].hdma_completed || hdma_active_after(i)) {
|
||||||
channel[i].hdma_iaddr >>= 8;
|
channel[i].hdma_iaddr >>= 8;
|
||||||
channel[i].hdma_iaddr |= r_mem->read(hdma_addr(i)) << 8;
|
channel[i].hdma_iaddr |= bus.read(hdma_addr(i)) << 8;
|
||||||
dma_add_clocks(8);
|
dma_add_clocks(8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sCPU::hdma_run() {
|
void sCPU::hdma_run() {
|
||||||
static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
|
static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
|
||||||
for(int i = 0; i < 8; i++) {
|
for(int i = 0; i < 8; i++) {
|
||||||
if(hdma_active(i) == false)continue;
|
if(hdma_active(i) == false) continue;
|
||||||
channel[i].dma_enabled = false; //HDMA run during DMA will stop DMA mid-transfer
|
channel[i].dma_enabled = false; //HDMA run during DMA will stop DMA mid-transfer
|
||||||
dma_add_clocks(8);
|
dma_add_clocks(8);
|
||||||
|
|
||||||
@@ -272,3 +285,5 @@ void sCPU::dma_reset() {
|
|||||||
channel[i].hdma_do_transfer = false;
|
channel[i].hdma_do_transfer = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif //ifdef SCPU_CPP
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
struct {
|
struct {
|
||||||
//$420b
|
//$420b
|
||||||
bool dma_enabled;
|
bool dma_enabled;
|
||||||
|
|
||||||
//$420c
|
//$420c
|
||||||
bool hdma_enabled;
|
bool hdma_enabled;
|
||||||
|
|
||||||
//$43x0
|
//$43x0
|
||||||
uint8 dmap;
|
uint8 dmap;
|
||||||
bool direction;
|
bool direction;
|
||||||
bool hdma_indirect;
|
bool hdma_indirect;
|
||||||
@@ -13,37 +13,37 @@ struct {
|
|||||||
bool fixedxfer;
|
bool fixedxfer;
|
||||||
uint8 xfermode;
|
uint8 xfermode;
|
||||||
|
|
||||||
//$43x1
|
//$43x1
|
||||||
uint8 destaddr;
|
uint8 destaddr;
|
||||||
|
|
||||||
//$43x2-$43x3
|
//$43x2-$43x3
|
||||||
uint16 srcaddr;
|
uint16 srcaddr;
|
||||||
|
|
||||||
//$43x4
|
//$43x4
|
||||||
uint8 srcbank;
|
uint8 srcbank;
|
||||||
|
|
||||||
//$43x5-$43x6
|
//$43x5-$43x6
|
||||||
union {
|
union {
|
||||||
uint16 xfersize;
|
uint16 xfersize;
|
||||||
uint16 hdma_iaddr;
|
uint16 hdma_iaddr;
|
||||||
};
|
};
|
||||||
|
|
||||||
//$43x7
|
//$43x7
|
||||||
uint8 hdma_ibank;
|
uint8 hdma_ibank;
|
||||||
|
|
||||||
//$43x8-$43x9
|
//$43x8-$43x9
|
||||||
uint16 hdma_addr;
|
uint16 hdma_addr;
|
||||||
|
|
||||||
//$43xa
|
//$43xa
|
||||||
uint8 hdma_line_counter;
|
uint8 hdma_line_counter;
|
||||||
|
|
||||||
//$43xb/$43xf
|
//$43xb/$43xf
|
||||||
uint8 unknown;
|
uint8 unknown;
|
||||||
|
|
||||||
//internal variables
|
//internal variables
|
||||||
bool hdma_completed;
|
bool hdma_completed;
|
||||||
bool hdma_do_transfer;
|
bool hdma_do_transfer;
|
||||||
} channel[8];
|
} channel[8];
|
||||||
|
|
||||||
void dma_add_clocks(uint clocks);
|
void dma_add_clocks(uint clocks);
|
||||||
void dma_transfer(bool direction, uint8 bbus, uint32 abus);
|
void dma_transfer(bool direction, uint8 bbus, uint32 abus);
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef SCPU_CPP
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
* These 3 functions control bus timing for the CPU.
|
* These 3 functions control bus timing for the CPU.
|
||||||
* cpu_io is an I/O cycle, and always 6 clock cycles long.
|
* cpu_io is an I/O cycle, and always 6 clock cycles long.
|
||||||
@@ -14,21 +16,21 @@ void sCPU::op_io() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8 sCPU::op_read(uint32 addr) {
|
uint8 sCPU::op_read(uint32 addr) {
|
||||||
status.clock_count = r_mem->speed(addr);
|
status.clock_count = bus.speed(addr);
|
||||||
precycle_edge();
|
precycle_edge();
|
||||||
add_clocks(status.clock_count - 4);
|
add_clocks(status.clock_count - 4);
|
||||||
regs.mdr = r_mem->read(addr);
|
regs.mdr = bus.read(addr);
|
||||||
add_clocks(4);
|
add_clocks(4);
|
||||||
cycle_edge();
|
cycle_edge();
|
||||||
return regs.mdr;
|
return regs.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sCPU::op_write(uint32 addr, uint8 data) {
|
void sCPU::op_write(uint32 addr, uint8 data) {
|
||||||
status.clock_count = r_mem->speed(addr);
|
status.clock_count = bus.speed(addr);
|
||||||
precycle_edge();
|
precycle_edge();
|
||||||
add_clocks(status.clock_count);
|
add_clocks(status.clock_count);
|
||||||
regs.mdr = data;
|
regs.mdr = data;
|
||||||
r_mem->write(addr, regs.mdr);
|
bus.write(addr, regs.mdr);
|
||||||
cycle_edge();
|
cycle_edge();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,3 +121,5 @@ alwaysinline void sCPU::op_writedp(uint32 addr, uint8 data) {
|
|||||||
alwaysinline void sCPU::op_writesp(uint32 addr, uint8 data) {
|
alwaysinline void sCPU::op_writesp(uint32 addr, uint8 data) {
|
||||||
op_write((regs.s + (addr & 0xffff)) & 0xffff, data);
|
op_write((regs.s + (addr & 0xffff)) & 0xffff, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif //ifdef SCPU_CPP
|
||||||
|
@@ -1,18 +1,18 @@
|
|||||||
/*****
|
/*****
|
||||||
* CPU<>APU communication ports
|
* CPU<>APU communication ports
|
||||||
*****/
|
*****/
|
||||||
uint8 apu_port[4];
|
uint8 apu_port[4];
|
||||||
uint8 port_read (uint8 port) { return apu_port[port & 3]; }
|
uint8 port_read(uint8 port) { return apu_port[port & 3]; }
|
||||||
void port_write(uint8 port, uint8 data) { apu_port[port & 3] = data; }
|
void port_write(uint8 port, uint8 data) { apu_port[port & 3] = data; }
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
* core CPU bus functions
|
* core CPU bus functions
|
||||||
*****/
|
*****/
|
||||||
void op_io();
|
void op_io();
|
||||||
uint8 op_read (uint32 addr);
|
uint8 op_read(uint32 addr);
|
||||||
void op_write(uint32 addr, uint8 data);
|
void op_write(uint32 addr, uint8 data);
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
* helper memory addressing functions used by CPU core
|
* helper memory addressing functions used by CPU core
|
||||||
*****/
|
*****/
|
||||||
uint8 op_readpc ();
|
uint8 op_readpc ();
|
||||||
|
@@ -1,17 +1,19 @@
|
|||||||
|
#ifdef SCPU_CPP
|
||||||
|
|
||||||
uint8 sCPU::pio_status() {
|
uint8 sCPU::pio_status() {
|
||||||
return status.pio;
|
return status.pio;
|
||||||
}
|
}
|
||||||
|
|
||||||
//WMDATA
|
//WMDATA
|
||||||
uint8 sCPU::mmio_r2180() {
|
uint8 sCPU::mmio_r2180() {
|
||||||
uint8 r = r_mem->read(0x7e0000 | status.wram_addr);
|
uint8 r = bus.read(0x7e0000 | status.wram_addr);
|
||||||
status.wram_addr = (status.wram_addr + 1) & 0x01ffff;
|
status.wram_addr = (status.wram_addr + 1) & 0x01ffff;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
//WMDATA
|
//WMDATA
|
||||||
void sCPU::mmio_w2180(uint8 data) {
|
void sCPU::mmio_w2180(uint8 data) {
|
||||||
r_mem->write(0x7e0000 | status.wram_addr, data);
|
bus.write(0x7e0000 | status.wram_addr, data);
|
||||||
status.wram_addr = (status.wram_addr + 1) & 0x01ffff;
|
status.wram_addr = (status.wram_addr + 1) & 0x01ffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +43,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.poll_input();
|
snes.input.poll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,8 +54,8 @@ void sCPU::mmio_w4016(uint8 data) {
|
|||||||
//TODO: test whether strobe latch of zero returns
|
//TODO: test whether strobe latch of zero returns
|
||||||
//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 |= (uint8)snes.port_read(0);
|
r |= (uint8)snes.input.port_read(0);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,8 +64,8 @@ uint8 r = regs.mdr & 0xfc;
|
|||||||
//4-2 = Always 1 (pins are connected to GND)
|
//4-2 = Always 1 (pins are connected to GND)
|
||||||
//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 |= (uint8)snes.port_read(1);
|
r |= (uint8)snes.input.port_read(1);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +78,7 @@ void sCPU::mmio_w4200(uint8 data) {
|
|||||||
//WRIO
|
//WRIO
|
||||||
void sCPU::mmio_w4201(uint8 data) {
|
void sCPU::mmio_w4201(uint8 data) {
|
||||||
if((status.pio & 0x80) && !(data & 0x80)) {
|
if((status.pio & 0x80) && !(data & 0x80)) {
|
||||||
r_ppu->latch_counters();
|
ppu.latch_counters();
|
||||||
}
|
}
|
||||||
status.pio = data;
|
status.pio = data;
|
||||||
}
|
}
|
||||||
@@ -159,7 +161,7 @@ void sCPU::mmio_w420c(uint8 data) {
|
|||||||
|
|
||||||
//MEMSEL
|
//MEMSEL
|
||||||
void sCPU::mmio_w420d(uint8 data) {
|
void sCPU::mmio_w420d(uint8 data) {
|
||||||
r_mem->set_speed(data & 1);
|
bus.set_speed(data & 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//RDNMI
|
//RDNMI
|
||||||
@@ -167,7 +169,7 @@ void sCPU::mmio_w420d(uint8 data) {
|
|||||||
//6-4 = MDR
|
//6-4 = MDR
|
||||||
//3-0 = CPU (5a22) version
|
//3-0 = CPU (5a22) version
|
||||||
uint8 sCPU::mmio_r4210() {
|
uint8 sCPU::mmio_r4210() {
|
||||||
uint8 r = (regs.mdr & 0x70);
|
uint8 r = (regs.mdr & 0x70);
|
||||||
r |= (uint8)(rdnmi()) << 7;
|
r |= (uint8)(rdnmi()) << 7;
|
||||||
r |= (cpu_version & 0x0f);
|
r |= (cpu_version & 0x0f);
|
||||||
return r;
|
return r;
|
||||||
@@ -177,7 +179,7 @@ uint8 r = (regs.mdr & 0x70);
|
|||||||
//7 = IRQ acknowledge
|
//7 = IRQ acknowledge
|
||||||
//6-0 = MDR
|
//6-0 = MDR
|
||||||
uint8 sCPU::mmio_r4211() {
|
uint8 sCPU::mmio_r4211() {
|
||||||
uint8 r = (regs.mdr & 0x7f);
|
uint8 r = (regs.mdr & 0x7f);
|
||||||
r |= (uint8)(timeup()) << 7;
|
r |= (uint8)(timeup()) << 7;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -188,16 +190,16 @@ uint8 r = (regs.mdr & 0x7f);
|
|||||||
//5-1 = MDR
|
//5-1 = MDR
|
||||||
//0 = JOYPAD acknowledge
|
//0 = JOYPAD acknowledge
|
||||||
uint8 sCPU::mmio_r4212() {
|
uint8 sCPU::mmio_r4212() {
|
||||||
uint8 r = (regs.mdr & 0x3e);
|
uint8 r = (regs.mdr & 0x3e);
|
||||||
uint16 vs = !overscan() ? 225 : 240;
|
uint16 vs = ppu.overscan() == false ? 225 : 240;
|
||||||
|
|
||||||
//auto joypad polling
|
//auto joypad polling
|
||||||
if(status.vcounter >= vs && status.vcounter <= (vs + 2))r |= 0x01;
|
if(status.vcounter >= vs && status.vcounter <= (vs + 2))r |= 0x01;
|
||||||
|
|
||||||
//hblank
|
//hblank
|
||||||
if(status.hclock <= 2 || status.hclock >= 1096)r |= 0x40;
|
if(status.hcounter <= 2 || status.hcounter >= 1096)r |= 0x40;
|
||||||
|
|
||||||
//vblank
|
//vblank
|
||||||
if(status.vcounter >= vs)r |= 0x80;
|
if(status.vcounter >= vs)r |= 0x80;
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
@@ -375,40 +377,40 @@ void sCPU::mmio_power() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sCPU::mmio_reset() {
|
void sCPU::mmio_reset() {
|
||||||
//$2181-$2183
|
//$2181-$2183
|
||||||
status.wram_addr = 0x000000;
|
status.wram_addr = 0x000000;
|
||||||
|
|
||||||
//$4016-$4017
|
//$4016-$4017
|
||||||
status.joypad_strobe_latch = 0;
|
status.joypad_strobe_latch = 0;
|
||||||
status.joypad1_bits = ~0;
|
status.joypad1_bits = ~0;
|
||||||
status.joypad2_bits = ~0;
|
status.joypad2_bits = ~0;
|
||||||
|
|
||||||
//$4200
|
//$4200
|
||||||
status.nmi_enabled = false;
|
status.nmi_enabled = false;
|
||||||
status.hirq_enabled = false;
|
status.hirq_enabled = false;
|
||||||
status.virq_enabled = false;
|
status.virq_enabled = false;
|
||||||
status.auto_joypad_poll = false;
|
status.auto_joypad_poll = false;
|
||||||
|
|
||||||
//$4201
|
//$4201
|
||||||
status.pio = 0xff;
|
status.pio = 0xff;
|
||||||
|
|
||||||
//$4202-$4203
|
//$4202-$4203
|
||||||
status.mul_a = 0xff;
|
status.mul_a = 0xff;
|
||||||
status.mul_b = 0xff;
|
status.mul_b = 0xff;
|
||||||
|
|
||||||
//$4204-$4206
|
//$4204-$4206
|
||||||
status.div_a = 0xffff;
|
status.div_a = 0xffff;
|
||||||
status.div_b = 0xff;
|
status.div_b = 0xff;
|
||||||
|
|
||||||
//$4207-$420a
|
//$4207-$420a
|
||||||
status.hirq_pos = 0x01ff;
|
status.hirq_pos = 0x01ff;
|
||||||
status.virq_pos = 0x01ff;
|
status.virq_pos = 0x01ff;
|
||||||
|
|
||||||
//$4214-$4217
|
//$4214-$4217
|
||||||
status.r4214 = 0x0000;
|
status.r4214 = 0x0000;
|
||||||
status.r4216 = 0x0000;
|
status.r4216 = 0x0000;
|
||||||
|
|
||||||
//$4218-$421f
|
//$4218-$421f
|
||||||
status.joy1l = 0x00;
|
status.joy1l = 0x00;
|
||||||
status.joy1h = 0x00;
|
status.joy1h = 0x00;
|
||||||
status.joy2l = 0x00;
|
status.joy2l = 0x00;
|
||||||
@@ -419,14 +421,16 @@ void sCPU::mmio_reset() {
|
|||||||
status.joy4h = 0x00;
|
status.joy4h = 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 sCPU::mmio_read(uint16 addr) {
|
uint8 sCPU::mmio_read(uint addr) {
|
||||||
//APU
|
addr &= 0xffff;
|
||||||
|
|
||||||
|
//APU
|
||||||
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
|
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
|
||||||
scheduler.sync_cpusmp();
|
scheduler.sync_cpusmp();
|
||||||
return r_smp->port_read(addr & 3);
|
return smp.port_read(addr & 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
//DMA
|
//DMA
|
||||||
if((addr & 0xff80) == 0x4300) { //$4300-$437f
|
if((addr & 0xff80) == 0x4300) { //$4300-$437f
|
||||||
uint i = (addr >> 4) & 7;
|
uint i = (addr >> 4) & 7;
|
||||||
switch(addr & 0xf) {
|
switch(addr & 0xf) {
|
||||||
@@ -474,15 +478,17 @@ uint8 sCPU::mmio_read(uint16 addr) {
|
|||||||
return regs.mdr;
|
return regs.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sCPU::mmio_write(uint16 addr, uint8 data) {
|
void sCPU::mmio_write(uint addr, uint8 data) {
|
||||||
//APU
|
addr &= 0xffff;
|
||||||
|
|
||||||
|
//APU
|
||||||
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
|
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
|
||||||
scheduler.sync_cpusmp();
|
scheduler.sync_cpusmp();
|
||||||
port_write(addr & 3, data);
|
port_write(addr & 3, data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//DMA
|
//DMA
|
||||||
if((addr & 0xff80) == 0x4300) { //$4300-$437f
|
if((addr & 0xff80) == 0x4300) { //$4300-$437f
|
||||||
uint i = (addr >> 4) & 7;
|
uint i = (addr >> 4) & 7;
|
||||||
switch(addr & 0xf) {
|
switch(addr & 0xf) {
|
||||||
@@ -528,3 +534,5 @@ void sCPU::mmio_write(uint16 addr, uint8 data) {
|
|||||||
case 0x420d: mmio_w420d(data); return;
|
case 0x420d: mmio_w420d(data); return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif //ifdef SCPU_CPP
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
void mmio_power();
|
void mmio_power();
|
||||||
void mmio_reset();
|
void mmio_reset();
|
||||||
uint8 mmio_read (uint16 addr);
|
uint8 mmio_read(uint addr);
|
||||||
void mmio_write(uint16 addr, uint8 data);
|
void mmio_write(uint addr, uint8 data);
|
||||||
|
|
||||||
uint8 pio_status();
|
uint8 pio_status();
|
||||||
|
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
#include "../../base.h"
|
#include "../../base.h"
|
||||||
|
#define SCPU_CPP
|
||||||
|
|
||||||
#include "core/core.cpp"
|
#include "core/core.cpp"
|
||||||
#include "dma/dma.cpp"
|
#include "dma/dma.cpp"
|
||||||
@@ -7,8 +8,6 @@
|
|||||||
#include "timing/timing.cpp"
|
#include "timing/timing.cpp"
|
||||||
|
|
||||||
void sCPU::power() {
|
void sCPU::power() {
|
||||||
status.region = (bool)snes.region();
|
|
||||||
|
|
||||||
regs.a = regs.x = regs.y = 0x0000;
|
regs.a = regs.x = regs.y = 0x0000;
|
||||||
regs.s = 0x01ff;
|
regs.s = 0x01ff;
|
||||||
|
|
||||||
@@ -21,10 +20,10 @@ void sCPU::power() {
|
|||||||
|
|
||||||
void sCPU::reset() {
|
void sCPU::reset() {
|
||||||
regs.pc.d = 0x000000;
|
regs.pc.d = 0x000000;
|
||||||
regs.pc.l = r_mem->read(0xfffc);
|
regs.pc.l = bus.read(0xfffc);
|
||||||
regs.pc.h = r_mem->read(0xfffd);
|
regs.pc.h = bus.read(0xfffd);
|
||||||
|
|
||||||
//note: some registers are not fully reset by SNES
|
//note: some registers are not fully reset by SNES
|
||||||
regs.x.h = 0x00;
|
regs.x.h = 0x00;
|
||||||
regs.y.h = 0x00;
|
regs.y.h = 0x00;
|
||||||
regs.s.h = 0x01;
|
regs.s.h = 0x01;
|
||||||
|
@@ -2,20 +2,19 @@ class sCPU : public CPU {
|
|||||||
public:
|
public:
|
||||||
void enter();
|
void enter();
|
||||||
|
|
||||||
public:
|
#include "core/core.h"
|
||||||
#include "core/core.h"
|
#include "dma/dma.h"
|
||||||
#include "dma/dma.h"
|
#include "memory/memory.h"
|
||||||
#include "memory/memory.h"
|
#include "mmio/mmio.h"
|
||||||
#include "mmio/mmio.h"
|
#include "timing/timing.h"
|
||||||
#include "timing/timing.h"
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool wai;
|
bool wai;
|
||||||
bool irq;
|
bool irq;
|
||||||
uint16 irq_vector;
|
uint16 irq_vector;
|
||||||
} event;
|
} event;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint nmi_hold;
|
uint nmi_hold;
|
||||||
uint irq_hold;
|
uint irq_hold;
|
||||||
|
|
||||||
@@ -35,31 +34,25 @@ struct {
|
|||||||
ctr = 0;
|
ctr = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} counter;
|
} counter;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
DMASTATE_INACTIVE,
|
DMASTATE_INACTIVE,
|
||||||
DMASTATE_DMASYNC,
|
DMASTATE_DMASYNC,
|
||||||
DMASTATE_RUN,
|
DMASTATE_RUN,
|
||||||
DMASTATE_CPUSYNC,
|
DMASTATE_CPUSYNC,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
//core
|
//core
|
||||||
uint8 opcode;
|
uint8 opcode;
|
||||||
bool in_opcode;
|
bool in_opcode;
|
||||||
|
|
||||||
uint clock_count;
|
uint clock_count;
|
||||||
|
|
||||||
//timing
|
//timing
|
||||||
bool region;
|
uint16 vcounter, hcounter;
|
||||||
uint16 region_scanlines;
|
|
||||||
uint16 vcounter, hcounter, hclock;
|
|
||||||
bool interlace, interlace_field;
|
|
||||||
bool overscan;
|
|
||||||
uint16 field_lines, line_clocks;
|
uint16 field_lines, line_clocks;
|
||||||
uint16 prev_field_lines, prev_line_clocks;
|
|
||||||
uint16 vblstart;
|
|
||||||
|
|
||||||
bool line_rendered;
|
bool line_rendered;
|
||||||
uint16 line_render_position;
|
uint16 line_render_position;
|
||||||
@@ -74,7 +67,6 @@ struct {
|
|||||||
|
|
||||||
uint16 irq_delay;
|
uint16 irq_delay;
|
||||||
|
|
||||||
uint16 vnmi_trigger_pos;
|
|
||||||
bool nmi_valid;
|
bool nmi_valid;
|
||||||
bool nmi_line;
|
bool nmi_line;
|
||||||
bool nmi_transition;
|
bool nmi_transition;
|
||||||
@@ -86,7 +78,7 @@ struct {
|
|||||||
bool irq_transition;
|
bool irq_transition;
|
||||||
bool irq_pending;
|
bool irq_pending;
|
||||||
|
|
||||||
//dma
|
//dma
|
||||||
uint dma_counter;
|
uint dma_counter;
|
||||||
uint dma_clocks;
|
uint dma_clocks;
|
||||||
uint dma_state;
|
uint dma_state;
|
||||||
@@ -94,44 +86,44 @@ struct {
|
|||||||
bool hdma_pending;
|
bool hdma_pending;
|
||||||
bool hdmainit_pending;
|
bool hdmainit_pending;
|
||||||
|
|
||||||
//mmio
|
//mmio
|
||||||
|
|
||||||
//$2181-$2183
|
//$2181-$2183
|
||||||
uint32 wram_addr;
|
uint32 wram_addr;
|
||||||
|
|
||||||
//$4016-$4017
|
//$4016-$4017
|
||||||
bool joypad_strobe_latch;
|
bool joypad_strobe_latch;
|
||||||
uint32 joypad1_bits;
|
uint32 joypad1_bits;
|
||||||
uint32 joypad2_bits;
|
uint32 joypad2_bits;
|
||||||
|
|
||||||
//$4200
|
//$4200
|
||||||
bool nmi_enabled;
|
bool nmi_enabled;
|
||||||
bool hirq_enabled, virq_enabled;
|
bool hirq_enabled, virq_enabled;
|
||||||
bool auto_joypad_poll;
|
bool auto_joypad_poll;
|
||||||
|
|
||||||
//$4201
|
//$4201
|
||||||
uint8 pio;
|
uint8 pio;
|
||||||
|
|
||||||
//$4202-$4203
|
//$4202-$4203
|
||||||
uint8 mul_a, mul_b;
|
uint8 mul_a, mul_b;
|
||||||
|
|
||||||
//$4204-$4206
|
//$4204-$4206
|
||||||
uint16 div_a;
|
uint16 div_a;
|
||||||
uint8 div_b;
|
uint8 div_b;
|
||||||
|
|
||||||
//$4207-$420a
|
//$4207-$420a
|
||||||
uint16 hirq_pos, virq_pos;
|
uint16 hirq_pos, virq_pos;
|
||||||
|
|
||||||
//$4214-$4217
|
//$4214-$4217
|
||||||
uint16 r4214;
|
uint16 r4214;
|
||||||
uint16 r4216;
|
uint16 r4216;
|
||||||
|
|
||||||
//$4218-$421f
|
//$4218-$421f
|
||||||
uint8 joy1l, joy1h;
|
uint8 joy1l, joy1h;
|
||||||
uint8 joy2l, joy2h;
|
uint8 joy2l, joy2h;
|
||||||
uint8 joy3l, joy3h;
|
uint8 joy3l, joy3h;
|
||||||
uint8 joy4l, joy4h;
|
uint8 joy4l, joy4h;
|
||||||
} status;
|
} status;
|
||||||
|
|
||||||
void power();
|
void power();
|
||||||
void reset();
|
void reset();
|
||||||
|
@@ -1,60 +1,137 @@
|
|||||||
#include "irqtiming.cpp"
|
#ifdef SCPU_CPP
|
||||||
|
|
||||||
|
void sCPU::update_interrupts() {
|
||||||
|
if(irq_pos_valid() == true) {
|
||||||
|
status.virq_trigger_pos = status.virq_pos;
|
||||||
|
status.hirq_trigger_pos = 4 * ((status.hirq_enabled) ? (status.hirq_pos + 1) : 0);
|
||||||
|
} else {
|
||||||
|
status.virq_trigger_pos = IRQ_TRIGGER_NEVER;
|
||||||
|
status.hirq_trigger_pos = IRQ_TRIGGER_NEVER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
alwaysinline void sCPU::poll_interrupts() {
|
||||||
|
uint16_t vpos, hpos;
|
||||||
|
|
||||||
|
//NMI hold
|
||||||
|
if(counter.nmi_hold) {
|
||||||
|
counter.nmi_hold -= 2;
|
||||||
|
if(counter.nmi_hold == 0) {
|
||||||
|
if(status.nmi_enabled == true) status.nmi_transition = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//NMI test
|
||||||
|
history.query(2, vpos, hpos);
|
||||||
|
bool nmi_valid = (vpos >= (!ppu.overscan() ? 225 : 240));
|
||||||
|
if(status.nmi_valid == false && nmi_valid == true) {
|
||||||
|
//0->1 edge sensitive transition
|
||||||
|
status.nmi_line = true;
|
||||||
|
counter.nmi_hold = 4;
|
||||||
|
} else if(status.nmi_valid == true && nmi_valid == false) {
|
||||||
|
//1->0 edge sensitive transition
|
||||||
|
status.nmi_line = false;
|
||||||
|
}
|
||||||
|
status.nmi_valid = nmi_valid;
|
||||||
|
|
||||||
|
//IRQ hold
|
||||||
|
if(counter.irq_hold) counter.irq_hold -= 2;
|
||||||
|
if(status.irq_line == true && counter.irq_hold == 0) {
|
||||||
|
if(status.virq_enabled == true || status.hirq_enabled == true) status.irq_transition = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//IRQ test
|
||||||
|
history.query(10, vpos, hpos);
|
||||||
|
bool irq_valid = (status.virq_enabled == true || status.hirq_enabled == true);
|
||||||
|
if(irq_valid == true) {
|
||||||
|
if(status.virq_enabled == true && vpos != status.virq_trigger_pos) irq_valid = false;
|
||||||
|
if(status.hirq_enabled == true && hpos != status.hirq_trigger_pos) irq_valid = false;
|
||||||
|
}
|
||||||
|
if(status.irq_valid == false && irq_valid == true) {
|
||||||
|
//0->1 edge sensitive transition
|
||||||
|
status.irq_line = true;
|
||||||
|
counter.irq_hold = 4;
|
||||||
|
}
|
||||||
|
status.irq_valid = irq_valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sCPU::nmitimen_update(uint8 data) {
|
||||||
|
bool nmi_enabled = status.nmi_enabled;
|
||||||
|
bool virq_enabled = status.virq_enabled;
|
||||||
|
bool hirq_enabled = status.hirq_enabled;
|
||||||
|
status.nmi_enabled = !!(data & 0x80);
|
||||||
|
status.virq_enabled = !!(data & 0x20);
|
||||||
|
status.hirq_enabled = !!(data & 0x10);
|
||||||
|
|
||||||
|
//0->1 edge sensitive transition
|
||||||
|
if(nmi_enabled == false && status.nmi_enabled == true && status.nmi_line == true) {
|
||||||
|
status.nmi_transition = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//?->1 level sensitive transition
|
||||||
|
if(status.virq_enabled == true && status.hirq_enabled == false && status.irq_line == true) {
|
||||||
|
status.irq_transition = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(status.virq_enabled == false && status.hirq_enabled == false) {
|
||||||
|
status.irq_line = false;
|
||||||
|
status.irq_transition = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
update_interrupts();
|
||||||
|
counter.set(counter.irq_delay, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sCPU::hvtime_update(uint16 addr) {
|
||||||
|
update_interrupts();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sCPU::rdnmi() {
|
||||||
|
bool result = status.nmi_line;
|
||||||
|
if(counter.nmi_hold == 0) {
|
||||||
|
status.nmi_line = false;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sCPU::timeup() {
|
||||||
|
bool result = status.irq_line;
|
||||||
|
if(counter.irq_hold == 0) {
|
||||||
|
status.irq_line = false;
|
||||||
|
status.irq_transition = false;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool sCPU::irq_pos_valid() {
|
bool sCPU::irq_pos_valid() {
|
||||||
uint vpos = status.virq_pos;
|
uint vpos = status.virq_pos;
|
||||||
uint hpos = (status.hirq_enabled) ? status.hirq_pos : 0;
|
uint hpos = (status.hirq_enabled) ? status.hirq_pos : 0;
|
||||||
uint vlimit = region_scanlines() >> 1;
|
uint vlimit = (snes.region() == SNES::NTSC ? 525 : 625) >> 1;
|
||||||
//positions that can never be latched
|
//positions that can never be latched
|
||||||
//vlimit = 262/NTSC, 312/PAL
|
//vlimit = 262/NTSC, 312/PAL
|
||||||
//PAL results are unverified on hardware
|
//PAL results are unverified on hardware
|
||||||
if(vpos == 240 && hpos == 339 && interlace() == false && interlace_field() == 1)return false;
|
if(vpos == 240 && hpos == 339 && ppu.interlace() == false && ppu.field() == 1) return false;
|
||||||
if(vpos == (vlimit - 1) && hpos == 339 && interlace() == false)return false;
|
if(vpos == (vlimit - 1) && hpos == 339 && ppu.interlace() == false) return false;
|
||||||
if(vpos == vlimit && interlace() == false)return false;
|
if(vpos == vlimit && ppu.interlace() == false) return false;
|
||||||
if(vpos == vlimit && hpos == 339)return false;
|
if(vpos == vlimit && hpos == 339) return false;
|
||||||
if(vpos > vlimit)return false;
|
if(vpos > vlimit) return false;
|
||||||
if(hpos > 339)return false;
|
if(hpos > 339) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
alwaysinline
|
alwaysinline bool sCPU::nmi_test() {
|
||||||
bool sCPU::nmi_test() {
|
if(status.nmi_transition == false) return false;
|
||||||
if(status.nmi_transition == false) { return false; }
|
|
||||||
status.nmi_transition = false;
|
status.nmi_transition = false;
|
||||||
|
|
||||||
event.wai = false;
|
event.wai = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
alwaysinline
|
alwaysinline bool sCPU::irq_test() {
|
||||||
bool sCPU::irq_test() {
|
if(status.irq_transition == false) return false;
|
||||||
if(status.irq_transition == false) { return false; }
|
|
||||||
status.irq_transition = false;
|
status.irq_transition = false;
|
||||||
|
|
||||||
event.wai = false;
|
event.wai = false;
|
||||||
return (regs.p.i) ? false : true;
|
return regs.p.i ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
#endif //ifdef SCPU_CPP
|
||||||
if(status.irq_transition == 1)goto irq_trigger;
|
|
||||||
|
|
||||||
if(status.irq_read == 0) {
|
|
||||||
if(status.irq_line == 1 && irq_edge()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
goto irq_trigger;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(status.irq_line == 0) {
|
|
||||||
status.irq_line = 1;
|
|
||||||
goto irq_trigger;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
|
|
||||||
irq_trigger:
|
|
||||||
status.irq_transition = 0;
|
|
||||||
event.wai = false;
|
|
||||||
return (regs.p.i) ? false : true;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
@@ -1,105 +0,0 @@
|
|||||||
void sCPU::update_interrupts() {
|
|
||||||
status.vnmi_trigger_pos = status.vblstart;
|
|
||||||
|
|
||||||
if(irq_pos_valid() == true) {
|
|
||||||
status.virq_trigger_pos = status.virq_pos;
|
|
||||||
status.hirq_trigger_pos = 4 * ((status.hirq_enabled) ? (status.hirq_pos + 1) : 0);
|
|
||||||
} else {
|
|
||||||
status.virq_trigger_pos = IRQ_TRIGGER_NEVER;
|
|
||||||
status.hirq_trigger_pos = IRQ_TRIGGER_NEVER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
alwaysinline
|
|
||||||
void sCPU::poll_interrupts() {
|
|
||||||
uint vpos = status.vcounter, hpos = status.hclock;
|
|
||||||
|
|
||||||
//NMI test
|
|
||||||
timeshift_backward(2, vpos, hpos);
|
|
||||||
bool nmi_valid = (vpos >= status.vnmi_trigger_pos);
|
|
||||||
if(status.nmi_valid == false && nmi_valid == true) {
|
|
||||||
//0->1 edge sensitive transition
|
|
||||||
status.nmi_line = true;
|
|
||||||
counter.nmi_hold = 6;
|
|
||||||
} else if(status.nmi_valid == true && nmi_valid == false) {
|
|
||||||
//1->0 edge sensitive transition
|
|
||||||
status.nmi_line = false;
|
|
||||||
}
|
|
||||||
status.nmi_valid = nmi_valid;
|
|
||||||
|
|
||||||
//NMI hold
|
|
||||||
if(counter.nmi_hold) {
|
|
||||||
counter.nmi_hold -= 2;
|
|
||||||
if(counter.nmi_hold == 0) {
|
|
||||||
if(status.nmi_enabled == true) { status.nmi_transition = true; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//IRQ test
|
|
||||||
timeshift_backward(8, vpos, hpos);
|
|
||||||
bool irq_valid = (status.virq_enabled == true || status.hirq_enabled == true);
|
|
||||||
if(irq_valid == true) {
|
|
||||||
if(status.virq_enabled == true && vpos != status.virq_trigger_pos) { irq_valid = false; }
|
|
||||||
if(status.hirq_enabled == true && hpos != status.hirq_trigger_pos) { irq_valid = false; }
|
|
||||||
}
|
|
||||||
if(status.irq_valid == false && irq_valid == true) {
|
|
||||||
//0->1 edge sensitive transition
|
|
||||||
status.irq_line = true;
|
|
||||||
counter.irq_hold = 6;
|
|
||||||
}
|
|
||||||
status.irq_valid = irq_valid;
|
|
||||||
|
|
||||||
//IRQ hold
|
|
||||||
if(counter.irq_hold) { counter.irq_hold -= 2; }
|
|
||||||
if(status.irq_line == true && counter.irq_hold == 0) {
|
|
||||||
if(status.virq_enabled == true || status.hirq_enabled == true) { status.irq_transition = true; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sCPU::nmitimen_update(uint8 data) {
|
|
||||||
bool nmi_enabled = status.nmi_enabled;
|
|
||||||
bool virq_enabled = status.virq_enabled;
|
|
||||||
bool hirq_enabled = status.hirq_enabled;
|
|
||||||
status.nmi_enabled = !!(data & 0x80);
|
|
||||||
status.virq_enabled = !!(data & 0x20);
|
|
||||||
status.hirq_enabled = !!(data & 0x10);
|
|
||||||
|
|
||||||
//0->1 edge sensitive transition
|
|
||||||
if(nmi_enabled == false && status.nmi_enabled == true && status.nmi_line == true) {
|
|
||||||
status.nmi_transition = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//?->1 level sensitive transition
|
|
||||||
if(status.virq_enabled == true && status.hirq_enabled == false && status.irq_line == true) {
|
|
||||||
status.irq_transition = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(status.virq_enabled == false && status.hirq_enabled == false) {
|
|
||||||
status.irq_line = false;
|
|
||||||
status.irq_transition = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
update_interrupts();
|
|
||||||
counter.set(counter.irq_delay, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sCPU::hvtime_update(uint16 addr) {
|
|
||||||
update_interrupts();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sCPU::rdnmi() {
|
|
||||||
bool result = status.nmi_line;
|
|
||||||
if(counter.nmi_hold == 0) {
|
|
||||||
status.nmi_line = false;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sCPU::timeup() {
|
|
||||||
bool result = status.irq_line;
|
|
||||||
if(counter.irq_hold == 0) {
|
|
||||||
status.irq_line = false;
|
|
||||||
status.irq_transition = false;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
@@ -1,8 +1,10 @@
|
|||||||
|
#ifdef SCPU_CPP
|
||||||
|
|
||||||
void sCPU::run_auto_joypad_poll() {
|
void sCPU::run_auto_joypad_poll() {
|
||||||
uint16 joy1 = 0, joy2 = 0;
|
uint16_t joy1 = 0, joy2 = 0;
|
||||||
for(int i = 0; i < 16; i++) {
|
for(unsigned i = 0; i < 16; i++) {
|
||||||
joy1 |= (uint16)snes.port_read(0) ? (0x8000 >> i) : 0;
|
joy1 |= (uint16_t)snes.input.port_read(0) ? (0x8000 >> i) : 0;
|
||||||
joy2 |= (uint16)snes.port_read(1) ? (0x8000 >> i) : 0;
|
joy2 |= (uint16_t)snes.input.port_read(1) ? (0x8000 >> i) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
status.joy1l = joy1;
|
status.joy1l = joy1;
|
||||||
@@ -17,3 +19,5 @@ uint16 joy1 = 0, joy2 = 0;
|
|||||||
status.joy4l = 0x00;
|
status.joy4l = 0x00;
|
||||||
status.joy4h = 0x00;
|
status.joy4h = 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif //ifdef SCPU_CPP
|
||||||
|
@@ -1,22 +0,0 @@
|
|||||||
alwaysinline void sCPU::timeshift_forward(uint clocks, uint &vtime, uint &htime) {
|
|
||||||
htime += clocks;
|
|
||||||
if(htime >= status.line_clocks) {
|
|
||||||
htime -= status.line_clocks;
|
|
||||||
if(++vtime >= status.field_lines) {
|
|
||||||
vtime = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
alwaysinline void sCPU::timeshift_backward(uint clocks, uint &vtime, uint &htime) {
|
|
||||||
if(htime >= clocks) {
|
|
||||||
htime -= clocks;
|
|
||||||
} else {
|
|
||||||
htime += status.prev_line_clocks - clocks;
|
|
||||||
if(vtime > 0) {
|
|
||||||
vtime--;
|
|
||||||
} else {
|
|
||||||
vtime = status.prev_field_lines - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,31 +1,16 @@
|
|||||||
#define ntsc_color_burst_phase_shift_scanline() \
|
#ifdef SCPU_CPP
|
||||||
(status.region == SNES::NTSC && status.vcounter == 240 && \
|
|
||||||
status.interlace == false && status.interlace_field == 1)
|
#define ntsc_color_burst_phase_shift_scanline() ( \
|
||||||
|
snes.region() == SNES::NTSC && status.vcounter == 240 && \
|
||||||
|
ppu.interlace() == false && ppu.field() == 1 \
|
||||||
|
)
|
||||||
|
|
||||||
#include "timeshift.cpp"
|
|
||||||
#include "irq.cpp"
|
#include "irq.cpp"
|
||||||
#include "joypad.cpp"
|
#include "joypad.cpp"
|
||||||
|
|
||||||
uint16 sCPU::vcounter() { return status.vcounter; }
|
uint16 sCPU::vcounter() { return status.vcounter; }
|
||||||
uint16 sCPU::hclock() { return status.hclock; }
|
uint16 sCPU::hcounter() { return status.hcounter; }
|
||||||
|
uint sCPU::dma_counter() { return (status.dma_counter + status.hcounter) & 7; }
|
||||||
bool sCPU::interlace() { return status.interlace; }
|
|
||||||
bool sCPU::interlace_field() { return status.interlace_field; }
|
|
||||||
bool sCPU::overscan() { return status.overscan; }
|
|
||||||
uint16 sCPU::region_scanlines() { return status.region_scanlines; }
|
|
||||||
|
|
||||||
uint sCPU::dma_counter() { return (status.dma_counter + status.hclock) & 7; }
|
|
||||||
|
|
||||||
void sCPU::set_interlace(bool r) {
|
|
||||||
status.interlace = r;
|
|
||||||
update_interrupts();
|
|
||||||
}
|
|
||||||
|
|
||||||
void sCPU::set_overscan (bool r) {
|
|
||||||
status.overscan = r;
|
|
||||||
status.vblstart = (status.overscan == false) ? 225 : 240;
|
|
||||||
update_interrupts();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
* One PPU dot = 4 CPU clocks
|
* One PPU dot = 4 CPU clocks
|
||||||
@@ -37,16 +22,14 @@ void sCPU::set_overscan (bool r) {
|
|||||||
* Dot 323 range = { 1292, 1294, 1296 }
|
* Dot 323 range = { 1292, 1294, 1296 }
|
||||||
* Dot 327 range = { 1310, 1312, 1314 }
|
* Dot 327 range = { 1310, 1312, 1314 }
|
||||||
*****/
|
*****/
|
||||||
uint16 sCPU::hcounter() {
|
uint16 sCPU::hdot() {
|
||||||
if(ntsc_color_burst_phase_shift_scanline() == true) {
|
if(ntsc_color_burst_phase_shift_scanline() == true) return (status.hcounter >> 2);
|
||||||
return (status.hclock >> 2);
|
return (status.hcounter - ((status.hcounter > 1292) << 1) - ((status.hcounter > 1310) << 1)) >> 2;
|
||||||
}
|
|
||||||
return (status.hclock - ((status.hclock > 1292) << 1) - ((status.hclock > 1310) << 1)) >> 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sCPU::add_clocks(uint clocks) {
|
void sCPU::add_clocks(uint clocks) {
|
||||||
if(status.dram_refreshed == false) {
|
if(status.dram_refreshed == false) {
|
||||||
if(status.hclock + clocks >= status.dram_refresh_position) {
|
if(status.hcounter + clocks >= status.dram_refresh_position) {
|
||||||
status.dram_refreshed = true;
|
status.dram_refreshed = true;
|
||||||
clocks += 40;
|
clocks += 40;
|
||||||
}
|
}
|
||||||
@@ -57,24 +40,20 @@ void sCPU::add_clocks(uint clocks) {
|
|||||||
|
|
||||||
clocks >>= 1;
|
clocks >>= 1;
|
||||||
while(clocks--) {
|
while(clocks--) {
|
||||||
status.hclock += 2;
|
history.enqueue(status.vcounter, status.hcounter);
|
||||||
if(status.hclock >= status.line_clocks) { scanline(); }
|
status.hcounter += 2;
|
||||||
|
if(status.hcounter >= status.line_clocks) scanline();
|
||||||
poll_interrupts();
|
poll_interrupts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sCPU::scanline() {
|
void sCPU::scanline() {
|
||||||
status.hclock = 0;
|
status.hcounter = 0;
|
||||||
status.dma_counter = (status.dma_counter + status.line_clocks) & 7;
|
status.dma_counter = (status.dma_counter + status.line_clocks) & 7;
|
||||||
|
if(++status.vcounter >= status.field_lines) frame();
|
||||||
if(++status.vcounter >= status.field_lines) {
|
|
||||||
frame();
|
|
||||||
}
|
|
||||||
|
|
||||||
status.prev_line_clocks = status.line_clocks;
|
|
||||||
status.line_clocks = (ntsc_color_burst_phase_shift_scanline() == false) ? 1364 : 1360;
|
status.line_clocks = (ntsc_color_burst_phase_shift_scanline() == false) ? 1364 : 1360;
|
||||||
|
|
||||||
//dram refresh occurs once every scanline
|
//dram refresh occurs once every scanline
|
||||||
status.dram_refreshed = false;
|
status.dram_refreshed = false;
|
||||||
if(cpu_version == 2) {
|
if(cpu_version == 2) {
|
||||||
if(ntsc_color_burst_phase_shift_scanline() == false) {
|
if(ntsc_color_burst_phase_shift_scanline() == false) {
|
||||||
@@ -86,29 +65,30 @@ void sCPU::scanline() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//hdma triggers once every visible scanline
|
//hdma triggers once every visible scanline
|
||||||
status.line_rendered = false;
|
status.line_rendered = false;
|
||||||
status.hdma_triggered = (status.vcounter <= (!overscan() ? 224 : 239)) ? false : true;
|
status.hdma_triggered = (status.vcounter <= (ppu.overscan() == false ? 224 : 239)) ? false : true;
|
||||||
|
|
||||||
r_ppu->scanline();
|
ppu.scanline();
|
||||||
snes.scanline();
|
snes.scanline();
|
||||||
|
|
||||||
update_interrupts();
|
update_interrupts();
|
||||||
|
|
||||||
if(status.auto_joypad_poll == true && status.vcounter == (!overscan() ? 227 : 242)) {
|
if(status.auto_joypad_poll == true && status.vcounter == (ppu.overscan() == false ? 227 : 242)) {
|
||||||
snes.poll_input();
|
snes.input.poll();
|
||||||
run_auto_joypad_poll();
|
run_auto_joypad_poll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sCPU::frame() {
|
void sCPU::frame() {
|
||||||
|
ppu.frame();
|
||||||
|
snes.frame();
|
||||||
|
|
||||||
status.vcounter = 0;
|
status.vcounter = 0;
|
||||||
status.interlace_field ^= 1;
|
status.field_lines = (snes.region() == SNES::NTSC ? 525 : 625) >> 1;
|
||||||
status.prev_field_lines = status.field_lines;
|
//interlaced even fields have one extra scanline
|
||||||
status.field_lines = (status.region_scanlines >> 1);
|
//(263+262=525 NTSC, 313+312=625 PAL)
|
||||||
//interlaced even fields have one extra scanline
|
if(ppu.interlace() == true && ppu.field() == 0) status.field_lines++;
|
||||||
//(263+262=525 NTSC, 313+312=625 PAL)
|
|
||||||
if(status.interlace == true && status.interlace_field == 0)status.field_lines++;
|
|
||||||
|
|
||||||
status.hdmainit_triggered = false;
|
status.hdmainit_triggered = false;
|
||||||
if(cpu_version == 1) {
|
if(cpu_version == 1) {
|
||||||
@@ -116,9 +96,6 @@ void sCPU::frame() {
|
|||||||
} else {
|
} else {
|
||||||
status.hdmainit_trigger_position = 12 + dma_counter();
|
status.hdmainit_trigger_position = 12 + dma_counter();
|
||||||
}
|
}
|
||||||
|
|
||||||
r_ppu->frame();
|
|
||||||
snes.frame();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
@@ -141,21 +118,20 @@ alwaysinline void sCPU::precycle_edge() {
|
|||||||
*****/
|
*****/
|
||||||
void sCPU::cycle_edge() {
|
void sCPU::cycle_edge() {
|
||||||
if(status.line_rendered == false) {
|
if(status.line_rendered == false) {
|
||||||
if(status.hclock >= status.line_render_position) {
|
if(status.hcounter >= status.line_render_position) {
|
||||||
status.line_rendered = true;
|
status.line_rendered = true;
|
||||||
r_ppu->render_scanline();
|
ppu.render_scanline();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(status.dma_state) {
|
switch(status.dma_state) {
|
||||||
case DMASTATE_INACTIVE:
|
case DMASTATE_INACTIVE: break;
|
||||||
break;
|
|
||||||
|
|
||||||
case DMASTATE_DMASYNC:
|
case DMASTATE_DMASYNC: {
|
||||||
status.dma_state = DMASTATE_RUN;
|
status.dma_state = DMASTATE_RUN;
|
||||||
break;
|
} break;
|
||||||
|
|
||||||
case DMASTATE_RUN:
|
case DMASTATE_RUN: {
|
||||||
status.dma_state = DMASTATE_CPUSYNC;
|
status.dma_state = DMASTATE_CPUSYNC;
|
||||||
status.dma_clocks = 8 - dma_counter() + 8;
|
status.dma_clocks = 8 - dma_counter() + 8;
|
||||||
add_clocks(status.dma_clocks);
|
add_clocks(status.dma_clocks);
|
||||||
@@ -164,11 +140,11 @@ void sCPU::cycle_edge() {
|
|||||||
if(status.hdma_pending) { hdma_run(); status.hdma_pending = false; }
|
if(status.hdma_pending) { hdma_run(); status.hdma_pending = false; }
|
||||||
if(status.dma_pending) { dma_run(); status.dma_pending = false; }
|
if(status.dma_pending) { dma_run(); status.dma_pending = false; }
|
||||||
|
|
||||||
break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(status.hdmainit_triggered == false) {
|
if(status.hdmainit_triggered == false) {
|
||||||
if(status.hclock >= status.hdmainit_trigger_position || status.vcounter) {
|
if(status.hcounter >= status.hdmainit_trigger_position || status.vcounter) {
|
||||||
status.hdmainit_triggered = true;
|
status.hdmainit_triggered = true;
|
||||||
hdma_init_reset();
|
hdma_init_reset();
|
||||||
if(hdma_enabled_channels()) {
|
if(hdma_enabled_channels()) {
|
||||||
@@ -185,7 +161,7 @@ void sCPU::cycle_edge() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(status.hdma_triggered == false) {
|
if(status.hdma_triggered == false) {
|
||||||
if(status.hclock >= 1106) {
|
if(status.hcounter >= 1106) {
|
||||||
status.hdma_triggered = true;
|
status.hdma_triggered = true;
|
||||||
if(hdma_active_channels()) {
|
if(hdma_active_channels()) {
|
||||||
add_clocks(18);
|
add_clocks(18);
|
||||||
@@ -211,7 +187,7 @@ void sCPU::cycle_edge() {
|
|||||||
* trigger during certain events (immediately after DMA, writes to $4200, etc)
|
* trigger during certain events (immediately after DMA, writes to $4200, etc)
|
||||||
*****/
|
*****/
|
||||||
void sCPU::last_cycle() {
|
void sCPU::last_cycle() {
|
||||||
if(counter.irq_delay) { return; }
|
if(counter.irq_delay) return;
|
||||||
|
|
||||||
status.nmi_pending |= nmi_test();
|
status.nmi_pending |= nmi_test();
|
||||||
status.irq_pending |= irq_test();
|
status.irq_pending |= irq_test();
|
||||||
@@ -235,22 +211,12 @@ void sCPU::timing_reset() {
|
|||||||
|
|
||||||
status.vcounter = 0;
|
status.vcounter = 0;
|
||||||
status.hcounter = 0;
|
status.hcounter = 0;
|
||||||
status.hclock = 0;
|
|
||||||
|
|
||||||
status.interlace = 0;
|
status.field_lines = (snes.region() == SNES::NTSC ? 525 : 625) >> 1;
|
||||||
status.interlace_field = 0;
|
|
||||||
status.overscan = false;
|
|
||||||
status.region_scanlines = (status.region == SNES::NTSC) ? 525 : 625;
|
|
||||||
status.vblstart = 225;
|
|
||||||
|
|
||||||
status.field_lines = status.region_scanlines >> 1;
|
|
||||||
status.line_clocks = 1364;
|
status.line_clocks = 1364;
|
||||||
|
|
||||||
status.prev_field_lines = status.region_scanlines >> 1;
|
|
||||||
status.prev_line_clocks = 1364;
|
|
||||||
|
|
||||||
status.line_rendered = false;
|
status.line_rendered = false;
|
||||||
status.line_render_position = min(1112, (uint16)config::ppu.hack.render_scanline_position);
|
status.line_render_position = min(1112U, (uint)config::ppu.hack.render_scanline_position);
|
||||||
|
|
||||||
status.dram_refreshed = false;
|
status.dram_refreshed = false;
|
||||||
status.dram_refresh_position = (cpu_version == 1) ? 530 : 538;
|
status.dram_refresh_position = (cpu_version == 1) ? 530 : 538;
|
||||||
@@ -280,10 +246,14 @@ void sCPU::timing_reset() {
|
|||||||
status.hdma_pending = false;
|
status.hdma_pending = false;
|
||||||
status.hdmainit_pending = false;
|
status.hdmainit_pending = false;
|
||||||
|
|
||||||
//initial latch values for $213c/$213d
|
history.reset();
|
||||||
//[x]0035 : [y]0000 (53.0 -> 212) [lda $2137]
|
|
||||||
//[x]0038 : [y]0000 (56.5 -> 226) [nop : lda $2137]
|
//initial latch values for $213c/$213d
|
||||||
//add_clocks(186);
|
//[x]0035 : [y]0000 (53.0 -> 212) [lda $2137]
|
||||||
|
//[x]0038 : [y]0000 (56.5 -> 226) [nop : lda $2137]
|
||||||
|
add_clocks(186);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef ntsc_color_burst_phase_shift_scanline
|
#undef ntsc_color_burst_phase_shift_scanline
|
||||||
|
|
||||||
|
#endif //ifdef SCPU_CPP
|
||||||
|
@@ -1,15 +1,6 @@
|
|||||||
uint16 vcounter();
|
uint16 vcounter();
|
||||||
uint16 hcounter();
|
uint16 hcounter();
|
||||||
uint16 hclock();
|
uint16 hdot();
|
||||||
|
|
||||||
bool interlace();
|
|
||||||
bool interlace_field();
|
|
||||||
bool overscan();
|
|
||||||
uint16 region_scanlines();
|
|
||||||
|
|
||||||
void set_interlace(bool r);
|
|
||||||
void set_overscan(bool r);
|
|
||||||
|
|
||||||
uint dma_counter();
|
uint dma_counter();
|
||||||
|
|
||||||
void add_clocks(uint clocks);
|
void add_clocks(uint clocks);
|
||||||
@@ -24,12 +15,33 @@
|
|||||||
void timing_power();
|
void timing_power();
|
||||||
void timing_reset();
|
void timing_reset();
|
||||||
|
|
||||||
//timeshift.cpp
|
//timeshifting -- needed by NMI and IRQ timing
|
||||||
void timeshift_forward (uint clocks, uint &v, uint &h);
|
struct History {
|
||||||
void timeshift_backward(uint clocks, uint &v, uint &h);
|
struct Time {
|
||||||
|
uint16 vcounter;
|
||||||
|
uint16 hcounter;
|
||||||
|
} time[32];
|
||||||
|
unsigned index;
|
||||||
|
alwaysinline void enqueue(uint16 vcounter, uint16 hcounter) {
|
||||||
|
Time &t = time[index++];
|
||||||
|
index &= 31;
|
||||||
|
t.vcounter = vcounter;
|
||||||
|
t.hcounter = hcounter;
|
||||||
|
}
|
||||||
|
alwaysinline void query(unsigned offset, uint16 &vcounter, uint16 &hcounter) {
|
||||||
|
Time &t = time[(index - (offset >> 1)) & 31];
|
||||||
|
vcounter = t.vcounter;
|
||||||
|
hcounter = t.hcounter;
|
||||||
|
}
|
||||||
|
void reset() {
|
||||||
|
index = 0;
|
||||||
|
for(unsigned i = 0; i < 32; i++) time[i].vcounter = time[i].hcounter = 0;
|
||||||
|
}
|
||||||
|
History() { reset(); }
|
||||||
|
} history;
|
||||||
|
|
||||||
//irq.cpp
|
//irq.cpp
|
||||||
enum { IRQ_TRIGGER_NEVER = 0x3fff };
|
enum { IRQ_TRIGGER_NEVER = 0x3fff };
|
||||||
void update_interrupts();
|
void update_interrupts();
|
||||||
void poll_interrupts();
|
void poll_interrupts();
|
||||||
void nmitimen_update(uint8 data);
|
void nmitimen_update(uint8 data);
|
||||||
@@ -41,5 +53,5 @@ enum { IRQ_TRIGGER_NEVER = 0x3fff };
|
|||||||
bool nmi_test();
|
bool nmi_test();
|
||||||
bool irq_test();
|
bool irq_test();
|
||||||
|
|
||||||
//joypad.cpp
|
//joypad.cpp
|
||||||
void run_auto_joypad_poll();
|
void run_auto_joypad_poll();
|
||||||
|
BIN
src/data/bsnes.png
Normal file
BIN
src/data/bsnes.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB |
1013
src/data/controller.h
Normal file
1013
src/data/controller.h
Normal file
File diff suppressed because it is too large
Load Diff
40
src/data/icon48.h
Normal file
40
src/data/icon48.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
static char enc_icon48[] = {
|
||||||
|
"_gAB8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB8AHw"
|
||||||
|
"AfD_AfAB8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB"
|
||||||
|
"8AHwAfD_AfAB8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHw"
|
||||||
|
"AfAB8AHwAfD_AfAB8AHwAfAB8AHwAfABgFD_oRYPBAA1BABWVQQAWwQAQQQAGgQA"
|
||||||
|
"Av8u8AHwAfAB8AHwAfAB8AHwVbSAAQQALQQAsAQA9FUEAP8EwPsEAM4EAFP9BAAE"
|
||||||
|
"QvAB8AHwAfAB8AHwqwHwvOAEBACFBAD5uPDVBOD-BAC9BAAUSvAB8L8B8AHwAfAB"
|
||||||
|
"8AHwvGADBACuoqjwBPAEwNsEABZS8H8B8AHwAfAB8AHwAfDAIHuvnPAE8ATwBCDH"
|
||||||
|
"BAAFVvC_AfAB8AHwAfAB8LzAIAQA3vaY8ATwBPAEYGZa8AHw3wHwAfAB8AHwwMCX"
|
||||||
|
"kPAE8OsE8ASg3wQABl7wAfAB8K8B8AHwAfC8QAYEAOeQ8PcE8ATw0OMvYvAB8AHw"
|
||||||
|
"AfDXAfAB8MBAHAQA_JDwBPALBPAE4GRi8AAAPz9U_wEEAA0EAB0EAB59BAAPBABE"
|
||||||
|
"9gHwAfDA8BVVBABxBAB3BAChUET9p5zwBPAE8BaGuMALBACqbAQAzgQA9AQA-wQA"
|
||||||
|
"qvwEAPYEANYEAHoEAL4SlvAB8AHwAfAEhjIEAF68FEKo8ATwBFCBcIFHtQQA5AQA"
|
||||||
|
"_wTwBKDuBAB-XDQQjvAB8AHwAfAQhmhHzPYE8ARgpQ5YwEBor2xBsPAE8AQQ_QQA"
|
||||||
|
"hFTyfwHwAfAB8MjA-Bgg8wTQowAQ-_-rACMuNrz_SrzwBPAE8MQgZ4LwbwHwAfAB"
|
||||||
|
"8BDJkbTwBMCnAAfLfV-0ETU6fP_mnPAE8ATwBCAkExxfhvAB8AHwAfDEgBEEAO0D"
|
||||||
|
"uPAEQKQO_f-tAIBCLDX_cTw-mPA3BPAE8ASAlYLwAUDNAKoBBAAFBAAUBAAiBAB-"
|
||||||
|
"JQhAEBAYEETz5PYE8KgABZxKRfIENju8_9eQ8ATwBPAEoOq0wKoDBAAsBACGBADM"
|
||||||
|
"BADq7AQA_AQA_gSAEBAYEOrKBACDBAAqBABMo6gAFkC88AQgrvgCBy83wP8VPj7_"
|
||||||
|
"-JDwBPCvBPAIs7yAuBDEoED_BPBXBPAEQDAQwAQAKcCAHRf8S7hQMBl_uFk4O_--"
|
||||||
|
"KYzwBPAE8ATwvEBhBABe95zwBPAE8ARg9gQAW1HAIJ8XFKwA8uhIkFUEAB-sxhkE"
|
||||||
|
"AH0EAJL1BADDBADznPAE8ATwwADozQBIBAD5kPAE8ATwAQTg-ADQACn_nrwYAshD"
|
||||||
|
"pPUB8NAQEQQA3nGgRqjwBPDAkOKI8ATw9wTwBPAEIM8UAwHwAfAB8HvIEPQYzKjw"
|
||||||
|
"BPAEQDQS0t-I8ATwBPAE8ARAeprwAfB3AfDEYLAZyqzwBPAEAMX1cAAvBADxiPAE"
|
||||||
|
"8ATwBOB68AQAGZbwAfAB8MSgHK0EAPGw8ASg_gQAScBDvj4URZTwBPAE8AQw6gQA"
|
||||||
|
"RjwN9mwJ__8IBAAT_QQAGgRADBAUEET2xHDgE6u48ARwuwQAA0CFGQQAup0EAPOc"
|
||||||
|
"8ATwBIDyBACgmADLABe0gAkEAKpFBACaBADSBADsBABa-QQA-wRADBDtBADTVQQA"
|
||||||
|
"nQQASAQACsDAGK0EAPW48AQg3QQAFfbwVcggEQQAUwQAoRxD6b0EAPRcJNwwEBAY"
|
||||||
|
"EJ8EAKpRBAAQuIAGBABuBAC66AQA_wTwBPAEgOoEAEpzBAAHSxBBOFgryF-88BQg"
|
||||||
|
"LHEB8NDQBgQAC10EAA0IQLj-vDAQBADFr5jwBPAE8ASgywQAFMRA6pm4gOcEAHAE"
|
||||||
|
"AOAgAfCvAfAB8AHwvEACBAC1jPAvBPAE8ATwBAC_VBBDMtT_TrAAeQQAPAQAYKLf"
|
||||||
|
"AfAB8AHwAfDAQBnYQozw1wTwBPAE8P0EAB1p8AHwrwHwAfAB8MDgGAQA-ojw7wTw"
|
||||||
|
"BPAE8AQA_AQA3PsB8N8B8AHwAfDA8CQVsYjwBPD3BPAE8AQAulz1AfAB8AHw1wHw"
|
||||||
|
"AfDEQA0EAL2M8ATw9wTwBKAEFBFh8AHwAfAB8FcB8AHwxIAFBABoBADjXQQA_pzw"
|
||||||
|
"BPAEgOUEAG3_hCUB8AHwAfAB8AHwAfAB8KvIEFwXPQQAkgQAz8BGXveYQwQQDBAU"
|
||||||
|
"ENAEAJT9BABB9CYB8AHwAfAB8AHwrwHwAfAB8NBwBAQADtgl_QQwDxRA5PIB8AHw"
|
||||||
|
"AfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB8AHwAfD_AfAB8AHwAfAB"
|
||||||
|
"8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB8AHwAfD_AfAB8AHw"
|
||||||
|
"AfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHwfwHwAfAB8AHwAfAB8AGA"
|
||||||
|
};
|
Binary file not shown.
Before Width: | Height: | Size: 20 KiB |
@@ -1,4 +1,6 @@
|
|||||||
#include "../../base.h"
|
#include "../../base.h"
|
||||||
|
#define ADSP_CPP
|
||||||
|
|
||||||
#include "adsp_tables.cpp"
|
#include "adsp_tables.cpp"
|
||||||
|
|
||||||
void aDSP::enter() { loop:
|
void aDSP::enter() { loop:
|
||||||
@@ -579,7 +581,7 @@ int32 fir_samplel, fir_sampler;
|
|||||||
}
|
}
|
||||||
|
|
||||||
snes.audio_update(msamplel, msampler);
|
snes.audio_update(msamplel, msampler);
|
||||||
scheduler.addclocks_dsp(32 * 3);
|
scheduler.addclocks_dsp(32 * 3 * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
aDSP::aDSP() {}
|
aDSP::aDSP() {}
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef ADSP_CPP
|
||||||
|
|
||||||
const uint16 aDSP::rate_table[32] = {
|
const uint16 aDSP::rate_table[32] = {
|
||||||
0x0000, 0x000F, 0x0014, 0x0018, 0x001E, 0x0028, 0x0030, 0x003C,
|
0x0000, 0x000F, 0x0014, 0x0018, 0x001E, 0x0028, 0x0030, 0x003C,
|
||||||
0x0050, 0x0060, 0x0078, 0x00A0, 0x00C0, 0x00F0, 0x0140, 0x0180,
|
0x0050, 0x0060, 0x0078, 0x00A0, 0x00C0, 0x00F0, 0x0140, 0x0180,
|
||||||
@@ -71,3 +73,5 @@ const int16 aDSP::gaussian_table[512] = {
|
|||||||
0x513, 0x514, 0x514, 0x515, 0x516, 0x516, 0x517, 0x517,
|
0x513, 0x514, 0x514, 0x515, 0x516, 0x516, 0x517, 0x517,
|
||||||
0x517, 0x518, 0x518, 0x518, 0x518, 0x518, 0x519, 0x519
|
0x517, 0x518, 0x518, 0x518, 0x518, 0x518, 0x519, 0x519
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif //ifdef ADSP_CPP
|
||||||
|
@@ -469,7 +469,7 @@ void bDSP::enter()
|
|||||||
{
|
{
|
||||||
// n is currently ignored
|
// n is currently ignored
|
||||||
#define NEXT_CLOCK( n ) \
|
#define NEXT_CLOCK( n ) \
|
||||||
scheduler.addclocks_dsp( 3 );
|
scheduler.addclocks_dsp( 3 * 8 );
|
||||||
|
|
||||||
// Execute clock for a particular voice
|
// Execute clock for a particular voice
|
||||||
#define V( clock, voice ) voice_##clock( &m.voices [voice] );
|
#define V( clock, voice ) voice_##clock( &m.voices [voice] );
|
||||||
@@ -563,7 +563,7 @@ void bDSP::enter()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Output sample to DAC
|
// Output sample to DAC
|
||||||
snes.audio_update( main_out_l, main_out_r );
|
snes.audio.update( main_out_l, main_out_r );
|
||||||
|
|
||||||
m.t_main_out [0] = 0;
|
m.t_main_out [0] = 0;
|
||||||
m.t_main_out [1] = 0;
|
m.t_main_out [1] = 0;
|
||||||
@@ -660,7 +660,7 @@ static uint8 const initial_regs [bDSP::register_count] =
|
|||||||
|
|
||||||
void bDSP::power()
|
void bDSP::power()
|
||||||
{
|
{
|
||||||
ram = (uint8*) r_smp->get_spcram_handle();
|
ram = (uint8*) smp.get_spcram_handle();
|
||||||
memset( &m, 0, sizeof m );
|
memset( &m, 0, sizeof m );
|
||||||
//memcpy( m.regs, initial_regs, sizeof m.regs );
|
//memcpy( m.regs, initial_regs, sizeof m.regs );
|
||||||
memset(m.regs, 0, sizeof m.regs);
|
memset(m.regs, 0, sizeof m.regs);
|
||||||
|
@@ -11,6 +11,11 @@ public:
|
|||||||
bDSP();
|
bDSP();
|
||||||
~bDSP();
|
~bDSP();
|
||||||
|
|
||||||
|
template<int n, typename T> inline T asr(const T x) {
|
||||||
|
enum { bits = (sizeof(T) << 3) - n };
|
||||||
|
return sclip<bits>(x >> n);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum { echo_hist_size = 8 };
|
enum { echo_hist_size = 8 };
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
class DSP { public:
|
class DSP {
|
||||||
|
public:
|
||||||
virtual void enter() = 0;
|
virtual void enter() = 0;
|
||||||
|
|
||||||
virtual uint8 read (uint8 addr) = 0;
|
virtual uint8 read(uint8 addr) = 0;
|
||||||
virtual void write(uint8 addr, uint8 data) = 0;
|
virtual void write(uint8 addr, uint8 data) = 0;
|
||||||
|
|
||||||
virtual void power() = 0;
|
virtual void power() = 0;
|
||||||
|
@@ -1,22 +1,11 @@
|
|||||||
#ifdef POLYMORPHISM
|
|
||||||
#define ref(x) x
|
|
||||||
#else
|
|
||||||
#define ref(x) (&x)
|
|
||||||
#endif
|
|
||||||
#define deref(x) __##x
|
|
||||||
|
|
||||||
#define r_mem ref(deref(mem))
|
|
||||||
#define r_cpu ref(deref(cpu))
|
|
||||||
#define r_smp ref(deref(smp))
|
|
||||||
#define r_dsp ref(deref(dsp))
|
|
||||||
#define r_ppu ref(deref(ppu))
|
|
||||||
|
|
||||||
#include "reader/reader.h"
|
#include "reader/reader.h"
|
||||||
#include "cart/cart.h"
|
|
||||||
#include "cheat/cheat.h"
|
#include "cheat/cheat.h"
|
||||||
|
#include "config/config.h"
|
||||||
|
|
||||||
#include "memory/memory.h"
|
#include "memory/memory.h"
|
||||||
#include "memory/bmemory/bmemory.h"
|
#include "memory/smemory/smemory.h"
|
||||||
|
|
||||||
|
#include "cart/cart.h"
|
||||||
|
|
||||||
#include "cpu/cpu.h"
|
#include "cpu/cpu.h"
|
||||||
#include "cpu/scpu/scpu.h"
|
#include "cpu/scpu/scpu.h"
|
||||||
@@ -25,51 +14,23 @@
|
|||||||
#include "smp/ssmp/ssmp.h"
|
#include "smp/ssmp/ssmp.h"
|
||||||
|
|
||||||
#include "dsp/dsp.h"
|
#include "dsp/dsp.h"
|
||||||
//#include "dsp/adsp/adsp.h"
|
|
||||||
#include "dsp/bdsp/bdsp.h"
|
#include "dsp/bdsp/bdsp.h"
|
||||||
|
|
||||||
#include "ppu/ppu.h"
|
#include "ppu/ppu.h"
|
||||||
#include "ppu/bppu/bppu.h"
|
#include "ppu/bppu/bppu.h"
|
||||||
|
|
||||||
#include "snes/snes.h"
|
#include "snes/snes.h"
|
||||||
|
#include "chip/chip.h"
|
||||||
#include "chip/srtc/srtc.h"
|
|
||||||
#include "chip/sdd1/sdd1.h"
|
|
||||||
#include "chip/c4/c4.h"
|
|
||||||
#include "chip/dsp1/dsp1.h"
|
|
||||||
#include "chip/dsp2/dsp2.h"
|
|
||||||
#include "chip/obc1/obc1.h"
|
|
||||||
|
|
||||||
extern MMIO mmio_unmapped;
|
|
||||||
#ifdef POLYMORPHISM
|
|
||||||
extern MemBus *deref(mem);
|
|
||||||
extern CPU *deref(cpu);
|
|
||||||
extern SMP *deref(smp);
|
|
||||||
extern DSP *deref(dsp);
|
|
||||||
extern PPU *deref(ppu);
|
|
||||||
#else
|
|
||||||
extern MEMCORE deref(mem);
|
|
||||||
extern CPUCORE deref(cpu);
|
|
||||||
extern SMPCORE deref(smp);
|
|
||||||
extern DSPCORE deref(dsp);
|
|
||||||
extern PPUCORE deref(ppu);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "config/config.h"
|
|
||||||
|
|
||||||
#ifdef INTERFACE_MAIN
|
#ifdef INTERFACE_MAIN
|
||||||
#include "config/config.cpp"
|
#include "config/config.cpp"
|
||||||
#ifdef POLYMORPHISM
|
#define extern
|
||||||
MemBus *deref(mem);
|
|
||||||
CPU *deref(cpu);
|
|
||||||
APU *deref(smp);
|
|
||||||
DSP *deref(dsp);
|
|
||||||
PPU *deref(ppu);
|
|
||||||
#else
|
|
||||||
MEMCORE deref(mem);
|
|
||||||
CPUCORE deref(cpu);
|
|
||||||
SMPCORE deref(smp);
|
|
||||||
DSPCORE deref(dsp);
|
|
||||||
PPUCORE deref(ppu);
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern BUSCORE bus;
|
||||||
|
extern CPUCORE cpu;
|
||||||
|
extern SMPCORE smp;
|
||||||
|
extern DSPCORE dsp;
|
||||||
|
extern PPUCORE ppu;
|
||||||
|
|
||||||
|
#undef extern
|
||||||
|
@@ -1,14 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
libbase : version 0.11 ~byuu (2007-09-08)
|
bbase : version 0.12 ~byuu (2007-12-12)
|
||||||
license: public domain
|
license: public domain
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LIBBASE_H
|
#ifndef BBASE_H
|
||||||
#define LIBBASE_H
|
#define BBASE_H
|
||||||
|
|
||||||
|
#include <nall/stdint.hpp>
|
||||||
|
typedef int8_t int8;
|
||||||
|
typedef int16_t int16;
|
||||||
|
typedef int32_t int32;
|
||||||
|
typedef int64_t int64;
|
||||||
|
typedef uint8_t uint8;
|
||||||
|
typedef uint16_t uint16;
|
||||||
|
typedef uint32_t uint32;
|
||||||
|
typedef uint64_t uint64;
|
||||||
|
typedef unsigned int uint;
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
using std::min;
|
||||||
|
using std::max;
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@@ -16,8 +30,6 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <new>
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
@@ -70,22 +82,6 @@
|
|||||||
#define alwaysinline inline
|
#define alwaysinline inline
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*****
|
|
||||||
* typedefs
|
|
||||||
*****/
|
|
||||||
|
|
||||||
typedef unsigned int uint;
|
|
||||||
|
|
||||||
typedef uint8_t uint8;
|
|
||||||
typedef uint16_t uint16;
|
|
||||||
typedef uint32_t uint32;
|
|
||||||
typedef uint64_t uint64;
|
|
||||||
|
|
||||||
typedef int8_t int8;
|
|
||||||
typedef int16_t int16;
|
|
||||||
typedef int32_t int32;
|
|
||||||
typedef int64_t int64;
|
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
* OS localization
|
* OS localization
|
||||||
*****/
|
*****/
|
||||||
@@ -109,7 +105,7 @@ struct passwd *userinfo = getpwuid(getuid());
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
* templates
|
* template functions
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
template<typename T> inline void safe_free(T &handle) {
|
template<typename T> inline void safe_free(T &handle) {
|
||||||
@@ -133,114 +129,58 @@ template<typename T> inline void safe_release(T &handle) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> inline void swap(T &x, T &y) {
|
|
||||||
T z = x;
|
|
||||||
x = y;
|
|
||||||
y = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef min
|
|
||||||
#define min(x, y) (((x) < (y)) ? (x) : (y))
|
|
||||||
|
|
||||||
#undef max
|
|
||||||
#define max(x, y) (((x) > (y)) ? (x) : (y))
|
|
||||||
|
|
||||||
template<int min, int max, typename T> inline T minmax(const T x) {
|
template<int min, int max, typename T> inline T minmax(const T x) {
|
||||||
return (x < (T)min) ? (T)min : (x > (T)max) ? (T)max : x;
|
return (x < (T)min) ? (T)min : (x > (T)max) ? (T)max : x;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int bits> inline unsigned uclamp(const unsigned x) {
|
|
||||||
enum { y = (1U << bits) - 1 };
|
|
||||||
return y + ((x - y) & -(x < y)); //min(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int bits> inline unsigned uclip(const unsigned x) {
|
|
||||||
enum { m = (1U << bits) - 1 };
|
|
||||||
return (x & m);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int bits> inline signed sclamp(const signed x) {
|
|
||||||
enum { b = 1U << (bits - 1), m = (1U << (bits - 1)) - 1 };
|
|
||||||
return (x > m) ? m : (x < -b) ? -b : x;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int bits> inline signed sclip(const signed x) {
|
|
||||||
enum { b = 1U << (bits - 1), m = (1U << bits) - 1 };
|
|
||||||
return ((x & m) ^ b) - b;
|
|
||||||
}
|
|
||||||
|
|
||||||
//bit shifting functions are deprecated
|
|
||||||
|
|
||||||
template<int n, typename T> inline T rol(const T x) {
|
|
||||||
enum { s = (sizeof(T) << 3) - n };
|
|
||||||
return (x << n) | (x >> s);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int n, typename T> inline T ror(const T x) {
|
|
||||||
enum { s = (sizeof(T) << 3) - n };
|
|
||||||
return (x >> n) | (x << s);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int n, typename T> inline T asl(const T x) {
|
|
||||||
return (x << n);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int n, typename T> inline T asr(const T x) {
|
|
||||||
enum { bits = (sizeof(T) << 3) - n };
|
|
||||||
return sclip<bits>(x >> n);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int n, typename T> inline T lsl(const T x) {
|
|
||||||
return (x << n);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int n, typename T> inline T lsr(const T x) {
|
|
||||||
enum { bits = (sizeof(T) << 3) - n };
|
|
||||||
return uclip<bits>(x >> n);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
* endian wrappers
|
* endian wrappers
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
#ifndef ARCH_MSB
|
#ifndef ARCH_MSB
|
||||||
//little-endian: uint8[] { 0x01, 0x02, 0x03, 0x04 } = 0x04030201
|
//little-endian: uint8[] { 0x01, 0x02, 0x03, 0x04 } == 0x04030201
|
||||||
#define order_lsb2(a,b) a,b
|
#define order_lsb2(a,b) a,b
|
||||||
#define order_lsb3(a,b,c) a,b,c
|
#define order_lsb3(a,b,c) a,b,c
|
||||||
#define order_lsb4(a,b,c,d) a,b,c,d
|
#define order_lsb4(a,b,c,d) a,b,c,d
|
||||||
#define order_lsb5(a,b,c,d,e) a,b,c,d,e
|
#define order_lsb5(a,b,c,d,e) a,b,c,d,e
|
||||||
#define order_lsb6(a,b,c,d,e,f) a,b,c,d,e,f
|
#define order_lsb6(a,b,c,d,e,f) a,b,c,d,e,f
|
||||||
#define order_lsb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g
|
#define order_lsb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g
|
||||||
#define order_lsb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h
|
#define order_lsb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h
|
||||||
#define order_msb2(a,b) b,a
|
#define order_msb2(a,b) b,a
|
||||||
#define order_msb3(a,b,c) c,b,a
|
#define order_msb3(a,b,c) c,b,a
|
||||||
#define order_msb4(a,b,c,d) d,c,b,a
|
#define order_msb4(a,b,c,d) d,c,b,a
|
||||||
#define order_msb5(a,b,c,d,e) e,d,c,b,a
|
#define order_msb5(a,b,c,d,e) e,d,c,b,a
|
||||||
#define order_msb6(a,b,c,d,e,f) f,e,d,c,b,a
|
#define order_msb6(a,b,c,d,e,f) f,e,d,c,b,a
|
||||||
#define order_msb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a
|
#define order_msb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a
|
||||||
#define order_msb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a
|
#define order_msb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a
|
||||||
#else
|
#else
|
||||||
//big-endian: uint8[] { 0x01, 0x02, 0x03, 0x04 } = 0x01020304
|
//big-endian: uint8[] { 0x01, 0x02, 0x03, 0x04 } == 0x01020304
|
||||||
#define order_lsb2(a,b) b,a
|
#define order_lsb2(a,b) b,a
|
||||||
#define order_lsb3(a,b,c) c,b,a
|
#define order_lsb3(a,b,c) c,b,a
|
||||||
#define order_lsb4(a,b,c,d) d,c,b,a
|
#define order_lsb4(a,b,c,d) d,c,b,a
|
||||||
#define order_lsb5(a,b,c,d,e) e,d,c,b,a
|
#define order_lsb5(a,b,c,d,e) e,d,c,b,a
|
||||||
#define order_lsb6(a,b,c,d,e,f) f,e,d,c,b,a
|
#define order_lsb6(a,b,c,d,e,f) f,e,d,c,b,a
|
||||||
#define order_lsb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a
|
#define order_lsb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a
|
||||||
#define order_lsb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a
|
#define order_lsb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a
|
||||||
#define order_msb2(a,b) a,b
|
#define order_msb2(a,b) a,b
|
||||||
#define order_msb3(a,b,c) a,b,c
|
#define order_msb3(a,b,c) a,b,c
|
||||||
#define order_msb4(a,b,c,d) a,b,c,d
|
#define order_msb4(a,b,c,d) a,b,c,d
|
||||||
#define order_msb5(a,b,c,d,e) a,b,c,d,e
|
#define order_msb5(a,b,c,d,e) a,b,c,d,e
|
||||||
#define order_msb6(a,b,c,d,e,f) a,b,c,d,e,f
|
#define order_msb6(a,b,c,d,e,f) a,b,c,d,e,f
|
||||||
#define order_msb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g
|
#define order_msb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g
|
||||||
#define order_msb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h
|
#define order_msb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
* libc extensions
|
* libc extensions
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
|
//pseudo-random number generator
|
||||||
|
static uint prng() {
|
||||||
|
static uint n = 0;
|
||||||
|
return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320);
|
||||||
|
}
|
||||||
|
|
||||||
static uint64 fget(FILE *fp, uint length = 1) {
|
static uint64 fget(FILE *fp, uint length = 1) {
|
||||||
uint64 data = 0;
|
uint64 data = 0;
|
||||||
for(uint i = 0; i < length; i++) {
|
for(uint i = 0; i < length; i++) {
|
||||||
@@ -288,7 +228,6 @@ static int fresize(FILE *fp, long size) {
|
|||||||
|
|
||||||
/*****
|
/*****
|
||||||
* crc32 calculation
|
* crc32 calculation
|
||||||
* TODO: create libhash and move this code there
|
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
const uint32 crc32_table[256] = {
|
const uint32 crc32_table[256] = {
|
||||||
@@ -349,4 +288,4 @@ uint32 crc32 = ~0;
|
|||||||
return ~crc32;
|
return ~crc32;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif //ifndef BBASE_H
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user