mirror of
https://github.com/ares-emulator/ares.git
synced 2026-11-08 01:08:24 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bbc77a6cf2 | ||
|
|
ebb9367c68 | ||
|
|
96fe8f760d | ||
|
|
8abd1b2dfe | ||
|
|
f6efcbe6fd | ||
|
|
36859ea52c | ||
|
|
64589148d4 | ||
|
|
89ae1101ee | ||
|
|
340d86845a | ||
|
|
b895f29bed | ||
|
|
1ef279cb83 | ||
|
|
0241dd78b7 | ||
|
|
a13c3aece6 | ||
|
|
20977817ae | ||
|
|
ba25c82939 | ||
|
|
3babe932fd | ||
|
|
6bdeaef0f4 | ||
|
|
9e3827e2a2 | ||
|
|
e499670ad9 | ||
|
|
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 | ||
|
|
c9ca01fe20 | ||
|
|
becf122aaa | ||
|
|
1e130d7872 | ||
|
|
c57c733d7d | ||
|
|
e41aa25887 | ||
|
|
435f7d4371 | ||
|
|
a1980fab09 | ||
|
|
ebb234ba5f | ||
|
|
2cc7fe30b4 | ||
|
|
5c3c872b78 | ||
|
|
36bf915244 | ||
|
|
045a0f7e79 | ||
|
|
a209e6ffbe | ||
|
|
3bf672dd97 | ||
|
|
157ddf3e8f | ||
|
|
ea23bf53ae | ||
|
|
d4598e1d01 | ||
|
|
f9a8564af0 | ||
|
|
6d66b1136d | ||
|
|
b01f18c34c | ||
|
|
1ebdb69516 | ||
|
|
add0f74387 | ||
|
|
b20f70f333 | ||
|
|
9aebf7bc6b | ||
|
|
a7bf219d5d | ||
|
|
04118be59a | ||
|
|
f24d17859f | ||
|
|
35fd80bde7 | ||
|
|
ccf1c00b58 | ||
|
|
f4520d41ec | ||
|
|
e308cf4275 | ||
|
|
192e53bb87 | ||
|
|
0ed9edfcdb | ||
|
|
764fe1974a | ||
|
|
a55d640459 | ||
|
|
6010bffe5d | ||
|
|
e492268025 | ||
|
|
a36c26c997 | ||
|
|
a3945e5772 | ||
|
|
6b6233b3af | ||
|
|
9f63cb1b99 | ||
|
|
49c39e0e4d | ||
|
|
7dec0b2a3c | ||
|
|
f288280ceb |
No files matched your search
@@ -1,135 +0,0 @@
|
||||
# Applies contrast adjust filter to video output when enabled
|
||||
# Works by lowering the brightness of darker colors,
|
||||
# while leaving brighter colors alone; thus reducing saturation
|
||||
# (default = true)
|
||||
snes.video_color_curve = true
|
||||
|
||||
# Selects color adjustment filter for video output
|
||||
# 0 = Normal (no filter, rgb555)
|
||||
# 1 = Grayscale mode (l5)
|
||||
# 2 = VGA mode (rgb332)
|
||||
# 3 = Genesis mode (rgb333)
|
||||
# (default = 0)
|
||||
snes.video_color_adjust_mode = 0
|
||||
|
||||
# Mutes SNES audio output when enabled
|
||||
# (default = true)
|
||||
snes.mute = true
|
||||
|
||||
# Video mode
|
||||
# 0 = 256x224w
|
||||
# 1 = 512x448w
|
||||
# 2 = 960x720w
|
||||
# 3 = 640x480f
|
||||
# 4 = 1024x768f
|
||||
# (default = 1)
|
||||
video.mode = 1
|
||||
|
||||
# Use Video RAM instead of System RAM
|
||||
# (default = true)
|
||||
video.use_vram = true
|
||||
|
||||
# Wait for vertical retrace when updating screen
|
||||
# (default = false)
|
||||
video.vblank = false
|
||||
|
||||
# Show framerate in window title
|
||||
# (default = true)
|
||||
gui.show_fps = true
|
||||
|
||||
# Joypad1 up
|
||||
# (default = 0x26)
|
||||
input.joypad1.up = 0x26
|
||||
|
||||
# Joypad1 down
|
||||
# (default = 0x28)
|
||||
input.joypad1.down = 0x28
|
||||
|
||||
# Joypad1 left
|
||||
# (default = 0x25)
|
||||
input.joypad1.left = 0x25
|
||||
|
||||
# Joypad1 right
|
||||
# (default = 0x27)
|
||||
input.joypad1.right = 0x27
|
||||
|
||||
# Joypad1 A
|
||||
# (default = 0x58)
|
||||
input.joypad1.a = 0x58
|
||||
|
||||
# Joypad1 B
|
||||
# (default = 0x5a)
|
||||
input.joypad1.b = 0x5a
|
||||
|
||||
# Joypad1 X
|
||||
# (default = 0x53)
|
||||
input.joypad1.x = 0x53
|
||||
|
||||
# Joypad1 Y
|
||||
# (default = 0x41)
|
||||
input.joypad1.y = 0x41
|
||||
|
||||
# Joypad1 L
|
||||
# (default = 0x44)
|
||||
input.joypad1.l = 0x44
|
||||
|
||||
# Joypad1 R
|
||||
# (default = 0x43)
|
||||
input.joypad1.r = 0x43
|
||||
|
||||
# Joypad1 select
|
||||
# (default = 0x10)
|
||||
input.joypad1.select = 0x10
|
||||
|
||||
# Joypad1 start
|
||||
# (default = 0xd)
|
||||
input.joypad1.start = 0xd
|
||||
|
||||
# Joypad2 up
|
||||
# (default = 0x54)
|
||||
input.joypad2.up = 0x54
|
||||
|
||||
# Joypad2 down
|
||||
# (default = 0x47)
|
||||
input.joypad2.down = 0x47
|
||||
|
||||
# Joypad2 left
|
||||
# (default = 0x46)
|
||||
input.joypad2.left = 0x46
|
||||
|
||||
# Joypad2 right
|
||||
# (default = 0x48)
|
||||
input.joypad2.right = 0x48
|
||||
|
||||
# Joypad2 A
|
||||
# (default = 0x4b)
|
||||
input.joypad2.a = 0x4b
|
||||
|
||||
# Joypad2 B
|
||||
# (default = 0x4a)
|
||||
input.joypad2.b = 0x4a
|
||||
|
||||
# Joypad2 X
|
||||
# (default = 0x49)
|
||||
input.joypad2.x = 0x49
|
||||
|
||||
# Joypad2 Y
|
||||
# (default = 0x55)
|
||||
input.joypad2.y = 0x55
|
||||
|
||||
# Joypad2 L
|
||||
# (default = 0x4f)
|
||||
input.joypad2.l = 0x4f
|
||||
|
||||
# Joypad2 R
|
||||
# (default = 0x4c)
|
||||
input.joypad2.r = 0x4c
|
||||
|
||||
# Joypad2 select
|
||||
# (default = 0x5b)
|
||||
input.joypad2.select = 0x5b
|
||||
|
||||
# Joypad2 start
|
||||
# (default = 0x5d)
|
||||
input.joypad2.start = 0x5d
|
||||
|
||||
+82
-22
@@ -1,26 +1,86 @@
|
||||
bsnes License:
|
||||
--------------
|
||||
You are free to redistribute this software, and its source code; provided
|
||||
there is no charge for the software, nor any charge for the medium used to
|
||||
distribute the software. You are also free to use and modify the source code
|
||||
as you desire for personal use only. No publically-released derivative works
|
||||
of this source code are permitted without my permission, though I will likely
|
||||
grant you permission if you ask me. You must also abide by the terms of any
|
||||
additional source code licenses contained within this program.
|
||||
bsnes (TM) Reference License
|
||||
Copyright (C) 2004 - 2008 byuu
|
||||
All rights reserved
|
||||
|
||||
Simple DirectMedia Layer License:
|
||||
---------------------------------
|
||||
The Simple DirectMedia Layer (SDL for short) is a cross-platform library
|
||||
designed to make it easy to write multi-media software, such as games and
|
||||
emulators.
|
||||
1. Definitions
|
||||
|
||||
The Simple DirectMedia Layer library source code is available from:
|
||||
http://www.libsdl.org/
|
||||
The terms "reproduce", "reproduction", "distribute" and "distribution" have the
|
||||
same meaning here as under U.S. copyright law.
|
||||
|
||||
This library is distributed under the terms of the GNU LGPL:
|
||||
http://www.gnu.org/copyleft/lesser.html
|
||||
"The software" means this software package as a whole, including, but not
|
||||
limited to, this license, binaries, source code, documentation, and data.
|
||||
|
||||
Licensing Exemptions:
|
||||
---------------------
|
||||
Richard Bannister has asked for and received my permission to distribute
|
||||
a binary-only port of bsnes on the Mac OS X platform.
|
||||
"You" means the licensee of the software.
|
||||
|
||||
"The licensor" means the copyright holder of the software, byuu.
|
||||
|
||||
2. Grant of Rights
|
||||
|
||||
Subject to the terms of this license, the licensor grants you a
|
||||
non-transferable, non-exclusive, worldwide, royalty-free copyright license to
|
||||
reproduce the software for non-commercial use only, provided the software
|
||||
remains unmodified, and there is no charge for the software itself, its' use,
|
||||
nor for the medium upon which the software is distributed. The reproduction of
|
||||
modified or derivative works of the software is strictly prohibited, except when
|
||||
transmitted solely to the licensor.
|
||||
|
||||
3. Limitations
|
||||
|
||||
This license does not grant you any rights to use the licensor's name, logo or
|
||||
trademarks.
|
||||
|
||||
The software is provided "as is", and any express or implied warranties,
|
||||
including, but not limited to, the implied warranties of merchantability and
|
||||
fitness for a particular purpose are disclaimed. In no event shall the licensor
|
||||
be liable for any direct, indirect, incidental, special, exemplary, or
|
||||
consequential damages (including, but not limited to, procurement of substitute
|
||||
goods or services; loss of use, data, or profits; or business interruption)
|
||||
however caused and on any theory of liability, whether in contract, strict
|
||||
liability, or tort (including negligence or otherwise) arising in any way out of
|
||||
the use of the software, even if advised of the possibility of such damage.
|
||||
|
||||
In the event that this license is determined to be invalid or unenforceable, the
|
||||
Grant of Rights will become null and void, and no rights shall be granted to the
|
||||
licensee, within the scope of U.S. copyright law.
|
||||
|
||||
4. Exemptions
|
||||
|
||||
The software includes the work of other copyright holders, which is licensed
|
||||
under different agreements, and exempt from this license. Below is a complete
|
||||
list of all such software, and their respective copyright holders and licenses.
|
||||
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
|
||||
under the bsnes license.
|
||||
|
||||
HQ2x filter, author: MaxST, license: LGPL
|
||||
JMA decompressor, author: NSRT Team, license: GPL (*)
|
||||
NTSC filter, author: blargg, license: LGPL
|
||||
zlib decompressor, license: zlib license
|
||||
|
||||
(*) 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
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
bsnes
|
||||
Version: 0.032a
|
||||
Author: byuu
|
||||
|
||||
--------
|
||||
General:
|
||||
--------
|
||||
bsnes is a Super Nintendo / Super Famicom emulator that began on
|
||||
October 14th, 2004.
|
||||
|
||||
The latest version can be downloaded from:
|
||||
http://byuu.org/
|
||||
|
||||
Please see license.txt for important licensing information.
|
||||
|
||||
--------------
|
||||
Configuration:
|
||||
--------------
|
||||
bsnes has two configuration files: bsnes.cfg, for program settings; and
|
||||
locale.cfg, for localization.
|
||||
|
||||
For each file, bsnes will start by looking inside the same folder where the
|
||||
bsnes executable is located. If said file is not found, it will then check your
|
||||
user profile folder. On Windows, this is located at "%APPDATA%/.bsnes". On all
|
||||
other operating systems, this is located at "~/.bsnes". If said file is still
|
||||
not found, it will automatically be created in your user profile folder.
|
||||
|
||||
If you wish to use bsnes in single-user mode, be sure that both files exist
|
||||
inside the same folder as the bsnes executable. If they do not, you can simply
|
||||
create new blank files and bsnes will use them in the future.
|
||||
|
||||
If you wish to use bsnes in multi-user mode, simply delete these two files from
|
||||
the bsnes executable directory if they exist.
|
||||
|
||||
If you wish to have multiple configuration profiles for the same user, you will
|
||||
need to make copies of the bsnes executable, and use each one in single-user
|
||||
mode.
|
||||
|
||||
------------------
|
||||
Known Limitations:
|
||||
------------------
|
||||
S-CPU
|
||||
- Multiply / divide register delays not implemented
|
||||
|
||||
S-PPU
|
||||
- Uses scanline-based renderer. This is very inaccurate, but few (if any)
|
||||
games rely on mid-scanline writes to function correctly
|
||||
- Does not support FirstSprite+Y priority
|
||||
- OAM / CGRAM accesses during active display not supported correctly
|
||||
- RTO flags are not calculated on frames that are skipped when frameskipping
|
||||
is enabled. This provides a major speedup, however it will cause in issues
|
||||
in games that test these flags, eg the SNES Test Program Electronics Test.
|
||||
Turning frameskipping off will allow RTO flag calculation on every frame
|
||||
|
||||
Hardware Bugs
|
||||
- S-CPU.r1 HDMA crashing bug not emulated
|
||||
- S-CPU<>S-SMP communication bus conflicts not emulated
|
||||
|
||||
---------------------
|
||||
Unsupported Hardware:
|
||||
---------------------
|
||||
SA-1
|
||||
Coprocessor used in many popular games, including:
|
||||
- Dragon Ball Z Hyper Dimension
|
||||
- Kirby Super Star
|
||||
- Kirby's Dreamland 3
|
||||
- Marvelous
|
||||
- SD Gundam G-NEXT
|
||||
- Super Mario RPG
|
||||
|
||||
Super FX
|
||||
Coprocessor used in many popular games, including:
|
||||
- Doom
|
||||
- Star Fox
|
||||
- Star Fox 2 (unreleased beta)
|
||||
- Super Mario World 2: Yoshi's Island
|
||||
|
||||
SPC7110
|
||||
Coprocessor used only by the following games:
|
||||
- Far East of Eden Zero
|
||||
- Far East of Eden Zero: Shounen Jump no Shou
|
||||
- Momotarou Densetsu Happy
|
||||
- Super Power League 4
|
||||
|
||||
ST-011
|
||||
SETA DSP used by Quick-move Shogi Match with Nidan Rank-holder Morita
|
||||
|
||||
ST-018
|
||||
SETA RISC CPU used by Quick-move Shogi Match with Nidan Rank-holder Morita 2
|
||||
|
||||
Super Gameboy
|
||||
Cartridge passthrough used for playing Gameboy games
|
||||
|
||||
------------------------
|
||||
Unsupported Controllers:
|
||||
------------------------
|
||||
Mouse
|
||||
Super Scope
|
||||
Justifier
|
||||
Multitap (4-port and 5-port)
|
||||
+279
@@ -0,0 +1,279 @@
|
||||
include lib/nall/Makefile.string
|
||||
prefix = /usr/local
|
||||
|
||||
################
|
||||
### compiler ###
|
||||
################
|
||||
|
||||
ifneq ($(findstring gcc,$(compiler)),) # GCC family
|
||||
flags = -O3 -fomit-frame-pointer -Ilib
|
||||
c = $(compiler) $(flags)
|
||||
cpp = $(subst cc,++,$(compiler)) $(flags)
|
||||
obj = o
|
||||
rule = -c $< -o $@
|
||||
link = -s
|
||||
mkbin = -o$1
|
||||
mkdef = -D$1
|
||||
mklib = -l$1
|
||||
else ifeq ($(compiler),cl) # Visual C++
|
||||
flags = /nologo /wd4355 /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
|
||||
|
||||
##########
|
||||
### os ###
|
||||
##########
|
||||
|
||||
ifeq ($(platform),x) # X11
|
||||
ruby = video.glx video.xv video.sdl audio.openal audio.oss audio.alsa audio.ao input.sdl input.x
|
||||
link += `pkg-config --libs gtk+-2.0`
|
||||
link += $(call mklib,Xtst)
|
||||
delete = rm -f $1
|
||||
else ifeq ($(platform),win) # Windows
|
||||
ruby = video.direct3d video.wgl video.directdraw video.gdi audio.directsound input.directinput
|
||||
link += $(if $(findstring mingw,$(compiler)),-mwindows)
|
||||
link += $(call mklib,uuid)
|
||||
link += $(call mklib,kernel32)
|
||||
link += $(call mklib,user32)
|
||||
link += $(call mklib,gdi32)
|
||||
link += $(call mklib,shell32)
|
||||
link += $(call mklib,winmm)
|
||||
link += $(call mklib,comdlg32)
|
||||
link += $(call mklib,comctl32)
|
||||
delete = $(if $(findstring i586-mingw-gcc,$(compiler)),rm -f $1,del $(subst /,\,$1))
|
||||
else
|
||||
unknown_platform: help;
|
||||
endif
|
||||
|
||||
############
|
||||
### ruby ###
|
||||
############
|
||||
|
||||
rubyflags =
|
||||
rubyflags += $(if $(findstring .sdl,$(ruby)),`sdl-config --cflags`)
|
||||
|
||||
link += $(if $(findstring video.direct3d,$(ruby)),$(call mklib,d3d9))
|
||||
link += $(if $(findstring video.directdraw,$(ruby)),$(call mklib,ddraw))
|
||||
link += $(if $(findstring video.glx,$(ruby)),$(call mklib,GL))
|
||||
link += $(if $(findstring video.wgl,$(ruby)),$(call mklib,opengl32))
|
||||
link += $(if $(findstring video.xv,$(ruby)),$(call mklib,Xv))
|
||||
link += $(if $(findstring audio.alsa,$(ruby)),$(call mklib,asound))
|
||||
link += $(if $(findstring audio.ao,$(ruby)),$(call mklib,ao))
|
||||
link += $(if $(findstring audio.directsound,$(ruby)),$(call mklib,dsound))
|
||||
link += $(if $(findstring audio.openal,$(ruby)),$(if $(call streq,$(platform),x),$(call mklib,openal),$(call mklib,openal32)))
|
||||
link += $(if $(findstring input.directinput,$(ruby)),$(call mklib,dinput8) $(call mklib,dxguid))
|
||||
link += $(if $(findstring input.sdl,$(ruby)),`sdl-config --libs`)
|
||||
|
||||
####################################
|
||||
### main target and dependencies ###
|
||||
####################################
|
||||
|
||||
objects = main libco hiro ruby libfilter string reader cart cheat \
|
||||
memory smemory cpu scpu smp ssmp sdsp ppu bppu snes \
|
||||
bsx srtc sdd1 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010
|
||||
|
||||
ifeq ($(enable_gzip),true)
|
||||
objects += adler32 compress crc32 deflate gzio inffast inflate inftrees ioapi trees unzip zip zutil
|
||||
flags += $(call mkdef,GZIP_SUPPORT)
|
||||
endif
|
||||
|
||||
ifeq ($(enable_jma),true)
|
||||
objects += jma jcrc32 lzmadec 7zlzma iiostrm inbyte lzma winout
|
||||
flags += $(call mkdef,JMA_SUPPORT)
|
||||
endif
|
||||
|
||||
objects := $(patsubst %,obj/%.$(obj),$(objects))
|
||||
rubydef := $(foreach c,$(subst .,_,$(call strupper,$(ruby))),$(call mkdef,$c))
|
||||
|
||||
# Windows resource file
|
||||
ifeq ($(platform),win)
|
||||
ifeq ($(compiler),cl)
|
||||
objects += obj/bsnes.res
|
||||
else ifneq ($(findstring gcc,$(compiler)),)
|
||||
objects += obj/bsnesrc.$(obj)
|
||||
endif
|
||||
endif
|
||||
|
||||
################
|
||||
### implicit ###
|
||||
################
|
||||
|
||||
compile = \
|
||||
$(strip \
|
||||
$(if $(filter %.c,$<), \
|
||||
$(c) $1 $(rule), \
|
||||
$(if $(filter %.cpp,$<), \
|
||||
$(cpp) $1 $(rule) \
|
||||
) \
|
||||
) \
|
||||
)
|
||||
|
||||
%.$(obj): $<; $(call compile)
|
||||
|
||||
all: build;
|
||||
|
||||
############
|
||||
### main ###
|
||||
############
|
||||
|
||||
obj/main.$(obj): ui/main.cpp ui/* ui/base/* ui/loader/* ui/settings/*
|
||||
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)
|
||||
|
||||
#################
|
||||
### libraries ###
|
||||
#################
|
||||
|
||||
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 ###
|
||||
#################
|
||||
|
||||
obj/reader.$(obj): reader/reader.cpp reader/*
|
||||
obj/cart.$(obj) : cart/cart.cpp cart/*
|
||||
obj/cheat.$(obj) : cheat/cheat.cpp cheat/*
|
||||
|
||||
##############
|
||||
### memory ###
|
||||
##############
|
||||
|
||||
obj/memory.$(obj) : memory/memory.cpp memory/*
|
||||
obj/smemory.$(obj): memory/smemory/smemory.cpp memory/smemory/* memory/smemory/mapper/*
|
||||
|
||||
###########
|
||||
### cpu ###
|
||||
###########
|
||||
|
||||
obj/cpu.$(obj) : cpu/cpu.cpp cpu/*
|
||||
obj/scpu.$(obj): cpu/scpu/scpu.cpp cpu/scpu/* cpu/scpu/core/* cpu/scpu/dma/* cpu/scpu/memory/* cpu/scpu/mmio/* cpu/scpu/timing/*
|
||||
|
||||
###########
|
||||
### smp ###
|
||||
###########
|
||||
|
||||
obj/smp.$(obj) : smp/smp.cpp smp/*
|
||||
obj/ssmp.$(obj): smp/ssmp/ssmp.cpp smp/ssmp/* smp/ssmp/core/* smp/ssmp/memory/* smp/ssmp/timing/*
|
||||
|
||||
###########
|
||||
### dsp ###
|
||||
###########
|
||||
|
||||
obj/adsp.$(obj): dsp/adsp/adsp.cpp dsp/adsp/*
|
||||
obj/bdsp.$(obj): dsp/bdsp/bdsp.cpp dsp/bdsp/*
|
||||
obj/sdsp.$(obj): dsp/sdsp/sdsp.cpp dsp/sdsp/*
|
||||
|
||||
###########
|
||||
### ppu ###
|
||||
###########
|
||||
|
||||
obj/ppu.$(obj) : ppu/ppu.cpp ppu/*
|
||||
obj/bppu.$(obj): ppu/bppu/bppu.cpp ppu/bppu/*
|
||||
|
||||
############
|
||||
### snes ###
|
||||
############
|
||||
|
||||
obj/snes.$(obj): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* snes/input/*
|
||||
|
||||
#####################
|
||||
### special chips ###
|
||||
#####################
|
||||
|
||||
obj/bsx.$(obj) : chip/bsx/bsx.cpp chip/bsx/*
|
||||
obj/srtc.$(obj) : chip/srtc/srtc.cpp chip/srtc/*
|
||||
obj/sdd1.$(obj) : chip/sdd1/sdd1.cpp chip/sdd1/*
|
||||
obj/cx4.$(obj) : chip/cx4/cx4.cpp chip/cx4/*
|
||||
obj/dsp1.$(obj) : chip/dsp1/dsp1.cpp chip/dsp1/*
|
||||
obj/dsp2.$(obj) : chip/dsp2/dsp2.cpp chip/dsp2/*
|
||||
obj/dsp3.$(obj) : chip/dsp3/dsp3.cpp chip/dsp3/*
|
||||
obj/dsp4.$(obj) : chip/dsp4/dsp4.cpp chip/dsp4/*
|
||||
obj/obc1.$(obj) : chip/obc1/obc1.cpp chip/obc1/*
|
||||
obj/st010.$(obj): chip/st010/st010.cpp chip/st010/*
|
||||
|
||||
############
|
||||
### zlib ###
|
||||
############
|
||||
|
||||
obj/adler32.$(obj) : reader/zlib/adler32.c reader/zlib/*
|
||||
obj/compress.$(obj): reader/zlib/compress.c reader/zlib/*
|
||||
obj/crc32.$(obj) : reader/zlib/crc32.c reader/zlib/*
|
||||
obj/deflate.$(obj) : reader/zlib/deflate.c reader/zlib/*
|
||||
obj/gzio.$(obj) : reader/zlib/gzio.c reader/zlib/*
|
||||
obj/inffast.$(obj) : reader/zlib/inffast.c reader/zlib/*
|
||||
obj/inflate.$(obj) : reader/zlib/inflate.c reader/zlib/*
|
||||
obj/inftrees.$(obj): reader/zlib/inftrees.c reader/zlib/*
|
||||
obj/ioapi.$(obj) : reader/zlib/ioapi.c reader/zlib/*
|
||||
obj/trees.$(obj) : reader/zlib/trees.c reader/zlib/*
|
||||
obj/unzip.$(obj) : reader/zlib/unzip.c reader/zlib/*
|
||||
obj/zip.$(obj) : reader/zlib/zip.c reader/zlib/*
|
||||
obj/zutil.$(obj) : reader/zlib/zutil.c reader/zlib/*
|
||||
|
||||
###########
|
||||
### jma ###
|
||||
###########
|
||||
|
||||
obj/jma.$(obj) : reader/jma/jma.cpp reader/jma/*
|
||||
obj/jcrc32.$(obj) : reader/jma/jcrc32.cpp reader/jma/*
|
||||
obj/lzmadec.$(obj): reader/jma/lzmadec.cpp reader/jma/*
|
||||
obj/7zlzma.$(obj) : reader/jma/7zlzma.cpp reader/jma/*
|
||||
obj/iiostrm.$(obj): reader/jma/iiostrm.cpp reader/jma/*
|
||||
obj/inbyte.$(obj) : reader/jma/inbyte.cpp reader/jma/*
|
||||
obj/lzma.$(obj) : reader/jma/lzma.cpp reader/jma/*
|
||||
obj/winout.$(obj) : reader/jma/winout.cpp reader/jma/*
|
||||
|
||||
###############
|
||||
### 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:
|
||||
-@$(call delete,obj/*.$(obj))
|
||||
-@$(call delete,*.res)
|
||||
-@$(call delete,*.pgd)
|
||||
-@$(call delete,*.pgc)
|
||||
-@$(call delete,*.ilk)
|
||||
-@$(call delete,*.pdb)
|
||||
-@$(call delete,*.manifest)
|
||||
|
||||
help:
|
||||
@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 ""
|
||||
@@ -1,30 +0,0 @@
|
||||
#include "apuregs.h"
|
||||
|
||||
class APU {
|
||||
public:
|
||||
APURegs regs;
|
||||
static const uint8 iplrom[64];
|
||||
enum {
|
||||
FLAG_N = 0x80, FLAG_V = 0x40,
|
||||
FLAG_P = 0x20, FLAG_B = 0x10,
|
||||
FLAG_H = 0x08, FLAG_I = 0x04,
|
||||
FLAG_Z = 0x02, FLAG_C = 0x01
|
||||
};
|
||||
|
||||
virtual uint8 spcram_read (uint16 addr) = 0;
|
||||
virtual void spcram_write(uint16 addr, uint8 value) = 0;
|
||||
//$f4-$f7
|
||||
virtual uint8 port_read (uint8 port) = 0;
|
||||
virtual void port_write(uint8 port, uint8 value) = 0;
|
||||
|
||||
virtual uint8 *get_spcram_handle() = 0;
|
||||
virtual void run() = 0;
|
||||
virtual uint32 cycles_executed() = 0;
|
||||
virtual void power() = 0;
|
||||
virtual void reset() = 0;
|
||||
|
||||
//debugging functions
|
||||
virtual bool in_opcode();
|
||||
void disassemble_opcode(char *output);
|
||||
inline uint16 __relb(int8 offset, int op_len);
|
||||
};
|
||||
@@ -1,49 +0,0 @@
|
||||
class APURegFlags {
|
||||
private:
|
||||
template <uint8 B> class bit {
|
||||
public:
|
||||
uint8 _b;
|
||||
inline operator bool() { return (_b & B); }
|
||||
inline bool operator = (bool i) { (i) ? _b |= B : _b &= ~B; return (_b & B); }
|
||||
inline bool operator & (bool i) { if(i)_b &= ~B; return (_b & B); }
|
||||
inline bool operator &= (bool i) { if(i)_b &= ~B; return (_b & B); }
|
||||
inline bool operator | (bool i) { if(i)_b |= B; return (_b & B); }
|
||||
inline bool operator |= (bool i) { if(i)_b |= B; return (_b & B); }
|
||||
inline bool operator ^ (bool i) { if(i)_b ^= B; return (_b & B); }
|
||||
inline bool operator ^= (bool i) { if(i)_b ^= B; return (_b & B); }
|
||||
};
|
||||
public:
|
||||
union {
|
||||
uint8 _b;
|
||||
bit<0x80> n;
|
||||
bit<0x40> v;
|
||||
bit<0x20> p;
|
||||
bit<0x10> b;
|
||||
bit<0x08> h;
|
||||
bit<0x04> i;
|
||||
bit<0x02> z;
|
||||
bit<0x01> c;
|
||||
};
|
||||
|
||||
APURegFlags() { _b = 0; }
|
||||
inline operator uint8() { return _b; }
|
||||
inline unsigned operator = (uint8 i) { _b = i; return _b; }
|
||||
inline unsigned operator &= (uint8 i) { _b &= i; return _b; }
|
||||
inline unsigned operator |= (uint8 i) { _b |= i; return _b; }
|
||||
inline unsigned operator ^= (uint8 i) { _b ^= i; return _b; }
|
||||
};
|
||||
|
||||
class APURegs {
|
||||
public:
|
||||
uint16 pc;
|
||||
union {
|
||||
uint16 ya;
|
||||
#ifdef ARCH_LSB
|
||||
struct { uint8 a, y; };
|
||||
#else
|
||||
struct { uint8 y, a; };
|
||||
#endif
|
||||
};
|
||||
uint8 x, sp;
|
||||
APURegFlags p;
|
||||
};
|
||||
@@ -1,299 +0,0 @@
|
||||
#include "../../base.h"
|
||||
|
||||
#include "bapu_op_fn.cpp"
|
||||
#include "bapu_op_mov.cpp"
|
||||
#include "bapu_op_pc.cpp"
|
||||
#include "bapu_op_read.cpp"
|
||||
#include "bapu_op_rmw.cpp"
|
||||
#include "bapu_op_misc.cpp"
|
||||
|
||||
#include "bapu_exec.cpp"
|
||||
|
||||
uint8 bAPU::spcram_read(uint16 addr) {
|
||||
uint8 r;
|
||||
if(addr >= 0x00f0 && addr <= 0x00ff) {
|
||||
switch(addr) {
|
||||
case 0xf0: //TEST -- operation unknown, supposedly returns 0x00
|
||||
r = 0x00;
|
||||
break;
|
||||
case 0xf1: //CONTROL -- write-only register, always returns 0x00
|
||||
r = 0x00;
|
||||
break;
|
||||
case 0xf2: //DSPADDR
|
||||
r = status.dsp_addr;
|
||||
break;
|
||||
case 0xf3: //DSPDATA
|
||||
//0x80-0xff is a read-only mirror of 0x00-0x7f
|
||||
r = dsp->read(status.dsp_addr & 0x7f);
|
||||
break;
|
||||
case 0xf4: //CPUIO0
|
||||
case 0xf5: //CPUIO1
|
||||
case 0xf6: //CPUIO2
|
||||
case 0xf7: //CPUIO3
|
||||
r = cpu->port_read(addr & 3);
|
||||
break;
|
||||
case 0xf8: //???
|
||||
case 0xf9: //??? -- Mapped to SPCRAM
|
||||
r = spcram[addr];
|
||||
break;
|
||||
case 0xfa: //T0TARGET
|
||||
case 0xfb: //T1TARGET
|
||||
case 0xfc: //T2TARGET -- write-only registers, always return 0x00
|
||||
r = 0x00;
|
||||
break;
|
||||
case 0xfd: //T0OUT -- 4-bit counter value
|
||||
r = t0.stage3_ticks & 15;
|
||||
t0.stage3_ticks = 0;
|
||||
break;
|
||||
case 0xfe: //T1OUT -- 4-bit counter value
|
||||
r = t1.stage3_ticks & 15;
|
||||
t1.stage3_ticks = 0;
|
||||
break;
|
||||
case 0xff: //T2OUT -- 4-bit counter value
|
||||
r = t2.stage3_ticks & 15;
|
||||
t2.stage3_ticks = 0;
|
||||
break;
|
||||
}
|
||||
} else if(addr < 0xffc0) {
|
||||
r = spcram[addr];
|
||||
} else {
|
||||
if(status.iplrom_enabled == true) {
|
||||
r = iplrom[addr & 0x3f];
|
||||
} else {
|
||||
r = spcram[addr];
|
||||
}
|
||||
}
|
||||
snes->notify(SNES::SPCRAM_READ, addr, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
void bAPU::spcram_write(uint16 addr, uint8 value) {
|
||||
if(addr >= 0x00f0 && addr <= 0x00ff) {
|
||||
switch(addr) {
|
||||
case 0xf0: //TEST -- operation unknown
|
||||
break;
|
||||
case 0xf1: //CONTROL
|
||||
status.iplrom_enabled = !!(value & 0x80);
|
||||
|
||||
//one-time clearing of APU port read registers,
|
||||
//emulated by simulating CPU writes of 0x00
|
||||
if(value & 0x20) {
|
||||
cpu->port_write(2, 0x00);
|
||||
cpu->port_write(3, 0x00);
|
||||
}
|
||||
if(value & 0x10) {
|
||||
cpu->port_write(0, 0x00);
|
||||
cpu->port_write(1, 0x00);
|
||||
}
|
||||
|
||||
//0->1 transistion resets timers
|
||||
if(t2.enabled == false && (value & 0x04)) {
|
||||
t2.stage2_ticks = 0;
|
||||
t2.stage3_ticks = 0;
|
||||
}
|
||||
t2.enabled = !!(value & 0x04);
|
||||
|
||||
if(t1.enabled == false && (value & 0x02)) {
|
||||
t1.stage2_ticks = 0;
|
||||
t1.stage3_ticks = 0;
|
||||
}
|
||||
t1.enabled = !!(value & 0x02);
|
||||
|
||||
if(t0.enabled == false && (value & 0x01)) {
|
||||
t0.stage2_ticks = 0;
|
||||
t0.stage3_ticks = 0;
|
||||
}
|
||||
t0.enabled = !!(value & 0x01);
|
||||
break;
|
||||
case 0xf2: //DSPADDR
|
||||
status.dsp_addr = value;
|
||||
break;
|
||||
case 0xf3: //DSPDATA
|
||||
//0x80-0xff is a read-only mirror of 0x00-0x7f
|
||||
if(status.dsp_addr < 0x80) {
|
||||
dsp->write(status.dsp_addr & 0x7f, value);
|
||||
}
|
||||
break;
|
||||
case 0xf4: //CPUIO0
|
||||
case 0xf5: //CPUIO1
|
||||
case 0xf6: //CPUIO2
|
||||
case 0xf7: //CPUIO3
|
||||
port_write(addr & 3, value);
|
||||
break;
|
||||
case 0xf8: //???
|
||||
case 0xf9: //??? - Mapped to SPCRAM
|
||||
spcram[addr] = value;
|
||||
break;
|
||||
case 0xfa: //T0TARGET
|
||||
t0.target = value;
|
||||
break;
|
||||
case 0xfb: //T1TARGET
|
||||
t1.target = value;
|
||||
break;
|
||||
case 0xfc: //T2TARGET
|
||||
t2.target = value;
|
||||
break;
|
||||
case 0xfd: //T0OUT
|
||||
case 0xfe: //T1OUT
|
||||
case 0xff: //T2OUT -- read-only registers
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
//writes to $ffc0-$ffff always go to spcram,
|
||||
//even if the iplrom is enabled.
|
||||
spcram[addr] = value;
|
||||
}
|
||||
snes->notify(SNES::SPCRAM_WRITE, addr, value);
|
||||
}
|
||||
|
||||
uint8 bAPU::port_read(uint8 port) {
|
||||
return spcram[0xf4 + (port & 3)];
|
||||
}
|
||||
|
||||
void bAPU::port_write(uint8 port, uint8 value) {
|
||||
spcram[0xf4 + (port & 0x03)] = value;
|
||||
}
|
||||
|
||||
void bAPU::add_cycles(int cycles) {
|
||||
status.cycles_executed += cycles;
|
||||
|
||||
t0.add_cycles(cycles);
|
||||
t1.add_cycles(cycles);
|
||||
t2.add_cycles(cycles);
|
||||
}
|
||||
|
||||
uint32 bAPU::cycles_executed() {
|
||||
uint32 r = status.cycles_executed;
|
||||
status.cycles_executed = 0;
|
||||
return (r << 4) + (r << 3);
|
||||
}
|
||||
|
||||
uint8 bAPU::op_read() {
|
||||
uint8 r;
|
||||
r = spcram_read(regs.pc);
|
||||
regs.pc++;
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8 bAPU::op_read(uint8 mode, uint16 addr) {
|
||||
uint8 r;
|
||||
switch(mode) {
|
||||
case OPMODE_ADDR:
|
||||
r = spcram_read(addr);
|
||||
break;
|
||||
case OPMODE_DP:
|
||||
r = spcram_read(((regs.p.p)?0x100:0x000) + (addr & 0xff));
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void bAPU::op_write(uint8 mode, uint16 addr, uint8 value) {
|
||||
switch(mode) {
|
||||
case OPMODE_ADDR:
|
||||
spcram_write(addr, value);
|
||||
break;
|
||||
case OPMODE_DP:
|
||||
spcram_write(((regs.p.p)?0x100:0x000) + (addr & 0xff), value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 bAPU::stack_read() {
|
||||
regs.sp++;
|
||||
return spcram_read(0x0100 | regs.sp);
|
||||
}
|
||||
|
||||
void bAPU::stack_write(uint8 value) {
|
||||
spcram_write(0x0100 | regs.sp, value);
|
||||
regs.sp--;
|
||||
}
|
||||
|
||||
uint8 *bAPU::get_spcram_handle() {
|
||||
if(!spcram) {
|
||||
alert("bAPU::get_spcram_handle() -- spcram uninitialized");
|
||||
}
|
||||
|
||||
return spcram;
|
||||
}
|
||||
|
||||
void bAPU::run() {
|
||||
exec_cycle();
|
||||
}
|
||||
|
||||
void bAPU::power() {
|
||||
memset(spcram, 0x00, 65536);
|
||||
reset();
|
||||
}
|
||||
|
||||
void bAPU::reset() {
|
||||
regs.pc = 0xffc0;
|
||||
regs.a = 0x00;
|
||||
regs.x = 0x00;
|
||||
regs.y = 0x00;
|
||||
regs.sp = 0xef;
|
||||
regs.p = 0x02;
|
||||
|
||||
status.cycle_pos = 0;
|
||||
status.cycles_executed = 0;
|
||||
|
||||
//$f1
|
||||
status.iplrom_enabled = true;
|
||||
|
||||
t0.enabled = false;
|
||||
t1.enabled = false;
|
||||
t2.enabled = false;
|
||||
|
||||
t0.stage1_ticks = 0;
|
||||
t1.stage1_ticks = 0;
|
||||
t2.stage1_ticks = 0;
|
||||
|
||||
t0.stage2_ticks = 0;
|
||||
t1.stage2_ticks = 0;
|
||||
t2.stage2_ticks = 0;
|
||||
|
||||
t0.stage3_ticks = 0;
|
||||
t1.stage3_ticks = 0;
|
||||
t2.stage3_ticks = 0;
|
||||
}
|
||||
|
||||
bAPU::bAPU() {
|
||||
init_op_table();
|
||||
|
||||
spcram = (uint8*)malloc(65536);
|
||||
|
||||
t0.cycle_frequency = 128; //1.024mhz / 8khz = 128
|
||||
t1.cycle_frequency = 128; //1.024mhz / 8khz = 128
|
||||
t2.cycle_frequency = 16; //1.024mhz / 64khz = 16
|
||||
|
||||
//targets not initialized/changed upon reset
|
||||
t0.target = 0;
|
||||
t1.target = 0;
|
||||
t2.target = 0;
|
||||
}
|
||||
|
||||
bAPU::~bAPU() {
|
||||
if(spcram)free(spcram);
|
||||
}
|
||||
|
||||
//cycles should never be greater than 12. since the minimum
|
||||
//cycle_frequency value is 16, we don't have to worry about
|
||||
//two ticks occuring in one call to this function.
|
||||
void bAPUTimer::add_cycles(int cycles) {
|
||||
//stage 1 increment
|
||||
stage1_ticks += cycles;
|
||||
if(stage1_ticks < cycle_frequency)return;
|
||||
|
||||
stage1_ticks -= cycle_frequency;
|
||||
if(enabled == false)return;
|
||||
|
||||
//stage 2 increment
|
||||
stage2_ticks++;
|
||||
|
||||
if(stage2_ticks != target)return;
|
||||
|
||||
//stage 3 increment
|
||||
stage2_ticks = 0;
|
||||
stage3_ticks++;
|
||||
stage3_ticks &= 15;
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
class bAPU;
|
||||
|
||||
class bAPUTimer {
|
||||
public:
|
||||
uint8 cycle_frequency, target;
|
||||
uint8 stage1_ticks, stage2_ticks, stage3_ticks;
|
||||
bool enabled;
|
||||
inline void add_cycles(int cycles);
|
||||
};
|
||||
|
||||
class bAPU : public APU {
|
||||
private:
|
||||
typedef void (bAPU::*op)();
|
||||
op optbl[256];
|
||||
|
||||
public:
|
||||
uint16 dp, sp, rd, wr, bit, ya;
|
||||
|
||||
struct {
|
||||
uint8 cycle_pos, opcode;
|
||||
uint32 cycles_executed;
|
||||
|
||||
//$f1
|
||||
bool iplrom_enabled;
|
||||
|
||||
//$f2
|
||||
uint8 dsp_addr;
|
||||
}status;
|
||||
|
||||
bAPUTimer t0, t1, t2;
|
||||
|
||||
uint8 *spcram;
|
||||
inline uint8 spcram_read (uint16 addr);
|
||||
inline void spcram_write(uint16 addr, uint8 value);
|
||||
inline uint8 port_read (uint8 port);
|
||||
inline void port_write(uint8 port, uint8 value);
|
||||
|
||||
inline uint8 *get_spcram_handle();
|
||||
inline void run();
|
||||
inline uint32 cycles_executed();
|
||||
inline void power();
|
||||
inline void reset();
|
||||
|
||||
inline void add_cycles(int cycles);
|
||||
|
||||
enum {
|
||||
OPMODE_ADDR = 0,
|
||||
OPMODE_DP = 1
|
||||
};
|
||||
inline uint8 op_read();
|
||||
inline uint8 op_read (uint8 mode, uint16 addr);
|
||||
inline void op_write(uint8 mode, uint16 addr, uint8 value);
|
||||
inline uint8 stack_read();
|
||||
inline void stack_write(uint8 value);
|
||||
|
||||
inline void exec_cycle();
|
||||
inline bool in_opcode();
|
||||
inline void init_op_table();
|
||||
|
||||
inline uint8 op_adc (uint8 x, uint8 y);
|
||||
inline uint16 op_addw(uint16 x, uint16 y);
|
||||
inline uint8 op_and (uint8 x, uint8 y);
|
||||
inline uint8 op_cmp (uint8 x, uint8 y);
|
||||
inline uint16 op_cmpw(uint16 x, uint16 y);
|
||||
inline uint8 op_eor (uint8 x, uint8 y);
|
||||
inline uint8 op_inc (uint8 x);
|
||||
inline uint16 op_incw(uint16 x);
|
||||
inline uint8 op_dec (uint8 x);
|
||||
inline uint16 op_decw(uint16 x);
|
||||
inline uint8 op_or (uint8 x, uint8 y);
|
||||
inline uint8 op_sbc (uint8 x, uint8 y);
|
||||
inline uint16 op_subw(uint16 x, uint16 y);
|
||||
inline uint8 op_asl (uint8 x);
|
||||
inline uint8 op_lsr (uint8 x);
|
||||
inline uint8 op_rol (uint8 x);
|
||||
inline uint8 op_ror (uint8 x);
|
||||
#include "bapu_op.h"
|
||||
|
||||
bAPU();
|
||||
~bAPU();
|
||||
};
|
||||
@@ -1,25 +0,0 @@
|
||||
void bAPU::exec_cycle() {
|
||||
uint8 op;
|
||||
if(status.cycle_pos == 0) {
|
||||
op = spcram_read(regs.pc);
|
||||
snes->notify(SNES::APU_EXEC_OPCODE_BEGIN);
|
||||
status.opcode = op_read();
|
||||
status.cycle_pos = 1;
|
||||
add_cycles(1);
|
||||
} else {
|
||||
(this->*optbl[status.opcode])();
|
||||
add_cycles(1);
|
||||
if(status.cycle_pos == 0) {
|
||||
snes->notify(SNES::APU_EXEC_OPCODE_END);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//only return true when we are on an opcode edge
|
||||
bool bAPU::in_opcode() {
|
||||
return (status.cycle_pos != 0);
|
||||
}
|
||||
|
||||
void bAPU::init_op_table() {
|
||||
#include "bapu_optable.cpp"
|
||||
}
|
||||
@@ -1,256 +0,0 @@
|
||||
void op_mov_a_x();
|
||||
void op_mov_a_y();
|
||||
void op_mov_x_a();
|
||||
void op_mov_y_a();
|
||||
void op_mov_x_sp();
|
||||
void op_mov_sp_x();
|
||||
void op_mov_a_const();
|
||||
void op_mov_x_const();
|
||||
void op_mov_y_const();
|
||||
void op_mov_a_ix();
|
||||
void op_mov_a_ixinc();
|
||||
void op_mov_a_dp();
|
||||
void op_mov_x_dp();
|
||||
void op_mov_y_dp();
|
||||
void op_mov_a_dpx();
|
||||
void op_mov_x_dpy();
|
||||
void op_mov_y_dpx();
|
||||
void op_mov_a_addr();
|
||||
void op_mov_x_addr();
|
||||
void op_mov_y_addr();
|
||||
void op_mov_a_addrx();
|
||||
void op_mov_a_addry();
|
||||
void op_mov_a_idpx();
|
||||
void op_mov_a_idpy();
|
||||
void op_mov_dp_dp();
|
||||
void op_mov_dp_const();
|
||||
void op_mov_ix_a();
|
||||
void op_mov_ixinc_a();
|
||||
void op_mov_dp_a();
|
||||
void op_mov_dp_x();
|
||||
void op_mov_dp_y();
|
||||
void op_mov_dpx_a();
|
||||
void op_mov_dpy_x();
|
||||
void op_mov_dpx_y();
|
||||
void op_mov_addr_a();
|
||||
void op_mov_addr_x();
|
||||
void op_mov_addr_y();
|
||||
void op_mov_addrx_a();
|
||||
void op_mov_addry_a();
|
||||
void op_mov_idpx_a();
|
||||
void op_mov_idpy_a();
|
||||
void op_movw_ya_dp();
|
||||
void op_movw_dp_ya();
|
||||
void op_mov1_c_bit();
|
||||
void op_mov1_bit_c();
|
||||
void op_bra();
|
||||
void op_beq();
|
||||
void op_bne();
|
||||
void op_bcs();
|
||||
void op_bcc();
|
||||
void op_bvs();
|
||||
void op_bvc();
|
||||
void op_bmi();
|
||||
void op_bpl();
|
||||
void op_bbs0();
|
||||
void op_bbc0();
|
||||
void op_bbs1();
|
||||
void op_bbc1();
|
||||
void op_bbs2();
|
||||
void op_bbc2();
|
||||
void op_bbs3();
|
||||
void op_bbc3();
|
||||
void op_bbs4();
|
||||
void op_bbc4();
|
||||
void op_bbs5();
|
||||
void op_bbc5();
|
||||
void op_bbs6();
|
||||
void op_bbc6();
|
||||
void op_bbs7();
|
||||
void op_bbc7();
|
||||
void op_cbne_dp();
|
||||
void op_cbne_dpx();
|
||||
void op_dbnz_dp();
|
||||
void op_dbnz_y();
|
||||
void op_jmp_addr();
|
||||
void op_jmp_iaddrx();
|
||||
void op_call();
|
||||
void op_pcall();
|
||||
void op_tcall_0();
|
||||
void op_tcall_1();
|
||||
void op_tcall_2();
|
||||
void op_tcall_3();
|
||||
void op_tcall_4();
|
||||
void op_tcall_5();
|
||||
void op_tcall_6();
|
||||
void op_tcall_7();
|
||||
void op_tcall_8();
|
||||
void op_tcall_9();
|
||||
void op_tcall_10();
|
||||
void op_tcall_11();
|
||||
void op_tcall_12();
|
||||
void op_tcall_13();
|
||||
void op_tcall_14();
|
||||
void op_tcall_15();
|
||||
void op_brk();
|
||||
void op_ret();
|
||||
void op_reti();
|
||||
void op_adc_a_const();
|
||||
void op_and_a_const();
|
||||
void op_cmp_a_const();
|
||||
void op_cmp_x_const();
|
||||
void op_cmp_y_const();
|
||||
void op_eor_a_const();
|
||||
void op_or_a_const();
|
||||
void op_sbc_a_const();
|
||||
void op_adc_a_ix();
|
||||
void op_and_a_ix();
|
||||
void op_cmp_a_ix();
|
||||
void op_eor_a_ix();
|
||||
void op_or_a_ix();
|
||||
void op_sbc_a_ix();
|
||||
void op_adc_a_dp();
|
||||
void op_and_a_dp();
|
||||
void op_cmp_a_dp();
|
||||
void op_cmp_x_dp();
|
||||
void op_cmp_y_dp();
|
||||
void op_eor_a_dp();
|
||||
void op_or_a_dp();
|
||||
void op_sbc_a_dp();
|
||||
void op_adc_a_dpx();
|
||||
void op_and_a_dpx();
|
||||
void op_cmp_a_dpx();
|
||||
void op_eor_a_dpx();
|
||||
void op_or_a_dpx();
|
||||
void op_sbc_a_dpx();
|
||||
void op_adc_a_addr();
|
||||
void op_and_a_addr();
|
||||
void op_cmp_a_addr();
|
||||
void op_cmp_x_addr();
|
||||
void op_cmp_y_addr();
|
||||
void op_eor_a_addr();
|
||||
void op_or_a_addr();
|
||||
void op_sbc_a_addr();
|
||||
void op_adc_a_addrx();
|
||||
void op_adc_a_addry();
|
||||
void op_and_a_addrx();
|
||||
void op_and_a_addry();
|
||||
void op_cmp_a_addrx();
|
||||
void op_cmp_a_addry();
|
||||
void op_eor_a_addrx();
|
||||
void op_eor_a_addry();
|
||||
void op_or_a_addrx();
|
||||
void op_or_a_addry();
|
||||
void op_sbc_a_addrx();
|
||||
void op_sbc_a_addry();
|
||||
void op_adc_a_idpx();
|
||||
void op_and_a_idpx();
|
||||
void op_cmp_a_idpx();
|
||||
void op_eor_a_idpx();
|
||||
void op_or_a_idpx();
|
||||
void op_sbc_a_idpx();
|
||||
void op_adc_a_idpy();
|
||||
void op_and_a_idpy();
|
||||
void op_cmp_a_idpy();
|
||||
void op_eor_a_idpy();
|
||||
void op_or_a_idpy();
|
||||
void op_sbc_a_idpy();
|
||||
void op_adc_ix_iy();
|
||||
void op_and_ix_iy();
|
||||
void op_cmp_ix_iy();
|
||||
void op_eor_ix_iy();
|
||||
void op_or_ix_iy();
|
||||
void op_sbc_ix_iy();
|
||||
void op_adc_dp_dp();
|
||||
void op_and_dp_dp();
|
||||
void op_cmp_dp_dp();
|
||||
void op_eor_dp_dp();
|
||||
void op_or_dp_dp();
|
||||
void op_sbc_dp_dp();
|
||||
void op_adc_dp_const();
|
||||
void op_and_dp_const();
|
||||
void op_cmp_dp_const();
|
||||
void op_eor_dp_const();
|
||||
void op_or_dp_const();
|
||||
void op_sbc_dp_const();
|
||||
void op_addw_ya_dp();
|
||||
void op_cmpw_ya_dp();
|
||||
void op_subw_ya_dp();
|
||||
void op_and1_bit();
|
||||
void op_and1_notbit();
|
||||
void op_eor1_bit();
|
||||
void op_not1_bit();
|
||||
void op_or1_bit();
|
||||
void op_or1_notbit();
|
||||
void op_inc_a();
|
||||
void op_inc_x();
|
||||
void op_inc_y();
|
||||
void op_dec_a();
|
||||
void op_dec_x();
|
||||
void op_dec_y();
|
||||
void op_asl_a();
|
||||
void op_lsr_a();
|
||||
void op_rol_a();
|
||||
void op_ror_a();
|
||||
void op_inc_dp();
|
||||
void op_dec_dp();
|
||||
void op_asl_dp();
|
||||
void op_lsr_dp();
|
||||
void op_rol_dp();
|
||||
void op_ror_dp();
|
||||
void op_inc_dpx();
|
||||
void op_dec_dpx();
|
||||
void op_asl_dpx();
|
||||
void op_lsr_dpx();
|
||||
void op_rol_dpx();
|
||||
void op_ror_dpx();
|
||||
void op_inc_addr();
|
||||
void op_dec_addr();
|
||||
void op_asl_addr();
|
||||
void op_lsr_addr();
|
||||
void op_rol_addr();
|
||||
void op_ror_addr();
|
||||
void op_incw_dp();
|
||||
void op_decw_dp();
|
||||
void op_nop();
|
||||
void op_sleep();
|
||||
void op_stop();
|
||||
void op_xcn();
|
||||
void op_daa();
|
||||
void op_das();
|
||||
void op_clrc();
|
||||
void op_clrp();
|
||||
void op_setc();
|
||||
void op_setp();
|
||||
void op_clrv();
|
||||
void op_notc();
|
||||
void op_ei();
|
||||
void op_di();
|
||||
void op_set0_dp();
|
||||
void op_clr0_dp();
|
||||
void op_set1_dp();
|
||||
void op_clr1_dp();
|
||||
void op_set2_dp();
|
||||
void op_clr2_dp();
|
||||
void op_set3_dp();
|
||||
void op_clr3_dp();
|
||||
void op_set4_dp();
|
||||
void op_clr4_dp();
|
||||
void op_set5_dp();
|
||||
void op_clr5_dp();
|
||||
void op_set6_dp();
|
||||
void op_clr6_dp();
|
||||
void op_set7_dp();
|
||||
void op_clr7_dp();
|
||||
void op_tset_addr_a();
|
||||
void op_tclr_addr_a();
|
||||
void op_push_a();
|
||||
void op_push_x();
|
||||
void op_push_y();
|
||||
void op_push_p();
|
||||
void op_pop_a();
|
||||
void op_pop_x();
|
||||
void op_pop_y();
|
||||
void op_pop_p();
|
||||
void op_mul_ya();
|
||||
void op_div_ya_x();
|
||||
@@ -1,140 +0,0 @@
|
||||
uint8 bAPU::op_adc(uint8 x, uint8 y) {
|
||||
int16 r = x + y + regs.p.c;
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.v = !!(~(x ^ y) & (y ^ (uint8)r) & 0x80);
|
||||
regs.p.h = !!((x ^ y ^ (uint8)r) & 0x10);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r > 0xff);
|
||||
return r;
|
||||
}
|
||||
|
||||
uint16 bAPU::op_addw(uint16 x, uint16 y) {
|
||||
int32 r = x + y;
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.v = !!(~(x ^ y) & (y ^ (uint16)r) & 0x8000);
|
||||
regs.p.h = !!((x ^ y ^ (uint16)r) & 0x10);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r > 0xffff);
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8 bAPU::op_and(uint8 x, uint8 y) {
|
||||
x &= y;
|
||||
regs.p.n = !!(x & 0x80);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 bAPU::op_cmp(uint8 x, uint8 y) {
|
||||
int16 r = x - y;
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint16 bAPU::op_cmpw(uint16 x, uint16 y) {
|
||||
int32 r = x - y;
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 bAPU::op_eor(uint8 x, uint8 y) {
|
||||
x ^= y;
|
||||
regs.p.n = !!(x & 0x80);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 bAPU::op_or(uint8 x, uint8 y) {
|
||||
x |= y;
|
||||
regs.p.n = !!(x & 0x80);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 bAPU::op_sbc(uint8 x, uint8 y) {
|
||||
int16 r = x - y - !regs.p.c;
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.v = !!((x ^ y) & (x ^ (uint8)r) & 0x80);
|
||||
regs.p.h = !((x ^ y ^ (uint8)r) & 0x10);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
uint16 bAPU::op_subw(uint16 x, uint16 y) {
|
||||
int32 r = x - y;
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.v = !!((x ^ y) & (x ^ (uint16)r) & 0x8000);
|
||||
regs.p.h = !((x ^ y ^ (uint16)r) & 0x10);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8 bAPU::op_inc(uint8 x) {
|
||||
x++;
|
||||
regs.p.n = !!(x & 0x80);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint16 bAPU::op_incw(uint16 x) {
|
||||
x++;
|
||||
regs.p.n = !!(x & 0x8000);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 bAPU::op_dec(uint8 x) {
|
||||
x--;
|
||||
regs.p.n = !!(x & 0x80);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint16 bAPU::op_decw(uint16 x) {
|
||||
x--;
|
||||
regs.p.n = !!(x & 0x8000);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 bAPU::op_asl(uint8 x) {
|
||||
regs.p.c = !!(x & 0x80);
|
||||
x <<= 1;
|
||||
regs.p.n = !!(x & 0x80);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 bAPU::op_lsr(uint8 x) {
|
||||
regs.p.c = !!(x & 0x01);
|
||||
x >>= 1;
|
||||
regs.p.n = !!(x & 0x80);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 bAPU::op_rol(uint8 x) {
|
||||
uint8 c = regs.p.c;
|
||||
regs.p.c = !!(x & 0x80);
|
||||
x <<= 1;
|
||||
x |= c;
|
||||
regs.p.n = !!(x & 0x80);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 bAPU::op_ror(uint8 x) {
|
||||
uint8 c = (regs.p.c)?0x80:0x00;
|
||||
regs.p.c = !!(x & 0x01);
|
||||
x >>= 1;
|
||||
x |= c;
|
||||
regs.p.n = !!(x & 0x80);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
@@ -1,643 +0,0 @@
|
||||
void bAPU::op_nop() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_sleep() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
regs.pc--;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_stop() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
regs.pc--;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_xcn() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
regs.a = (regs.a >> 4) | (regs.a << 4);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_daa() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
if(regs.p.c || (regs.a) > 0x99) {
|
||||
regs.a += 0x60;
|
||||
regs.p.c = 1;
|
||||
}
|
||||
if(regs.p.h || (regs.a & 15) > 0x09) {
|
||||
regs.a += 0x06;
|
||||
}
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_das() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
if(!regs.p.c || (regs.a) > 0x99) {
|
||||
regs.a -= 0x60;
|
||||
regs.p.c = 0;
|
||||
}
|
||||
if(!regs.p.h || (regs.a & 15) > 0x09) {
|
||||
regs.a -= 0x06;
|
||||
}
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clrc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.p.c = 0;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clrp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.p.p = 0;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_setc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.p.c = 1;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_setp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.p.p = 1;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clrv() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.p.v = 0;
|
||||
regs.p.h = 0;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_notc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
regs.p.c ^= 1;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_ei() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
regs.p.i = 1;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_di() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
regs.p.i = 0;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_set0_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd |= 0x01;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clr0_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd &= ~0x01;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_set1_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd |= 0x02;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clr1_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd &= ~0x02;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_set2_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd |= 0x04;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clr2_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd &= ~0x04;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_set3_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd |= 0x08;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clr3_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd &= ~0x08;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_set4_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd |= 0x10;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clr4_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd &= ~0x10;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_set5_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd |= 0x20;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clr5_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd &= ~0x20;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_set6_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd |= 0x40;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clr6_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd &= ~0x40;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_set7_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd |= 0x80;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clr7_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd &= ~0x80;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_tset_addr_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
break;
|
||||
case 4:
|
||||
regs.p.n = !!((rd & regs.a) & 0x80);
|
||||
regs.p.z = ((rd & regs.a) == 0);
|
||||
rd |= regs.a;
|
||||
break;
|
||||
case 5:
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_tclr_addr_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
break;
|
||||
case 4:
|
||||
regs.p.n = !!((rd & regs.a) & 0x80);
|
||||
regs.p.z = ((rd & regs.a) == 0);
|
||||
rd &=~ regs.a;
|
||||
break;
|
||||
case 5:
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_push_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
stack_write(regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_push_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
stack_write(regs.x);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_push_y() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
stack_write(regs.y);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_push_p() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
stack_write(regs.p);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_pop_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
regs.a = stack_read();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_pop_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
regs.x = stack_read();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_pop_y() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
regs.y = stack_read();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_pop_p() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
regs.p = stack_read();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mul_ya() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
case 5:
|
||||
break;
|
||||
case 6:
|
||||
break;
|
||||
case 7:
|
||||
break;
|
||||
case 8:
|
||||
ya = regs.y * regs.a;
|
||||
regs.a = ya;
|
||||
regs.y = ya >> 8;
|
||||
//result is set based on y (high-byte) only
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_div_ya_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
case 5:
|
||||
break;
|
||||
case 6:
|
||||
break;
|
||||
case 7:
|
||||
break;
|
||||
case 8:
|
||||
break;
|
||||
case 9:
|
||||
break;
|
||||
case 10:
|
||||
break;
|
||||
case 11:
|
||||
ya = regs.ya;
|
||||
//overflow set if quotient >= 256
|
||||
regs.p.v = !!(regs.y >= regs.x);
|
||||
regs.p.h = !!((regs.y & 15) >= (regs.x & 15));
|
||||
if(regs.y < (regs.x << 1)) {
|
||||
//if quotient is <= 511 (will fit into 9-bit result)
|
||||
regs.a = ya / regs.x;
|
||||
regs.y = ya % regs.x;
|
||||
} else {
|
||||
//otherwise, the quotient won't fit into regs.p.v + regs.a
|
||||
//this emulates the odd behavior of the SPC700 in this case
|
||||
regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x);
|
||||
regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x);
|
||||
}
|
||||
//result is set based on a (quotient) only
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,710 +0,0 @@
|
||||
void bAPU::op_mov_a_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.a = regs.x;
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_y() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.a = regs.y;
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_x_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.x = regs.a;
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_y_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.y = regs.a;
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_x_sp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.x = regs.sp;
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_sp_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.sp = regs.x;
|
||||
regs.p.n = !!(regs.sp & 0x80);
|
||||
regs.p.z = (regs.sp == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_const() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.a = op_read();
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_x_const() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.x = op_read();
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_y_const() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.y = op_read();
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_ix() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
regs.a = op_read(OPMODE_DP, regs.x);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_ixinc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
regs.a = op_read(OPMODE_DP, regs.x++);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
regs.a = op_read(OPMODE_DP, sp);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_x_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
regs.x = op_read(OPMODE_DP, sp);
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_y_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
regs.y = op_read(OPMODE_DP, sp);
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
regs.a = op_read(OPMODE_DP, sp + regs.x);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_x_dpy() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
regs.x = op_read(OPMODE_DP, sp + regs.y);
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_y_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
regs.y = op_read(OPMODE_DP, sp + regs.x);
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
sp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
regs.a = op_read(OPMODE_ADDR, sp);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_x_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
sp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
regs.x = op_read(OPMODE_ADDR, sp);
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_y_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
sp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
regs.y = op_read(OPMODE_ADDR, sp);
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_addrx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
sp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
regs.a = op_read(OPMODE_ADDR, sp + regs.x);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_addry() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
sp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
regs.a = op_read(OPMODE_ADDR, sp + regs.y);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_idpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read() + regs.x;
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
sp = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 4:
|
||||
sp |= op_read(OPMODE_DP, dp + 1) << 8;
|
||||
break;
|
||||
case 5:
|
||||
regs.a = op_read(OPMODE_ADDR, sp);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_idpy() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
sp = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 4:
|
||||
sp |= op_read(OPMODE_DP, dp + 1) << 8;
|
||||
break;
|
||||
case 5:
|
||||
regs.a = op_read(OPMODE_ADDR, sp + regs.y);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_dp_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 3:
|
||||
rd = op_read(OPMODE_DP, sp);
|
||||
break;
|
||||
case 4:
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_dp_const() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
rd = op_read();
|
||||
break;
|
||||
case 2:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_ix_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
op_write(OPMODE_DP, regs.x, regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_ixinc_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
op_write(OPMODE_DP, regs.x++, regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_dp_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
op_write(OPMODE_DP, dp, regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_dp_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
op_write(OPMODE_DP, dp, regs.x);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_dp_y() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
op_write(OPMODE_DP, dp, regs.y);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_dpx_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
op_write(OPMODE_DP, dp + regs.x, regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_dpy_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
op_write(OPMODE_DP, dp + regs.y, regs.x);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_dpx_y() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
op_write(OPMODE_DP, dp + regs.x, regs.y);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_addr_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
op_write(OPMODE_ADDR, dp, regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_addr_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
op_write(OPMODE_ADDR, dp, regs.x);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_addr_y() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
op_write(OPMODE_ADDR, dp, regs.y);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_addrx_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
case 5:
|
||||
op_write(OPMODE_ADDR, dp + regs.x, regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_addry_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
case 5:
|
||||
op_write(OPMODE_ADDR, dp + regs.y, regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_idpx_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
sp = op_read() + regs.x;
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
dp = op_read(OPMODE_DP, sp);
|
||||
break;
|
||||
case 4:
|
||||
dp |= op_read(OPMODE_DP, sp + 1) << 8;
|
||||
break;
|
||||
case 5:
|
||||
break;
|
||||
case 6:
|
||||
op_write(OPMODE_ADDR, dp, regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_idpy_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
dp = op_read(OPMODE_DP, sp);
|
||||
break;
|
||||
case 4:
|
||||
dp |= op_read(OPMODE_DP, sp + 1) << 8;
|
||||
break;
|
||||
case 5:
|
||||
break;
|
||||
case 6:
|
||||
op_write(OPMODE_ADDR, dp + regs.y, regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_movw_ya_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
regs.a = op_read(OPMODE_DP, sp);
|
||||
break;
|
||||
case 4:
|
||||
regs.y = op_read(OPMODE_DP, sp + 1);
|
||||
regs.p.n = !!(regs.ya & 0x8000);
|
||||
regs.p.z = (regs.ya == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_movw_dp_ya() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
op_write(OPMODE_DP, dp, regs.a);
|
||||
break;
|
||||
case 4:
|
||||
op_write(OPMODE_DP, dp + 1, regs.y);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov1_c_bit() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
sp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
bit = sp >> 13;
|
||||
sp &= 0x1fff;
|
||||
rd = op_read(OPMODE_ADDR, sp);
|
||||
regs.p.c = !!(rd & (1 << bit));
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov1_bit_c() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
if(regs.p.c)rd |= (1 << bit);
|
||||
else rd &= ~(1 << bit);
|
||||
break;
|
||||
case 4:
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,452 +0,0 @@
|
||||
void bAPU::op_inc_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.a = op_inc(regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_inc_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.x = op_inc(regs.x);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_inc_y() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.y = op_inc(regs.y);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_dec_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.a = op_dec(regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_dec_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.x = op_dec(regs.x);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_dec_y() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.y = op_dec(regs.y);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_asl_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.a = op_asl(regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_lsr_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.a = op_lsr(regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_rol_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.a = op_rol(regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_ror_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
regs.a = op_ror(regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_inc_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd = op_inc(rd);
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_dec_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd = op_dec(rd);
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_asl_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd = op_asl(rd);
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_lsr_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd = op_lsr(rd);
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_rol_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd = op_rol(rd);
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_ror_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd = op_ror(rd);
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_inc_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
rd = op_read(OPMODE_DP, dp + regs.x);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_inc(rd);
|
||||
op_write(OPMODE_DP, dp + regs.x, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_dec_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
rd = op_read(OPMODE_DP, dp + regs.x);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_dec(rd);
|
||||
op_write(OPMODE_DP, dp + regs.x, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_asl_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
rd = op_read(OPMODE_DP, dp + regs.x);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_asl(rd);
|
||||
op_write(OPMODE_DP, dp + regs.x, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_lsr_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
rd = op_read(OPMODE_DP, dp + regs.x);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_lsr(rd);
|
||||
op_write(OPMODE_DP, dp + regs.x, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_rol_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
rd = op_read(OPMODE_DP, dp + regs.x);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_rol(rd);
|
||||
op_write(OPMODE_DP, dp + regs.x, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_ror_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
rd = op_read(OPMODE_DP, dp + regs.x);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_ror(rd);
|
||||
op_write(OPMODE_DP, dp + regs.x, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_inc_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_inc(rd);
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_dec_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_dec(rd);
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_asl_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_asl(rd);
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_lsr_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_lsr(rd);
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_rol_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_rol(rd);
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_ror_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
break;
|
||||
case 4:
|
||||
rd = op_ror(rd);
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_incw_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd |= op_read(OPMODE_DP, dp + 1) << 8;
|
||||
break;
|
||||
case 4:
|
||||
rd = op_incw(rd);
|
||||
op_write(OPMODE_DP, dp + 1, rd >> 8);
|
||||
break;
|
||||
case 5:
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_decw_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
rd |= op_read(OPMODE_DP, dp + 1) << 8;
|
||||
break;
|
||||
case 4:
|
||||
rd = op_decw(rd);
|
||||
op_write(OPMODE_DP, dp + 1, rd >> 8);
|
||||
break;
|
||||
case 5:
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,256 +0,0 @@
|
||||
optbl[0x7d] = &bAPU::op_mov_a_x;
|
||||
optbl[0xdd] = &bAPU::op_mov_a_y;
|
||||
optbl[0x5d] = &bAPU::op_mov_x_a;
|
||||
optbl[0xfd] = &bAPU::op_mov_y_a;
|
||||
optbl[0x9d] = &bAPU::op_mov_x_sp;
|
||||
optbl[0xbd] = &bAPU::op_mov_sp_x;
|
||||
optbl[0xe8] = &bAPU::op_mov_a_const;
|
||||
optbl[0xcd] = &bAPU::op_mov_x_const;
|
||||
optbl[0x8d] = &bAPU::op_mov_y_const;
|
||||
optbl[0xe6] = &bAPU::op_mov_a_ix;
|
||||
optbl[0xbf] = &bAPU::op_mov_a_ixinc;
|
||||
optbl[0xe4] = &bAPU::op_mov_a_dp;
|
||||
optbl[0xf8] = &bAPU::op_mov_x_dp;
|
||||
optbl[0xeb] = &bAPU::op_mov_y_dp;
|
||||
optbl[0xf4] = &bAPU::op_mov_a_dpx;
|
||||
optbl[0xf9] = &bAPU::op_mov_x_dpy;
|
||||
optbl[0xfb] = &bAPU::op_mov_y_dpx;
|
||||
optbl[0xe5] = &bAPU::op_mov_a_addr;
|
||||
optbl[0xe9] = &bAPU::op_mov_x_addr;
|
||||
optbl[0xec] = &bAPU::op_mov_y_addr;
|
||||
optbl[0xf5] = &bAPU::op_mov_a_addrx;
|
||||
optbl[0xf6] = &bAPU::op_mov_a_addry;
|
||||
optbl[0xe7] = &bAPU::op_mov_a_idpx;
|
||||
optbl[0xf7] = &bAPU::op_mov_a_idpy;
|
||||
optbl[0xfa] = &bAPU::op_mov_dp_dp;
|
||||
optbl[0x8f] = &bAPU::op_mov_dp_const;
|
||||
optbl[0xc6] = &bAPU::op_mov_ix_a;
|
||||
optbl[0xaf] = &bAPU::op_mov_ixinc_a;
|
||||
optbl[0xc4] = &bAPU::op_mov_dp_a;
|
||||
optbl[0xd8] = &bAPU::op_mov_dp_x;
|
||||
optbl[0xcb] = &bAPU::op_mov_dp_y;
|
||||
optbl[0xd4] = &bAPU::op_mov_dpx_a;
|
||||
optbl[0xd9] = &bAPU::op_mov_dpy_x;
|
||||
optbl[0xdb] = &bAPU::op_mov_dpx_y;
|
||||
optbl[0xc5] = &bAPU::op_mov_addr_a;
|
||||
optbl[0xc9] = &bAPU::op_mov_addr_x;
|
||||
optbl[0xcc] = &bAPU::op_mov_addr_y;
|
||||
optbl[0xd5] = &bAPU::op_mov_addrx_a;
|
||||
optbl[0xd6] = &bAPU::op_mov_addry_a;
|
||||
optbl[0xc7] = &bAPU::op_mov_idpx_a;
|
||||
optbl[0xd7] = &bAPU::op_mov_idpy_a;
|
||||
optbl[0xba] = &bAPU::op_movw_ya_dp;
|
||||
optbl[0xda] = &bAPU::op_movw_dp_ya;
|
||||
optbl[0xaa] = &bAPU::op_mov1_c_bit;
|
||||
optbl[0xca] = &bAPU::op_mov1_bit_c;
|
||||
optbl[0x2f] = &bAPU::op_bra;
|
||||
optbl[0xf0] = &bAPU::op_beq;
|
||||
optbl[0xd0] = &bAPU::op_bne;
|
||||
optbl[0xb0] = &bAPU::op_bcs;
|
||||
optbl[0x90] = &bAPU::op_bcc;
|
||||
optbl[0x70] = &bAPU::op_bvs;
|
||||
optbl[0x50] = &bAPU::op_bvc;
|
||||
optbl[0x30] = &bAPU::op_bmi;
|
||||
optbl[0x10] = &bAPU::op_bpl;
|
||||
optbl[0x03] = &bAPU::op_bbs0;
|
||||
optbl[0x13] = &bAPU::op_bbc0;
|
||||
optbl[0x23] = &bAPU::op_bbs1;
|
||||
optbl[0x33] = &bAPU::op_bbc1;
|
||||
optbl[0x43] = &bAPU::op_bbs2;
|
||||
optbl[0x53] = &bAPU::op_bbc2;
|
||||
optbl[0x63] = &bAPU::op_bbs3;
|
||||
optbl[0x73] = &bAPU::op_bbc3;
|
||||
optbl[0x83] = &bAPU::op_bbs4;
|
||||
optbl[0x93] = &bAPU::op_bbc4;
|
||||
optbl[0xa3] = &bAPU::op_bbs5;
|
||||
optbl[0xb3] = &bAPU::op_bbc5;
|
||||
optbl[0xc3] = &bAPU::op_bbs6;
|
||||
optbl[0xd3] = &bAPU::op_bbc6;
|
||||
optbl[0xe3] = &bAPU::op_bbs7;
|
||||
optbl[0xf3] = &bAPU::op_bbc7;
|
||||
optbl[0x2e] = &bAPU::op_cbne_dp;
|
||||
optbl[0xde] = &bAPU::op_cbne_dpx;
|
||||
optbl[0x6e] = &bAPU::op_dbnz_dp;
|
||||
optbl[0xfe] = &bAPU::op_dbnz_y;
|
||||
optbl[0x5f] = &bAPU::op_jmp_addr;
|
||||
optbl[0x1f] = &bAPU::op_jmp_iaddrx;
|
||||
optbl[0x3f] = &bAPU::op_call;
|
||||
optbl[0x4f] = &bAPU::op_pcall;
|
||||
optbl[0x01] = &bAPU::op_tcall_0;
|
||||
optbl[0x11] = &bAPU::op_tcall_1;
|
||||
optbl[0x21] = &bAPU::op_tcall_2;
|
||||
optbl[0x31] = &bAPU::op_tcall_3;
|
||||
optbl[0x41] = &bAPU::op_tcall_4;
|
||||
optbl[0x51] = &bAPU::op_tcall_5;
|
||||
optbl[0x61] = &bAPU::op_tcall_6;
|
||||
optbl[0x71] = &bAPU::op_tcall_7;
|
||||
optbl[0x81] = &bAPU::op_tcall_8;
|
||||
optbl[0x91] = &bAPU::op_tcall_9;
|
||||
optbl[0xa1] = &bAPU::op_tcall_10;
|
||||
optbl[0xb1] = &bAPU::op_tcall_11;
|
||||
optbl[0xc1] = &bAPU::op_tcall_12;
|
||||
optbl[0xd1] = &bAPU::op_tcall_13;
|
||||
optbl[0xe1] = &bAPU::op_tcall_14;
|
||||
optbl[0xf1] = &bAPU::op_tcall_15;
|
||||
optbl[0x0f] = &bAPU::op_brk;
|
||||
optbl[0x6f] = &bAPU::op_ret;
|
||||
optbl[0x7f] = &bAPU::op_reti;
|
||||
optbl[0x88] = &bAPU::op_adc_a_const;
|
||||
optbl[0x28] = &bAPU::op_and_a_const;
|
||||
optbl[0x68] = &bAPU::op_cmp_a_const;
|
||||
optbl[0xc8] = &bAPU::op_cmp_x_const;
|
||||
optbl[0xad] = &bAPU::op_cmp_y_const;
|
||||
optbl[0x48] = &bAPU::op_eor_a_const;
|
||||
optbl[0x08] = &bAPU::op_or_a_const;
|
||||
optbl[0xa8] = &bAPU::op_sbc_a_const;
|
||||
optbl[0x86] = &bAPU::op_adc_a_ix;
|
||||
optbl[0x26] = &bAPU::op_and_a_ix;
|
||||
optbl[0x66] = &bAPU::op_cmp_a_ix;
|
||||
optbl[0x46] = &bAPU::op_eor_a_ix;
|
||||
optbl[0x06] = &bAPU::op_or_a_ix;
|
||||
optbl[0xa6] = &bAPU::op_sbc_a_ix;
|
||||
optbl[0x84] = &bAPU::op_adc_a_dp;
|
||||
optbl[0x24] = &bAPU::op_and_a_dp;
|
||||
optbl[0x64] = &bAPU::op_cmp_a_dp;
|
||||
optbl[0x3e] = &bAPU::op_cmp_x_dp;
|
||||
optbl[0x7e] = &bAPU::op_cmp_y_dp;
|
||||
optbl[0x44] = &bAPU::op_eor_a_dp;
|
||||
optbl[0x04] = &bAPU::op_or_a_dp;
|
||||
optbl[0xa4] = &bAPU::op_sbc_a_dp;
|
||||
optbl[0x94] = &bAPU::op_adc_a_dpx;
|
||||
optbl[0x34] = &bAPU::op_and_a_dpx;
|
||||
optbl[0x74] = &bAPU::op_cmp_a_dpx;
|
||||
optbl[0x54] = &bAPU::op_eor_a_dpx;
|
||||
optbl[0x14] = &bAPU::op_or_a_dpx;
|
||||
optbl[0xb4] = &bAPU::op_sbc_a_dpx;
|
||||
optbl[0x85] = &bAPU::op_adc_a_addr;
|
||||
optbl[0x25] = &bAPU::op_and_a_addr;
|
||||
optbl[0x65] = &bAPU::op_cmp_a_addr;
|
||||
optbl[0x1e] = &bAPU::op_cmp_x_addr;
|
||||
optbl[0x5e] = &bAPU::op_cmp_y_addr;
|
||||
optbl[0x45] = &bAPU::op_eor_a_addr;
|
||||
optbl[0x05] = &bAPU::op_or_a_addr;
|
||||
optbl[0xa5] = &bAPU::op_sbc_a_addr;
|
||||
optbl[0x95] = &bAPU::op_adc_a_addrx;
|
||||
optbl[0x96] = &bAPU::op_adc_a_addry;
|
||||
optbl[0x35] = &bAPU::op_and_a_addrx;
|
||||
optbl[0x36] = &bAPU::op_and_a_addry;
|
||||
optbl[0x75] = &bAPU::op_cmp_a_addrx;
|
||||
optbl[0x76] = &bAPU::op_cmp_a_addry;
|
||||
optbl[0x55] = &bAPU::op_eor_a_addrx;
|
||||
optbl[0x56] = &bAPU::op_eor_a_addry;
|
||||
optbl[0x15] = &bAPU::op_or_a_addrx;
|
||||
optbl[0x16] = &bAPU::op_or_a_addry;
|
||||
optbl[0xb5] = &bAPU::op_sbc_a_addrx;
|
||||
optbl[0xb6] = &bAPU::op_sbc_a_addry;
|
||||
optbl[0x87] = &bAPU::op_adc_a_idpx;
|
||||
optbl[0x27] = &bAPU::op_and_a_idpx;
|
||||
optbl[0x67] = &bAPU::op_cmp_a_idpx;
|
||||
optbl[0x47] = &bAPU::op_eor_a_idpx;
|
||||
optbl[0x07] = &bAPU::op_or_a_idpx;
|
||||
optbl[0xa7] = &bAPU::op_sbc_a_idpx;
|
||||
optbl[0x97] = &bAPU::op_adc_a_idpy;
|
||||
optbl[0x37] = &bAPU::op_and_a_idpy;
|
||||
optbl[0x77] = &bAPU::op_cmp_a_idpy;
|
||||
optbl[0x57] = &bAPU::op_eor_a_idpy;
|
||||
optbl[0x17] = &bAPU::op_or_a_idpy;
|
||||
optbl[0xb7] = &bAPU::op_sbc_a_idpy;
|
||||
optbl[0x99] = &bAPU::op_adc_ix_iy;
|
||||
optbl[0x39] = &bAPU::op_and_ix_iy;
|
||||
optbl[0x79] = &bAPU::op_cmp_ix_iy;
|
||||
optbl[0x59] = &bAPU::op_eor_ix_iy;
|
||||
optbl[0x19] = &bAPU::op_or_ix_iy;
|
||||
optbl[0xb9] = &bAPU::op_sbc_ix_iy;
|
||||
optbl[0x89] = &bAPU::op_adc_dp_dp;
|
||||
optbl[0x29] = &bAPU::op_and_dp_dp;
|
||||
optbl[0x69] = &bAPU::op_cmp_dp_dp;
|
||||
optbl[0x49] = &bAPU::op_eor_dp_dp;
|
||||
optbl[0x09] = &bAPU::op_or_dp_dp;
|
||||
optbl[0xa9] = &bAPU::op_sbc_dp_dp;
|
||||
optbl[0x98] = &bAPU::op_adc_dp_const;
|
||||
optbl[0x38] = &bAPU::op_and_dp_const;
|
||||
optbl[0x78] = &bAPU::op_cmp_dp_const;
|
||||
optbl[0x58] = &bAPU::op_eor_dp_const;
|
||||
optbl[0x18] = &bAPU::op_or_dp_const;
|
||||
optbl[0xb8] = &bAPU::op_sbc_dp_const;
|
||||
optbl[0x7a] = &bAPU::op_addw_ya_dp;
|
||||
optbl[0x5a] = &bAPU::op_cmpw_ya_dp;
|
||||
optbl[0x9a] = &bAPU::op_subw_ya_dp;
|
||||
optbl[0x4a] = &bAPU::op_and1_bit;
|
||||
optbl[0x6a] = &bAPU::op_and1_notbit;
|
||||
optbl[0x8a] = &bAPU::op_eor1_bit;
|
||||
optbl[0xea] = &bAPU::op_not1_bit;
|
||||
optbl[0x0a] = &bAPU::op_or1_bit;
|
||||
optbl[0x2a] = &bAPU::op_or1_notbit;
|
||||
optbl[0xbc] = &bAPU::op_inc_a;
|
||||
optbl[0x3d] = &bAPU::op_inc_x;
|
||||
optbl[0xfc] = &bAPU::op_inc_y;
|
||||
optbl[0x9c] = &bAPU::op_dec_a;
|
||||
optbl[0x1d] = &bAPU::op_dec_x;
|
||||
optbl[0xdc] = &bAPU::op_dec_y;
|
||||
optbl[0x1c] = &bAPU::op_asl_a;
|
||||
optbl[0x5c] = &bAPU::op_lsr_a;
|
||||
optbl[0x3c] = &bAPU::op_rol_a;
|
||||
optbl[0x7c] = &bAPU::op_ror_a;
|
||||
optbl[0xab] = &bAPU::op_inc_dp;
|
||||
optbl[0x8b] = &bAPU::op_dec_dp;
|
||||
optbl[0x0b] = &bAPU::op_asl_dp;
|
||||
optbl[0x4b] = &bAPU::op_lsr_dp;
|
||||
optbl[0x2b] = &bAPU::op_rol_dp;
|
||||
optbl[0x6b] = &bAPU::op_ror_dp;
|
||||
optbl[0xbb] = &bAPU::op_inc_dpx;
|
||||
optbl[0x9b] = &bAPU::op_dec_dpx;
|
||||
optbl[0x1b] = &bAPU::op_asl_dpx;
|
||||
optbl[0x5b] = &bAPU::op_lsr_dpx;
|
||||
optbl[0x3b] = &bAPU::op_rol_dpx;
|
||||
optbl[0x7b] = &bAPU::op_ror_dpx;
|
||||
optbl[0xac] = &bAPU::op_inc_addr;
|
||||
optbl[0x8c] = &bAPU::op_dec_addr;
|
||||
optbl[0x0c] = &bAPU::op_asl_addr;
|
||||
optbl[0x4c] = &bAPU::op_lsr_addr;
|
||||
optbl[0x2c] = &bAPU::op_rol_addr;
|
||||
optbl[0x6c] = &bAPU::op_ror_addr;
|
||||
optbl[0x3a] = &bAPU::op_incw_dp;
|
||||
optbl[0x1a] = &bAPU::op_decw_dp;
|
||||
optbl[0x00] = &bAPU::op_nop;
|
||||
optbl[0xef] = &bAPU::op_sleep;
|
||||
optbl[0xff] = &bAPU::op_stop;
|
||||
optbl[0x9f] = &bAPU::op_xcn;
|
||||
optbl[0xdf] = &bAPU::op_daa;
|
||||
optbl[0xbe] = &bAPU::op_das;
|
||||
optbl[0x60] = &bAPU::op_clrc;
|
||||
optbl[0x20] = &bAPU::op_clrp;
|
||||
optbl[0x80] = &bAPU::op_setc;
|
||||
optbl[0x40] = &bAPU::op_setp;
|
||||
optbl[0xe0] = &bAPU::op_clrv;
|
||||
optbl[0xed] = &bAPU::op_notc;
|
||||
optbl[0xa0] = &bAPU::op_ei;
|
||||
optbl[0xc0] = &bAPU::op_di;
|
||||
optbl[0x02] = &bAPU::op_set0_dp;
|
||||
optbl[0x12] = &bAPU::op_clr0_dp;
|
||||
optbl[0x22] = &bAPU::op_set1_dp;
|
||||
optbl[0x32] = &bAPU::op_clr1_dp;
|
||||
optbl[0x42] = &bAPU::op_set2_dp;
|
||||
optbl[0x52] = &bAPU::op_clr2_dp;
|
||||
optbl[0x62] = &bAPU::op_set3_dp;
|
||||
optbl[0x72] = &bAPU::op_clr3_dp;
|
||||
optbl[0x82] = &bAPU::op_set4_dp;
|
||||
optbl[0x92] = &bAPU::op_clr4_dp;
|
||||
optbl[0xa2] = &bAPU::op_set5_dp;
|
||||
optbl[0xb2] = &bAPU::op_clr5_dp;
|
||||
optbl[0xc2] = &bAPU::op_set6_dp;
|
||||
optbl[0xd2] = &bAPU::op_clr6_dp;
|
||||
optbl[0xe2] = &bAPU::op_set7_dp;
|
||||
optbl[0xf2] = &bAPU::op_clr7_dp;
|
||||
optbl[0x0e] = &bAPU::op_tset_addr_a;
|
||||
optbl[0x4e] = &bAPU::op_tclr_addr_a;
|
||||
optbl[0x2d] = &bAPU::op_push_a;
|
||||
optbl[0x4d] = &bAPU::op_push_x;
|
||||
optbl[0x6d] = &bAPU::op_push_y;
|
||||
optbl[0x0d] = &bAPU::op_push_p;
|
||||
optbl[0xae] = &bAPU::op_pop_a;
|
||||
optbl[0xce] = &bAPU::op_pop_x;
|
||||
optbl[0xee] = &bAPU::op_pop_y;
|
||||
optbl[0x8e] = &bAPU::op_pop_p;
|
||||
optbl[0xcf] = &bAPU::op_mul_ya;
|
||||
optbl[0x9e] = &bAPU::op_div_ya_x;
|
||||
@@ -1,3 +0,0 @@
|
||||
cl /ML /O2 bapugen.cpp
|
||||
@pause
|
||||
@del *.obj
|
||||
@@ -1 +0,0 @@
|
||||
@del *.exe
|
||||
@@ -1,207 +0,0 @@
|
||||
mov_a_x(0x7d, a, x),
|
||||
mov_a_y(0xdd, a, y),
|
||||
mov_x_a(0x5d, x, a),
|
||||
mov_y_a(0xfd, y, a),
|
||||
mov_x_sp(0x9d, x, sp),
|
||||
mov_sp_x(0xbd, sp, x) {
|
||||
1:regs.$1 = regs.$2;
|
||||
regs.p.n = !!(regs.$1 & 0x80);
|
||||
regs.p.z = (regs.$1 == 0);
|
||||
}
|
||||
|
||||
mov_a_const(0xe8, a),
|
||||
mov_x_const(0xcd, x),
|
||||
mov_y_const(0x8d, y) {
|
||||
1:regs.$1 = op_read();
|
||||
regs.p.n = !!(regs.$1 & 0x80);
|
||||
regs.p.z = (regs.$1 == 0);
|
||||
}
|
||||
|
||||
mov_a_ix(0xe6) {
|
||||
1:
|
||||
2:regs.a = op_read(OPMODE_DP, regs.x);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
mov_a_ixinc(0xbf) {
|
||||
1:
|
||||
2:
|
||||
3:regs.a = op_read(OPMODE_DP, regs.x++);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
mov_a_dp(0xe4, a),
|
||||
mov_x_dp(0xf8, x),
|
||||
mov_y_dp(0xeb, y) {
|
||||
1:sp = op_read();
|
||||
2:regs.$1 = op_read(OPMODE_DP, sp);
|
||||
regs.p.n = !!(regs.$1 & 0x80);
|
||||
regs.p.z = (regs.$1 == 0);
|
||||
}
|
||||
|
||||
mov_a_dpx(0xf4, a, x),
|
||||
mov_x_dpy(0xf9, x, y),
|
||||
mov_y_dpx(0xfb, y, x) {
|
||||
1:sp = op_read();
|
||||
2:
|
||||
3:regs.$1 = op_read(OPMODE_DP, sp + regs.$2);
|
||||
regs.p.n = !!(regs.$1 & 0x80);
|
||||
regs.p.z = (regs.$1 == 0);
|
||||
}
|
||||
|
||||
mov_a_addr(0xe5, a),
|
||||
mov_x_addr(0xe9, x),
|
||||
mov_y_addr(0xec, y) {
|
||||
1:sp = op_read();
|
||||
2:sp |= op_read() << 8;
|
||||
3:regs.$1 = op_read(OPMODE_ADDR, sp);
|
||||
regs.p.n = !!(regs.$1 & 0x80);
|
||||
regs.p.z = (regs.$1 == 0);
|
||||
}
|
||||
|
||||
mov_a_addrx(0xf5, x),
|
||||
mov_a_addry(0xf6, y) {
|
||||
1:sp = op_read();
|
||||
2:sp |= op_read() << 8;
|
||||
3:
|
||||
4:regs.a = op_read(OPMODE_ADDR, sp + regs.$1);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
mov_a_idpx(0xe7) {
|
||||
1:dp = op_read() + regs.x;
|
||||
2:
|
||||
3:sp = op_read(OPMODE_DP, dp);
|
||||
4:sp |= op_read(OPMODE_DP, dp + 1) << 8;
|
||||
5:regs.a = op_read(OPMODE_ADDR, sp);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
mov_a_idpy(0xf7) {
|
||||
1:dp = op_read();
|
||||
2:
|
||||
3:sp = op_read(OPMODE_DP, dp);
|
||||
4:sp |= op_read(OPMODE_DP, dp + 1) << 8;
|
||||
5:regs.a = op_read(OPMODE_ADDR, sp + regs.y);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
mov_dp_dp(0xfa) {
|
||||
1:sp = op_read();
|
||||
2:dp = op_read();
|
||||
3:rd = op_read(OPMODE_DP, sp);
|
||||
4:op_write(OPMODE_DP, dp, rd);
|
||||
}
|
||||
|
||||
mov_dp_const(0x8f) {
|
||||
1:rd = op_read();
|
||||
2:dp = op_read();
|
||||
3:
|
||||
4:op_write(OPMODE_DP, dp, rd);
|
||||
}
|
||||
|
||||
mov_ix_a(0xc6) {
|
||||
1:
|
||||
2:
|
||||
3:op_write(OPMODE_DP, regs.x, regs.a);
|
||||
}
|
||||
|
||||
mov_ixinc_a(0xaf) {
|
||||
1:
|
||||
2:
|
||||
3:op_write(OPMODE_DP, regs.x++, regs.a);
|
||||
}
|
||||
|
||||
mov_dp_a(0xc4, a),
|
||||
mov_dp_x(0xd8, x),
|
||||
mov_dp_y(0xcb, y) {
|
||||
1:dp = op_read();
|
||||
2:
|
||||
3:op_write(OPMODE_DP, dp, regs.$1);
|
||||
}
|
||||
|
||||
mov_dpx_a(0xd4, x, a),
|
||||
mov_dpy_x(0xd9, y, x),
|
||||
mov_dpx_y(0xdb, x, y) {
|
||||
1:dp = op_read();
|
||||
2:
|
||||
3:
|
||||
4:op_write(OPMODE_DP, dp + regs.$1, regs.$2);
|
||||
}
|
||||
|
||||
mov_addr_a(0xc5, a),
|
||||
mov_addr_x(0xc9, x),
|
||||
mov_addr_y(0xcc, y) {
|
||||
1:dp = op_read();
|
||||
2:dp |= op_read() << 8;
|
||||
3:
|
||||
4:op_write(OPMODE_ADDR, dp, regs.$1);
|
||||
}
|
||||
|
||||
mov_addrx_a(0xd5, x),
|
||||
mov_addry_a(0xd6, y) {
|
||||
1:dp = op_read();
|
||||
2:dp |= op_read() << 8;
|
||||
3:
|
||||
4:
|
||||
5:op_write(OPMODE_ADDR, dp + regs.$1, regs.a);
|
||||
}
|
||||
|
||||
mov_idpx_a(0xc7) {
|
||||
1:sp = op_read() + regs.x;
|
||||
2:
|
||||
3:dp = op_read(OPMODE_DP, sp);
|
||||
4:dp |= op_read(OPMODE_DP, sp + 1) << 8;
|
||||
5:
|
||||
6:op_write(OPMODE_ADDR, dp, regs.a);
|
||||
}
|
||||
|
||||
mov_idpy_a(0xd7) {
|
||||
1:sp = op_read();
|
||||
2:
|
||||
3:dp = op_read(OPMODE_DP, sp);
|
||||
4:dp |= op_read(OPMODE_DP, sp + 1) << 8;
|
||||
5:
|
||||
6:op_write(OPMODE_ADDR, dp + regs.y, regs.a);
|
||||
}
|
||||
|
||||
movw_ya_dp(0xba) {
|
||||
1:sp = op_read();
|
||||
2:
|
||||
3:regs.a = op_read(OPMODE_DP, sp);
|
||||
4:regs.y = op_read(OPMODE_DP, sp + 1);
|
||||
regs.p.n = !!(regs.ya & 0x8000);
|
||||
regs.p.z = (regs.ya == 0);
|
||||
}
|
||||
|
||||
movw_dp_ya(0xda) {
|
||||
1:dp = op_read();
|
||||
2:
|
||||
3:op_write(OPMODE_DP, dp, regs.a);
|
||||
4:op_write(OPMODE_DP, dp + 1, regs.y);
|
||||
}
|
||||
|
||||
mov1_c_bit(0xaa) {
|
||||
1:sp = op_read();
|
||||
2:sp |= op_read() << 8;
|
||||
3:bit = sp >> 13;
|
||||
sp &= 0x1fff;
|
||||
rd = op_read(OPMODE_ADDR, sp);
|
||||
regs.p.c = !!(rd & (1 << bit));
|
||||
}
|
||||
|
||||
mov1_bit_c(0xca) {
|
||||
1:dp = op_read();
|
||||
2:dp |= op_read() << 8;
|
||||
3:bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
if(regs.p.c)rd |= (1 << bit);
|
||||
else rd &= ~(1 << bit);
|
||||
4:op_write(OPMODE_ADDR, dp, rd);
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
bra(0x2f, 0),
|
||||
beq(0xf0, !regs.p.z),
|
||||
bne(0xd0, regs.p.z),
|
||||
bcs(0xb0, !regs.p.c),
|
||||
bcc(0x90, regs.p.c),
|
||||
bvs(0x70, !regs.p.v),
|
||||
bvc(0x50, regs.p.v),
|
||||
bmi(0x30, !regs.p.n),
|
||||
bpl(0x10, regs.p.n) {
|
||||
1:rd = op_read();
|
||||
if($1)end;
|
||||
2:
|
||||
3:regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
bbs0(0x03, 0x01, !=),
|
||||
bbc0(0x13, 0x01, ==),
|
||||
bbs1(0x23, 0x02, !=),
|
||||
bbc1(0x33, 0x02, ==),
|
||||
bbs2(0x43, 0x04, !=),
|
||||
bbc2(0x53, 0x04, ==),
|
||||
bbs3(0x63, 0x08, !=),
|
||||
bbc3(0x73, 0x08, ==),
|
||||
bbs4(0x83, 0x10, !=),
|
||||
bbc4(0x93, 0x10, ==),
|
||||
bbs5(0xa3, 0x20, !=),
|
||||
bbc5(0xb3, 0x20, ==),
|
||||
bbs6(0xc3, 0x40, !=),
|
||||
bbc6(0xd3, 0x40, ==),
|
||||
bbs7(0xe3, 0x80, !=),
|
||||
bbc7(0xf3, 0x80, ==) {
|
||||
1:dp = op_read();
|
||||
2:rd = op_read();
|
||||
3:sp = op_read(OPMODE_DP, dp);
|
||||
4:if((sp & $1) $2 $1)end;
|
||||
5:
|
||||
6:regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
cbne_dp(0x2e) {
|
||||
1:dp = op_read();
|
||||
2:rd = op_read();
|
||||
3:sp = op_read(OPMODE_DP, dp);
|
||||
4:if(regs.a == sp)end;
|
||||
5:
|
||||
6:regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
cbne_dpx(0xde) {
|
||||
1:dp = op_read();
|
||||
2:rd = op_read();
|
||||
3:
|
||||
4:sp = op_read(OPMODE_DP, dp + regs.x);
|
||||
5:if(regs.a == sp)end;
|
||||
6:
|
||||
7:regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
dbnz_dp(0x6e) {
|
||||
1:dp = op_read();
|
||||
2:rd = op_read();
|
||||
3:wr = op_read(OPMODE_DP, dp);
|
||||
4:wr--;
|
||||
op_write(OPMODE_DP, dp, wr);
|
||||
if(wr == 0x00)end;
|
||||
5:
|
||||
6:regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
dbnz_y(0xfe) {
|
||||
1:rd = op_read();
|
||||
2:regs.y--;
|
||||
3:if(regs.y == 0x00)end;
|
||||
4:
|
||||
5:regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
jmp_addr(0x5f) {
|
||||
1:rd = op_read();
|
||||
2:rd |= op_read() << 8;
|
||||
regs.pc = rd;
|
||||
}
|
||||
|
||||
jmp_iaddrx(0x1f) {
|
||||
1:dp = op_read();
|
||||
2:dp |= op_read() << 8;
|
||||
3:dp += regs.x;
|
||||
4:rd = op_read(OPMODE_ADDR, dp);
|
||||
5:rd |= op_read(OPMODE_ADDR, dp + 1) << 8;
|
||||
regs.pc = rd;
|
||||
}
|
||||
|
||||
call(0x3f) {
|
||||
1:rd = op_read();
|
||||
2:rd |= op_read() << 8;
|
||||
3:
|
||||
4:
|
||||
5:
|
||||
6:stack_write(regs.pc >> 8);
|
||||
7:stack_write(regs.pc);
|
||||
regs.pc = rd;
|
||||
}
|
||||
|
||||
pcall(0x4f) {
|
||||
1:rd = op_read();
|
||||
2:
|
||||
3:
|
||||
4:stack_write(regs.pc >> 8);
|
||||
5:stack_write(regs.pc);
|
||||
regs.pc = 0xff00 | rd;
|
||||
}
|
||||
|
||||
tcall_0(0x01, 0),
|
||||
tcall_1(0x11, 1),
|
||||
tcall_2(0x21, 2),
|
||||
tcall_3(0x31, 3),
|
||||
tcall_4(0x41, 4),
|
||||
tcall_5(0x51, 5),
|
||||
tcall_6(0x61, 6),
|
||||
tcall_7(0x71, 7),
|
||||
tcall_8(0x81, 8),
|
||||
tcall_9(0x91, 9),
|
||||
tcall_10(0xa1, 10),
|
||||
tcall_11(0xb1, 11),
|
||||
tcall_12(0xc1, 12),
|
||||
tcall_13(0xd1, 13),
|
||||
tcall_14(0xe1, 14),
|
||||
tcall_15(0xf1, 15) {
|
||||
1:dp = 0xffde - ($1 << 1);
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
2:rd |= op_read(OPMODE_ADDR, dp + 1) << 8;
|
||||
3:
|
||||
4:
|
||||
5:
|
||||
6:stack_write(regs.pc >> 8);
|
||||
7:stack_write(regs.pc);
|
||||
regs.pc = rd;
|
||||
}
|
||||
|
||||
brk(0x0f) {
|
||||
1:rd = op_read(OPMODE_ADDR, 0xffde);
|
||||
2:rd |= op_read(OPMODE_ADDR, 0xffdf) << 8;
|
||||
3:
|
||||
4:
|
||||
5:stack_write(regs.pc >> 8);
|
||||
6:stack_write(regs.pc);
|
||||
7:stack_write(regs.p);
|
||||
regs.pc = rd;
|
||||
regs.p.b = 1;
|
||||
regs.p.i = 0;
|
||||
}
|
||||
|
||||
ret(0x6f) {
|
||||
1:rd = stack_read();
|
||||
2:rd |= stack_read() << 8;
|
||||
3:
|
||||
4:regs.pc = rd;
|
||||
}
|
||||
|
||||
reti(0x7f) {
|
||||
1:regs.p = stack_read();
|
||||
2:rd = stack_read();
|
||||
3:rd |= stack_read() << 8;
|
||||
4:
|
||||
5:regs.pc = rd;
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
inc_a(0xbc, inc, a),
|
||||
inc_x(0x3d, inc, x),
|
||||
inc_y(0xfc, inc, y),
|
||||
dec_a(0x9c, dec, a),
|
||||
dec_x(0x1d, dec, x),
|
||||
dec_y(0xdc, dec, y),
|
||||
asl_a(0x1c, asl, a),
|
||||
lsr_a(0x5c, lsr, a),
|
||||
rol_a(0x3c, rol, a),
|
||||
ror_a(0x7c, ror, a) {
|
||||
1:regs.$2 = op_$1(regs.$2);
|
||||
}
|
||||
|
||||
inc_dp(0xab, inc),
|
||||
dec_dp(0x8b, dec),
|
||||
asl_dp(0x0b, asl),
|
||||
lsr_dp(0x4b, lsr),
|
||||
rol_dp(0x2b, rol),
|
||||
ror_dp(0x6b, ror) {
|
||||
1:dp = op_read();
|
||||
2:rd = op_read(OPMODE_DP, dp);
|
||||
3:rd = op_$1(rd);
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
}
|
||||
|
||||
inc_dpx(0xbb, inc),
|
||||
dec_dpx(0x9b, dec),
|
||||
asl_dpx(0x1b, asl),
|
||||
lsr_dpx(0x5b, lsr),
|
||||
rol_dpx(0x3b, rol),
|
||||
ror_dpx(0x7b, ror) {
|
||||
1:dp = op_read();
|
||||
2:
|
||||
3:rd = op_read(OPMODE_DP, dp + regs.x);
|
||||
4:rd = op_$1(rd);
|
||||
op_write(OPMODE_DP, dp + regs.x, rd);
|
||||
}
|
||||
|
||||
inc_addr(0xac, inc),
|
||||
dec_addr(0x8c, dec),
|
||||
asl_addr(0x0c, asl),
|
||||
lsr_addr(0x4c, lsr),
|
||||
rol_addr(0x2c, rol),
|
||||
ror_addr(0x6c, ror) {
|
||||
1:dp = op_read();
|
||||
2:dp |= op_read() << 8;
|
||||
3:rd = op_read(OPMODE_ADDR, dp);
|
||||
4:rd = op_$1(rd);
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
}
|
||||
|
||||
incw_dp(0x3a, incw),
|
||||
decw_dp(0x1a, decw) {
|
||||
1:dp = op_read();
|
||||
2:rd = op_read(OPMODE_DP, dp);
|
||||
3:rd |= op_read(OPMODE_DP, dp + 1) << 8;
|
||||
4:rd = op_$1(rd);
|
||||
op_write(OPMODE_DP, dp + 1, rd >> 8);
|
||||
5:op_write(OPMODE_DP, dp, rd);
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
#include "../../base.h"
|
||||
|
||||
uint8 bAPUSkip::spcram_read (uint16 addr) { return 0xff; }
|
||||
void bAPUSkip::spcram_write(uint16 addr, uint8 value) {}
|
||||
|
||||
/*
|
||||
This routine is very serious. It will eat holes through
|
||||
the ROM to skip APU test conditions. Or in other words,
|
||||
it will disable and/or force branches when neccesary.
|
||||
|
||||
It can very easily break or corrupt a game and prevent it
|
||||
from being playable until the ROM is reloaded (ROM writes
|
||||
are only performed in memory, of course).
|
||||
|
||||
However, this kind of brute force approach is required to
|
||||
get many games playable without proper SPC700 emulation.
|
||||
*/
|
||||
uint8 bAPUSkip::port_read(uint8 port) {
|
||||
port &= 3;
|
||||
_apu_port *p = &apu_port[port];
|
||||
int i, x, y, z, t;
|
||||
uint32 addr;
|
||||
|
||||
addr = cpu->regs.pc.d;
|
||||
p->read_addr[p->read_pos & 31] = addr;
|
||||
|
||||
//- lda $214x
|
||||
// cmp $214x
|
||||
// bne -
|
||||
// cmp ???
|
||||
// beq/bne -
|
||||
__test1:
|
||||
//look for an lda/cmp read pattern
|
||||
if(addr == p->read_addr[(p->read_pos - 1) & 31])goto __test2;
|
||||
if(addr != p->read_addr[(p->read_pos - 2) & 31])goto __test2;
|
||||
if(addr == p->read_addr[(p->read_pos - 3) & 31])goto __test2;
|
||||
if(addr != p->read_addr[(p->read_pos - 4) & 31])goto __test2;
|
||||
if(p->read_addr[(p->read_pos - 1) & 31] != p->read_addr[(p->read_pos - 3) & 31])goto __test2;
|
||||
//try and find compare opcode
|
||||
for(i=0;i<24;i++) {
|
||||
x = mem_bus->read(addr + i);
|
||||
if(x == OP_CMP_CONST || x == OP_CPX_CONST || x == OP_CPY_CONST)break;
|
||||
if(x == OP_CMP_ADDR || x == OP_CPX_ADDR || x == OP_CPY_ADDR) break;
|
||||
if(x == OP_CMP_LONG)break;
|
||||
}
|
||||
if(i == 24)goto __test2;
|
||||
//seek to next opcode
|
||||
if(x == OP_CMP_CONST) {
|
||||
i += (cpu->regs.p.m)?2:3;
|
||||
} else if(x == OP_CPX_CONST || x == OP_CPY_CONST) {
|
||||
i += (cpu->regs.p.x)?2:3;
|
||||
} else if(x == OP_CMP_ADDR || x == OP_CPX_ADDR || x == OP_CPY_ADDR) {
|
||||
i += 3;
|
||||
} else { //(x == OP_CMP_LONG) {
|
||||
i += 4;
|
||||
}
|
||||
x = mem_bus->read(addr + i);
|
||||
if(x == OP_BNE) {
|
||||
mem_bus->cart->write_protect(false);
|
||||
mem_bus->write(addr + i, OP_NOP);
|
||||
mem_bus->write(addr + i + 1, OP_NOP);
|
||||
mem_bus->cart->write_protect(true);
|
||||
} else if(x == OP_BEQ) {
|
||||
mem_bus->cart->write_protect(false);
|
||||
mem_bus->write(addr + i, OP_BRA);
|
||||
mem_bus->cart->write_protect(true);
|
||||
} else goto __test2;
|
||||
goto __pass;
|
||||
|
||||
//- lda $214x
|
||||
// cmp ???
|
||||
// beq/bne -
|
||||
__test2:
|
||||
//look for a repeated read pattern
|
||||
if(addr != p->read_addr[(p->read_pos - 1) & 31])goto __test3;
|
||||
if(addr != p->read_addr[(p->read_pos - 2) & 31])goto __test3;
|
||||
if(addr != p->read_addr[(p->read_pos - 3) & 31])goto __test3;
|
||||
if(addr != p->read_addr[(p->read_pos - 4) & 31])goto __test3;
|
||||
if(addr != p->read_addr[(p->read_pos - 5) & 31])goto __test3;
|
||||
if(addr != p->read_addr[(p->read_pos - 6) & 31])goto __test3;
|
||||
if(addr != p->read_addr[(p->read_pos - 7) & 31])goto __test3;
|
||||
if(addr != p->read_addr[(p->read_pos - 8) & 31])goto __test3;
|
||||
//try and find compare opcode
|
||||
for(i=0;i<24;i++) {
|
||||
x = mem_bus->read(addr + i);
|
||||
if(x == OP_CMP_CONST || x == OP_CPX_CONST || x == OP_CPY_CONST)break;
|
||||
if(x == OP_CMP_ADDR || x == OP_CPX_ADDR || x == OP_CPY_ADDR) break;
|
||||
if(x == OP_CMP_LONG)break;
|
||||
}
|
||||
if(i == 24)goto __test3;
|
||||
//seek to next opcode
|
||||
if(x == OP_CMP_CONST) {
|
||||
i += (cpu->regs.p.m)?2:3;
|
||||
} else if(x == OP_CPX_CONST || x == OP_CPY_CONST) {
|
||||
i += (cpu->regs.p.x)?2:3;
|
||||
} else if(x == OP_CMP_ADDR || x == OP_CPX_ADDR || x == OP_CPY_ADDR) {
|
||||
i += 3;
|
||||
} else if(x == OP_CMP_LONG) {
|
||||
i += 4;
|
||||
}
|
||||
x = mem_bus->read(addr + i);
|
||||
if(x == OP_BNE) {
|
||||
mem_bus->cart->write_protect(false);
|
||||
mem_bus->write(addr + i, OP_NOP);
|
||||
mem_bus->write(addr + i + 1, OP_NOP);
|
||||
mem_bus->cart->write_protect(true);
|
||||
} else if(x == OP_BEQ) {
|
||||
mem_bus->cart->write_protect(false);
|
||||
mem_bus->write(addr + i, OP_BRA);
|
||||
mem_bus->cart->write_protect(true);
|
||||
} else goto __test3;
|
||||
goto __pass;
|
||||
|
||||
//fallback
|
||||
__test3:
|
||||
if(p->pos < 4) {
|
||||
if(!(port & 1)) {
|
||||
p->value = cpu->regs.a.l;
|
||||
} else {
|
||||
p->value = cpu->regs.a.h;
|
||||
}
|
||||
} else if(p->pos < 8) {
|
||||
if(!(port & 1)) {
|
||||
p->value = cpu->regs.x.l;
|
||||
} else {
|
||||
p->value = cpu->regs.x.h;
|
||||
}
|
||||
} else if(p->pos < 12) {
|
||||
if(!(port & 1)) {
|
||||
p->value = cpu->regs.y.l;
|
||||
} else {
|
||||
p->value = cpu->regs.y.h;
|
||||
}
|
||||
} else if(p->pos < 16) {
|
||||
p->value = rand();
|
||||
}
|
||||
if(++p->pos == 16)p->pos = 0;
|
||||
|
||||
__pass:
|
||||
p->read_pos++;
|
||||
p->read_pos &= 31;
|
||||
return p->value;
|
||||
}
|
||||
|
||||
void bAPUSkip::port_write(uint8 port, uint8 value) {
|
||||
port &= 3;
|
||||
apu_port[port].value = value;
|
||||
}
|
||||
|
||||
void bAPUSkip::run() {
|
||||
snes->notify(SNES::APU_EXEC_OPCODE_BEGIN);
|
||||
snes->notify(SNES::APU_EXEC_OPCODE_END);
|
||||
}
|
||||
|
||||
void bAPUSkip::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void bAPUSkip::reset() {
|
||||
regs.a = 0x00;
|
||||
regs.x = 0x00;
|
||||
regs.y = 0x00;
|
||||
regs.sp = 0x00;
|
||||
regs.p = 0x02;
|
||||
regs.pc = 0xffc0;
|
||||
|
||||
memset(&apu_port[0], 0, sizeof(_apu_port));
|
||||
memset(&apu_port[1], 0, sizeof(_apu_port));
|
||||
memset(&apu_port[2], 0, sizeof(_apu_port));
|
||||
memset(&apu_port[3], 0, sizeof(_apu_port));
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
class bAPUSkip : public APU {
|
||||
private:
|
||||
uint8 spcram[65536];
|
||||
|
||||
public:
|
||||
|
||||
struct _apu_port {
|
||||
uint8 value;
|
||||
uint8 step, pos;
|
||||
uint32 read_addr[32], read_pos;
|
||||
}apu_port[4];
|
||||
|
||||
enum {
|
||||
OP_CMP_CONST = 0xc9,
|
||||
OP_CPX_CONST = 0xe0,
|
||||
OP_CPY_CONST = 0xc0,
|
||||
OP_CMP_ADDR = 0xcd,
|
||||
OP_CPX_ADDR = 0xec,
|
||||
OP_CPY_ADDR = 0xcc,
|
||||
OP_CMP_LONG = 0xcf,
|
||||
OP_BNE = 0xd0,
|
||||
OP_BEQ = 0xf0,
|
||||
OP_BRA = 0x80,
|
||||
OP_NOP = 0xea
|
||||
};
|
||||
|
||||
uint8 spcram_read (uint16 addr);
|
||||
void spcram_write(uint16 addr, uint8 value);
|
||||
uint8 port_read (uint8 port);
|
||||
void port_write (uint8 port, uint8 value);
|
||||
|
||||
uint8 *get_spcram_handle() { return spcram; }
|
||||
void run();
|
||||
uint32 cycles_executed() { return 12 * 24; }
|
||||
void power();
|
||||
void reset();
|
||||
};
|
||||
@@ -1,306 +0,0 @@
|
||||
//virtual function, see src/cpu/dcpu.cpp
|
||||
//for explanation of this function
|
||||
bool APU::in_opcode() { return false; }
|
||||
|
||||
uint16 APU::__relb(int8 offset, int op_len) {
|
||||
uint16 pc = regs.pc + op_len;
|
||||
return pc + offset;
|
||||
}
|
||||
|
||||
void APU::disassemble_opcode(char *output) {
|
||||
char *s, t[512];
|
||||
uint8 op, op0, op1;
|
||||
uint16 opw, opdp0, opdp1;
|
||||
s = output;
|
||||
|
||||
if(in_opcode() == true) {
|
||||
strcpy(s, "..???? <APU within opcode>");
|
||||
return;
|
||||
}
|
||||
|
||||
sprintf(s, "..%0.4x ", regs.pc);
|
||||
|
||||
op = spcram_read(regs.pc);
|
||||
op0 = spcram_read(regs.pc + 1);
|
||||
op1 = spcram_read(regs.pc + 2);
|
||||
opw = (op0) | (op1 << 8);
|
||||
opdp0 = ((regs.p.p)?0x100:0x000) + op0;
|
||||
opdp1 = ((regs.p.p)?0x100:0x000) + op1;
|
||||
|
||||
strcpy(t, " ");
|
||||
switch(op) {
|
||||
case 0x00:sprintf(t, "nop"); break;
|
||||
case 0x01:sprintf(t, "tcall 0"); break;
|
||||
case 0x02:sprintf(t, "set0 $%0.3x", opdp0); break;
|
||||
case 0x03:sprintf(t, "bbs0 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
|
||||
case 0x04:sprintf(t, "or a,$%0.3x", opdp0); break;
|
||||
case 0x05:sprintf(t, "or a,$%0.4x", opw); break;
|
||||
case 0x06:sprintf(t, "or a,(x)"); break;
|
||||
case 0x07:sprintf(t, "or a,($%0.3x+x)", opdp0); break;
|
||||
case 0x08:sprintf(t, "or a,#$%0.2x", op0); break;
|
||||
case 0x09:sprintf(t, "or $%0.3x,$%0.3x", opdp1, opdp0); break;
|
||||
case 0x0a:sprintf(t, "or1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
|
||||
case 0x0b:sprintf(t, "asl $%0.3x", opdp0); break;
|
||||
case 0x0c:sprintf(t, "asl $%0.4x", opw); break;
|
||||
case 0x0d:sprintf(t, "push p"); break;
|
||||
case 0x0e:sprintf(t, "tset $%0.4x,a", opw); break;
|
||||
case 0x0f:sprintf(t, "brk"); break;
|
||||
case 0x10:sprintf(t, "bpl $%0.4x", __relb(op0, 2)); break;
|
||||
case 0x11:sprintf(t, "tcall 1"); break;
|
||||
case 0x12:sprintf(t, "clr0 $%0.3x", opdp0); break;
|
||||
case 0x13:sprintf(t, "bbc0 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
|
||||
case 0x14:sprintf(t, "or a,$%0.3x+x", opdp0); break;
|
||||
case 0x15:sprintf(t, "or a,$%0.4x+x", opw); break;
|
||||
case 0x16:sprintf(t, "or a,$%0.4x+y", opw); break;
|
||||
case 0x17:sprintf(t, "or a,($%0.3x)+y", opdp0); break;
|
||||
case 0x18:sprintf(t, "or $%0.3x,#$%0.2x", opdp1, op0); break;
|
||||
case 0x19:sprintf(t, "or (x),(y)"); break;
|
||||
case 0x1a:sprintf(t, "decw $%0.3x", opdp0); break;
|
||||
case 0x1b:sprintf(t, "asl $%0.3x+x", opdp0); break;
|
||||
case 0x1c:sprintf(t, "asl a"); break;
|
||||
case 0x1d:sprintf(t, "dec x"); break;
|
||||
case 0x1e:sprintf(t, "cmp x,$%0.4x", opw); break;
|
||||
case 0x1f:sprintf(t, "jmp ($%0.4x+x)", opw); break;
|
||||
case 0x20:sprintf(t, "clrp"); break;
|
||||
case 0x21:sprintf(t, "tcall 2"); break;
|
||||
case 0x22:sprintf(t, "set1 $%0.3x", opdp0); break;
|
||||
case 0x23:sprintf(t, "bbs1 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
|
||||
case 0x24:sprintf(t, "and a,$%0.3x", opdp0); break;
|
||||
case 0x25:sprintf(t, "and a,$%0.4x", opw); break;
|
||||
case 0x26:sprintf(t, "and a,(x)"); break;
|
||||
case 0x27:sprintf(t, "and a,($%0.3x+x)", opdp0); break;
|
||||
case 0x28:sprintf(t, "and a,#$%0.2x", op0); break;
|
||||
case 0x29:sprintf(t, "and $%0.3x,$%0.3x", opdp1, opdp0); break;
|
||||
case 0x2a:sprintf(t, "or1 c,!$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
|
||||
case 0x2b:sprintf(t, "rol $%0.3x", opdp0); break;
|
||||
case 0x2c:sprintf(t, "rol $%0.4x", opw); break;
|
||||
case 0x2d:sprintf(t, "push a"); break;
|
||||
case 0x2e:sprintf(t, "cbne $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
|
||||
case 0x2f:sprintf(t, "bra $%0.4x", __relb(op0, 2)); break;
|
||||
case 0x30:sprintf(t, "bmi $%0.4x", __relb(op0, 2)); break;
|
||||
case 0x31:sprintf(t, "tcall 3"); break;
|
||||
case 0x32:sprintf(t, "clr1 $%0.3x", opdp0); break;
|
||||
case 0x33:sprintf(t, "bbc1 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
|
||||
case 0x34:sprintf(t, "and a,$%0.3x+x", opdp0); break;
|
||||
case 0x35:sprintf(t, "and a,$%0.4x+x", opw); break;
|
||||
case 0x36:sprintf(t, "and a,$%0.4x+y", opw); break;
|
||||
case 0x37:sprintf(t, "and a,($%0.3x)+y", opdp0); break;
|
||||
case 0x38:sprintf(t, "and $%0.3x,#$%0.2x", opdp1, op0); break;
|
||||
case 0x39:sprintf(t, "and (x),(y)"); break;
|
||||
case 0x3a:sprintf(t, "incw $%0.3x", opdp0); break;
|
||||
case 0x3b:sprintf(t, "rol $%0.3x+x", opdp0); break;
|
||||
case 0x3c:sprintf(t, "rol a"); break;
|
||||
case 0x3d:sprintf(t, "inc x"); break;
|
||||
case 0x3e:sprintf(t, "cmp x,$%0.3x", opdp0); break;
|
||||
case 0x3f:sprintf(t, "call $%0.4x", opw); break;
|
||||
case 0x40:sprintf(t, "setp"); break;
|
||||
case 0x41:sprintf(t, "tcall 4"); break;
|
||||
case 0x42:sprintf(t, "set2 $%0.3x", opdp0); break;
|
||||
case 0x43:sprintf(t, "bbs2 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
|
||||
case 0x44:sprintf(t, "eor a,$%0.3x", opdp0); break;
|
||||
case 0x45:sprintf(t, "eor a,$%0.4x", opw); break;
|
||||
case 0x46:sprintf(t, "eor a,(x)"); break;
|
||||
case 0x47:sprintf(t, "eor a,($%0.3x+x)", opdp0); break;
|
||||
case 0x48:sprintf(t, "eor a,#$%0.2x", op0); break;
|
||||
case 0x49:sprintf(t, "eor $%0.3x,$%0.3x", opdp1, opdp0); break;
|
||||
case 0x4a:sprintf(t, "and1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
|
||||
case 0x4b:sprintf(t, "lsr $%0.3x", opdp0); break;
|
||||
case 0x4c:sprintf(t, "lsr $%0.4x", opw); break;
|
||||
case 0x4d:sprintf(t, "push x"); break;
|
||||
case 0x4e:sprintf(t, "tclr $%0.4x,a", opw); break;
|
||||
case 0x4f:sprintf(t, "pcall $ff%0.2x", op0); break;
|
||||
case 0x50:sprintf(t, "bvc $%0.4x", __relb(op0, 2)); break;
|
||||
case 0x51:sprintf(t, "tcall 5"); break;
|
||||
case 0x52:sprintf(t, "clr2 $%0.3x", opdp0); break;
|
||||
case 0x53:sprintf(t, "bbc2 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
|
||||
case 0x54:sprintf(t, "eor a,$%0.3x+x", opdp0); break;
|
||||
case 0x55:sprintf(t, "eor a,$%0.4x+x", opw); break;
|
||||
case 0x56:sprintf(t, "eor a,$%0.4x+y", opw); break;
|
||||
case 0x57:sprintf(t, "eor a,($%0.3x)+y", opdp0); break;
|
||||
case 0x58:sprintf(t, "eor $%0.3x,#$%0.2x", opdp1, op0); break;
|
||||
case 0x59:sprintf(t, "eor (x),(y)"); break;
|
||||
case 0x5a:sprintf(t, "cmpw ya,$%0.3x", opdp0); break;
|
||||
case 0x5b:sprintf(t, "lsr $%0.3x+x", opdp0); break;
|
||||
case 0x5c:sprintf(t, "lsr a"); break;
|
||||
case 0x5d:sprintf(t, "mov x,a"); break;
|
||||
case 0x5e:sprintf(t, "cmp y,$%0.4x", opw); break;
|
||||
case 0x5f:sprintf(t, "jmp $%0.4x", opw); break;
|
||||
case 0x60:sprintf(t, "clrc"); break;
|
||||
case 0x61:sprintf(t, "tcall 6"); break;
|
||||
case 0x62:sprintf(t, "set3 $%0.3x", opdp0); break;
|
||||
case 0x63:sprintf(t, "bbs3 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
|
||||
case 0x64:sprintf(t, "cmp a,$%0.3x", opdp0); break;
|
||||
case 0x65:sprintf(t, "cmp a,$%0.4x", opw); break;
|
||||
case 0x66:sprintf(t, "cmp a,(x)"); break;
|
||||
case 0x67:sprintf(t, "cmp a,($%0.3x+x)", opdp0); break;
|
||||
case 0x68:sprintf(t, "cmp a,#$%0.2x", op0); break;
|
||||
case 0x69:sprintf(t, "cmp $%0.3x,$%0.3x", opdp1, opdp0); break;
|
||||
case 0x6a:sprintf(t, "and1 c,!$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
|
||||
case 0x6b:sprintf(t, "ror $%0.3x", opdp0); break;
|
||||
case 0x6c:sprintf(t, "ror $%0.4x", opw); break;
|
||||
case 0x6d:sprintf(t, "push y"); break;
|
||||
case 0x6e:sprintf(t, "dbnz $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
|
||||
case 0x6f:sprintf(t, "ret"); break;
|
||||
case 0x70:sprintf(t, "bvs $%0.4x", __relb(op0, 2)); break;
|
||||
case 0x71:sprintf(t, "tcall 7"); break;
|
||||
case 0x72:sprintf(t, "clr3 $%0.3x", opdp0); break;
|
||||
case 0x73:sprintf(t, "bbc3 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
|
||||
case 0x74:sprintf(t, "cmp a,$%0.3x+x", opdp0); break;
|
||||
case 0x75:sprintf(t, "cmp a,$%0.4x+x", opw); break;
|
||||
case 0x76:sprintf(t, "cmp a,$%0.4x+y", opw); break;
|
||||
case 0x77:sprintf(t, "cmp a,($%0.3x)+y", opdp0); break;
|
||||
case 0x78:sprintf(t, "cmp $%0.3x,#$%0.2x", opdp1, op0); break;
|
||||
case 0x79:sprintf(t, "cmp (x),(y)"); break;
|
||||
case 0x7a:sprintf(t, "addw ya,$%0.3x", opdp0); break;
|
||||
case 0x7b:sprintf(t, "ror $%0.3x+x", opdp0); break;
|
||||
case 0x7c:sprintf(t, "ror a"); break;
|
||||
case 0x7d:sprintf(t, "mov a,x"); break;
|
||||
case 0x7e:sprintf(t, "cmp y,$%0.3x", opdp0); break;
|
||||
case 0x7f:sprintf(t, "reti"); break;
|
||||
case 0x80:sprintf(t, "setc"); break;
|
||||
case 0x81:sprintf(t, "tcall 8"); break;
|
||||
case 0x82:sprintf(t, "set4 $%0.3x", opdp0); break;
|
||||
case 0x83:sprintf(t, "bbs4 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
|
||||
case 0x84:sprintf(t, "adc a,$%0.3x", opdp0); break;
|
||||
case 0x85:sprintf(t, "adc a,$%0.4x", opw); break;
|
||||
case 0x86:sprintf(t, "adc a,(x)"); break;
|
||||
case 0x87:sprintf(t, "adc a,($%0.3x+x)", opdp0); break;
|
||||
case 0x88:sprintf(t, "adc a,#$%0.2x", op0); break;
|
||||
case 0x89:sprintf(t, "adc $%0.3x,$%0.3x", opdp1, opdp0); break;
|
||||
case 0x8a:sprintf(t, "eor1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
|
||||
case 0x8b:sprintf(t, "dec $%0.3x", opdp0); break;
|
||||
case 0x8c:sprintf(t, "dec $%0.4x", opw); break;
|
||||
case 0x8d:sprintf(t, "mov y,#$%0.2x", op0); break;
|
||||
case 0x8e:sprintf(t, "pop p"); break;
|
||||
case 0x8f:sprintf(t, "mov $%0.3x,#$%0.2x", opdp1, op0); break;
|
||||
case 0x90:sprintf(t, "bcc $%0.4x", __relb(op0, 2)); break;
|
||||
case 0x91:sprintf(t, "tcall 9"); break;
|
||||
case 0x92:sprintf(t, "clr4 $%0.3x", opdp0); break;
|
||||
case 0x93:sprintf(t, "bbc4 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
|
||||
case 0x94:sprintf(t, "adc a,$%0.3x+x", opdp0); break;
|
||||
case 0x95:sprintf(t, "adc a,$%0.4x+x", opw); break;
|
||||
case 0x96:sprintf(t, "adc a,$%0.4x+y", opw); break;
|
||||
case 0x97:sprintf(t, "adc a,($%0.3x)+y", opdp0); break;
|
||||
case 0x98:sprintf(t, "adc $%0.3x,#$%0.2x", opdp1, op0); break;
|
||||
case 0x99:sprintf(t, "adc (x),(y)"); break;
|
||||
case 0x9a:sprintf(t, "subw ya,$%0.3x", opdp0); break;
|
||||
case 0x9b:sprintf(t, "dec $%0.3x+x", opdp0); break;
|
||||
case 0x9c:sprintf(t, "dec a"); break;
|
||||
case 0x9d:sprintf(t, "mov x,sp"); break;
|
||||
case 0x9e:sprintf(t, "div ya,x"); break;
|
||||
case 0x9f:sprintf(t, "xcn a"); break;
|
||||
case 0xa0:sprintf(t, "ei"); break;
|
||||
case 0xa1:sprintf(t, "tcall 10"); break;
|
||||
case 0xa2:sprintf(t, "set5 $%0.3x", opdp0); break;
|
||||
case 0xa3:sprintf(t, "bbs5 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
|
||||
case 0xa4:sprintf(t, "sbc a,$%0.3x", opdp0); break;
|
||||
case 0xa5:sprintf(t, "sbc a,$%0.4x", opw); break;
|
||||
case 0xa6:sprintf(t, "sbc a,(x)"); break;
|
||||
case 0xa7:sprintf(t, "sbc a,($%0.3x+x)", opdp0); break;
|
||||
case 0xa8:sprintf(t, "sbc a,#$%0.2x", op0); break;
|
||||
case 0xa9:sprintf(t, "sbc $%0.3x,$%0.3x", opdp1, opdp0); break;
|
||||
case 0xaa:sprintf(t, "mov1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
|
||||
case 0xab:sprintf(t, "inc $%0.3x", opdp0); break;
|
||||
case 0xac:sprintf(t, "inc $%0.4x", opw); break;
|
||||
case 0xad:sprintf(t, "cmp y,#$%0.2x", op0); break;
|
||||
case 0xae:sprintf(t, "pop a"); break;
|
||||
case 0xaf:sprintf(t, "mov (x)+,a"); break;
|
||||
case 0xb0:sprintf(t, "bcs $%0.4x", __relb(op0, 2)); break;
|
||||
case 0xb1:sprintf(t, "tcall 11"); break;
|
||||
case 0xb2:sprintf(t, "clr5 $%0.3x", opdp0); break;
|
||||
case 0xb3:sprintf(t, "bbc5 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
|
||||
case 0xb4:sprintf(t, "sbc a,$%0.3x+x", opdp0); break;
|
||||
case 0xb5:sprintf(t, "sbc a,$%0.4x+x", opw); break;
|
||||
case 0xb6:sprintf(t, "sbc a,$%0.4x+y", opw); break;
|
||||
case 0xb7:sprintf(t, "sbc a,($%0.3x)+y", opdp0); break;
|
||||
case 0xb8:sprintf(t, "sbc $%0.3x,#$%0.2x", opdp1, op0); break;
|
||||
case 0xb9:sprintf(t, "sbc (x),(y)"); break;
|
||||
case 0xba:sprintf(t, "movw ya,$%0.3x", opdp0); break;
|
||||
case 0xbb:sprintf(t, "inc $%0.3x+x", opdp0); break;
|
||||
case 0xbc:sprintf(t, "inc a"); break;
|
||||
case 0xbd:sprintf(t, "mov sp,x"); break;
|
||||
case 0xbe:sprintf(t, "das a"); break;
|
||||
case 0xbf:sprintf(t, "mov a,(x)+"); break;
|
||||
case 0xc0:sprintf(t, "di"); break;
|
||||
case 0xc1:sprintf(t, "tcall 12"); break;
|
||||
case 0xc2:sprintf(t, "set6 $%0.3x", opdp0); break;
|
||||
case 0xc3:sprintf(t, "bbs6 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
|
||||
case 0xc4:sprintf(t, "mov $%0.3x,a", opdp0); break;
|
||||
case 0xc5:sprintf(t, "mov $%0.4x,a", opw); break;
|
||||
case 0xc6:sprintf(t, "mov (x),a"); break;
|
||||
case 0xc7:sprintf(t, "mov ($%0.3x+x),a", opdp0); break;
|
||||
case 0xc8:sprintf(t, "cmp x,#$%0.2x", op0); break;
|
||||
case 0xc9:sprintf(t, "mov $%0.4x,x", opw); break;
|
||||
case 0xca:sprintf(t, "mov1 $%0.4x:%d,c", opw & 0x1fff, opw >> 13); break;
|
||||
case 0xcb:sprintf(t, "mov $%0.3x,y", opdp0); break;
|
||||
case 0xcc:sprintf(t, "mov $%0.4x,y", opw); break;
|
||||
case 0xcd:sprintf(t, "mov x,#$%0.2x", op0); break;
|
||||
case 0xce:sprintf(t, "pop x"); break;
|
||||
case 0xcf:sprintf(t, "mul ya"); break;
|
||||
case 0xd0:sprintf(t, "bne $%0.4x", __relb(op0, 2)); break;
|
||||
case 0xd1:sprintf(t, "tcall 13"); break;
|
||||
case 0xd2:sprintf(t, "clr6 $%0.3x", opdp0); break;
|
||||
case 0xd3:sprintf(t, "bbc6 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
|
||||
case 0xd4:sprintf(t, "mov $%0.3x+x,a", opdp0); break;
|
||||
case 0xd5:sprintf(t, "mov $%0.4x+x,a", opw); break;
|
||||
case 0xd6:sprintf(t, "mov $%0.4x+y,a", opw); break;
|
||||
case 0xd7:sprintf(t, "mov ($%0.3x)+y,a", opdp0); break;
|
||||
case 0xd8:sprintf(t, "mov $%0.3x,x", opdp0); break;
|
||||
case 0xd9:sprintf(t, "mov $%0.3x+y,x", opdp0); break;
|
||||
case 0xda:sprintf(t, "movw $%0.3x,ya", opdp0); break;
|
||||
case 0xdb:sprintf(t, "mov $%0.3x+x,y", opdp0); break;
|
||||
case 0xdc:sprintf(t, "dec y"); break;
|
||||
case 0xdd:sprintf(t, "mov a,y"); break;
|
||||
case 0xde:sprintf(t, "cbne $%0.3x+x,$%0.4x", opdp0, __relb(op1, 3));break;
|
||||
case 0xdf:sprintf(t, "daa a"); break;
|
||||
case 0xe0:sprintf(t, "clrv"); break;
|
||||
case 0xe1:sprintf(t, "tcall 14"); break;
|
||||
case 0xe2:sprintf(t, "set7 $%0.3x", opdp0); break;
|
||||
case 0xe3:sprintf(t, "bbs7 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
|
||||
case 0xe4:sprintf(t, "mov a,$%0.3x", opdp0); break;
|
||||
case 0xe5:sprintf(t, "mov a,$%0.4x", opw); break;
|
||||
case 0xe6:sprintf(t, "mov a,(x)"); break;
|
||||
case 0xe7:sprintf(t, "mov a,($%0.3x+x)", opdp0); break;
|
||||
case 0xe8:sprintf(t, "mov a,#$%0.2x", op0); break;
|
||||
case 0xe9:sprintf(t, "mov x,$%0.4x", opw); break;
|
||||
case 0xea:sprintf(t, "not1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
|
||||
case 0xeb:sprintf(t, "mov y,$%0.3x", opdp0); break;
|
||||
case 0xec:sprintf(t, "mov y,$%0.4x", opw); break;
|
||||
case 0xed:sprintf(t, "notc"); break;
|
||||
case 0xee:sprintf(t, "pop y"); break;
|
||||
case 0xef:sprintf(t, "sleep"); break;
|
||||
case 0xf0:sprintf(t, "beq $%0.4x", __relb(op0, 2)); break;
|
||||
case 0xf1:sprintf(t, "tcall 15"); break;
|
||||
case 0xf2:sprintf(t, "clr7 $%0.3x", opdp0); break;
|
||||
case 0xf3:sprintf(t, "bbc7 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
|
||||
case 0xf4:sprintf(t, "mov a,$%0.3x+x", opdp0); break;
|
||||
case 0xf5:sprintf(t, "mov a,$%0.4x+x", opw); break;
|
||||
case 0xf6:sprintf(t, "mov a,$%0.4x+y", opw); break;
|
||||
case 0xf7:sprintf(t, "mov a,($%0.3x)+y", opdp0); break;
|
||||
case 0xf8:sprintf(t, "mov x,$%0.3x", opdp0); break;
|
||||
case 0xf9:sprintf(t, "mov x,$%0.3x+y", opdp0); break;
|
||||
case 0xfa:sprintf(t, "mov $%0.3x,$%0.3x", opdp1, opdp0); break;
|
||||
case 0xfb:sprintf(t, "mov y,$%0.3x+x", opdp0); break;
|
||||
case 0xfc:sprintf(t, "inc y"); break;
|
||||
case 0xfd:sprintf(t, "mov y,a"); break;
|
||||
case 0xfe:sprintf(t, "dbnz y,$%0.4x", __relb(op0, 2)); break;
|
||||
case 0xff:sprintf(t, "stop"); break;
|
||||
}
|
||||
t[strlen(t)] = ' ';
|
||||
strcat(s, t);
|
||||
|
||||
sprintf(t, "A:%0.2x X:%0.2x Y:%0.2x SP:01%0.2x YA:%0.4x ",
|
||||
regs.a, regs.x, regs.y, regs.sp, regs.ya);
|
||||
strcat(s, t);
|
||||
|
||||
sprintf(t, "%c%c%c%c%c%c%c%c",
|
||||
(regs.p.n)?'N':'n',
|
||||
(regs.p.v)?'V':'v',
|
||||
(regs.p.p)?'P':'p',
|
||||
(regs.p.b)?'B':'b',
|
||||
(regs.p.h)?'H':'h',
|
||||
(regs.p.i)?'I':'i',
|
||||
(regs.p.z)?'Z':'z',
|
||||
(regs.p.c)?'C':'c');
|
||||
strcat(s, t);
|
||||
}
|
||||
+56
-42
@@ -1,42 +1,56 @@
|
||||
//this should be declared in the port-specific makefiles
|
||||
//#define ARCH_LSB
|
||||
//#define ARCH_MSB
|
||||
|
||||
#ifndef ARCH_LSB
|
||||
#ifndef ARCH_MSB
|
||||
#define ARCH_LSB
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#include "lib/libbase.h"
|
||||
#include "lib/libvector.h"
|
||||
#include "lib/libstring.h"
|
||||
#include "lib/libconfig.h"
|
||||
|
||||
inline uint16 read16(uint8 *addr, uint pos) {
|
||||
#ifdef ARCH_LSB
|
||||
return *((uint16*)(addr + pos));
|
||||
#else
|
||||
return (addr[pos]) | (addr[pos + 1] << 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define _WIN32_
|
||||
#undef _UNIX_
|
||||
#elif defined(__GNUC__)
|
||||
#define _UNIX_
|
||||
#undef _WIN32_
|
||||
#else
|
||||
#error "unknown architecture"
|
||||
#endif
|
||||
|
||||
//platform-specific global functions
|
||||
void *memalloc(uint32 size, char *name = 0, ...);
|
||||
void memfree(void *mem, char *name = 0, ...);
|
||||
void alert(char *s, ...);
|
||||
void dprintf(char *s, ...);
|
||||
|
||||
//various class interfaces
|
||||
#include "interface.h"
|
||||
#define BSNES_VERSION "0.032a"
|
||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||
|
||||
#define BUSCORE sBus
|
||||
#define CPUCORE sCPU
|
||||
#define SMPCORE sSMP
|
||||
#define DSPCORE sDSP
|
||||
#define PPUCORE bPPU
|
||||
|
||||
//S-DSP can be encapsulated into a state machine using #define magic
|
||||
//this avoids ~2.048m co_switch() calls per second (~5% speedup)
|
||||
#define USE_STATE_MACHINE
|
||||
|
||||
//FAST_FRAMESKIP disables calculation of RTO during frameskip
|
||||
//frameskip offers near-zero speedup if RTO is calculated
|
||||
//accuracy is not affected by this define when frameskipping is off
|
||||
#define FAST_FRAMESKIP
|
||||
|
||||
//game genie + pro action replay code support (~2% speed hit)
|
||||
#define CHEAT_SYSTEM
|
||||
|
||||
#include <nall/algorithm.hpp>
|
||||
#include <nall/array.hpp>
|
||||
#include <nall/bit.hpp>
|
||||
#include <nall/config.hpp>
|
||||
#include <nall/detect.hpp>
|
||||
#include <nall/function.hpp>
|
||||
#include <nall/modulo.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 <libco/libco.h>
|
||||
#include <bbase.h>
|
||||
|
||||
//platform-specific global functions
|
||||
void alert(const char*, ...);
|
||||
void dprintf(const char*, ...);
|
||||
void dprintf(uint, const char*, ...);
|
||||
|
||||
namespace source {
|
||||
enum {
|
||||
none = 0,
|
||||
debug,
|
||||
cpu,
|
||||
ppu,
|
||||
smp,
|
||||
dsp,
|
||||
bus,
|
||||
};
|
||||
};
|
||||
|
||||
#include "interface.h"
|
||||
@@ -0,0 +1,137 @@
|
||||
#include "../base.h"
|
||||
#define CART_CPP
|
||||
|
||||
#include <nall/crc32.hpp>
|
||||
#include <nall/ups.hpp>
|
||||
|
||||
#include "cart_normal.cpp"
|
||||
#include "cart_bsx.cpp"
|
||||
#include "cart_bsc.cpp"
|
||||
#include "cart_st.cpp"
|
||||
|
||||
#include "cart_file.cpp"
|
||||
#include "cart_header.cpp"
|
||||
|
||||
namespace memory {
|
||||
MappedRAM cartrom, cartram;
|
||||
MappedRAM bscram;
|
||||
MappedRAM stArom, stAram;
|
||||
MappedRAM stBrom, stBram;
|
||||
};
|
||||
|
||||
Cartridge cartridge;
|
||||
|
||||
Cartridge::MemoryMapper Cartridge::mapper() { return info.mapper; }
|
||||
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.bsxbase = false;
|
||||
info.bsxcart = false;
|
||||
info.bsxflash = false;
|
||||
info.st = false;
|
||||
|
||||
info.superfx = false;
|
||||
info.sa1 = false;
|
||||
info.spc7110 = false;
|
||||
info.srtc = false;
|
||||
info.sdd1 = false;
|
||||
info.cx4 = false;
|
||||
info.dsp1 = false;
|
||||
info.dsp2 = false;
|
||||
info.dsp3 = false;
|
||||
info.dsp4 = false;
|
||||
info.obc1 = false;
|
||||
info.st010 = false;
|
||||
info.st011 = false;
|
||||
info.st018 = false;
|
||||
|
||||
info.dsp1_mapper = DSP1Unmapped;
|
||||
|
||||
info.header_index = 0xffc0;
|
||||
info.mapper = LoROM;
|
||||
info.name[0] = 0;
|
||||
info.region = NTSC;
|
||||
|
||||
info.rom_size = 0;
|
||||
info.ram_size = 0;
|
||||
}
|
||||
|
||||
void Cartridge::load_end() {
|
||||
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);
|
||||
|
||||
memory::cartrom.write_protect(true);
|
||||
memory::cartram.write_protect(false);
|
||||
memory::bscram.write_protect(true);
|
||||
memory::stArom.write_protect(true);
|
||||
memory::stAram.write_protect(false);
|
||||
memory::stBrom.write_protect(true);
|
||||
memory::stBram.write_protect(false);
|
||||
|
||||
if(fexists(get_cheat_filename(cart.fn, "cht"))) {
|
||||
cheat.clear();
|
||||
cheat.load(cheatfn);
|
||||
}
|
||||
|
||||
cart.loaded = true;
|
||||
bus.load_cart();
|
||||
}
|
||||
|
||||
bool Cartridge::unload() {
|
||||
if(cart.loaded == false) return false;
|
||||
|
||||
bus.unload_cart();
|
||||
|
||||
switch(info.type) {
|
||||
case CartridgeNormal: unload_cart_normal(); break;
|
||||
case CartridgeBSX: unload_cart_bsx(); break;
|
||||
case CartridgeBSC: unload_cart_bsc(); break;
|
||||
case CartridgeSufamiTurbo: unload_cart_st(); break;
|
||||
}
|
||||
|
||||
if(cart.rom) { delete[] cart.rom; cart.rom = 0; }
|
||||
if(cart.ram) { delete[] cart.ram; cart.ram = 0; }
|
||||
if(bs.ram) { delete[] bs.ram; bs.ram = 0; }
|
||||
if(stA.rom) { delete[] stA.rom; stA.rom = 0; }
|
||||
if(stA.ram) { delete[] stA.ram; stA.ram = 0; }
|
||||
if(stB.rom) { delete[] stB.rom; stB.rom = 0; }
|
||||
if(stB.ram) { delete[] stB.ram; stB.ram = 0; }
|
||||
|
||||
char fn[PATH_MAX];
|
||||
strcpy(fn, cart.fn);
|
||||
modify_extension(fn, "cht");
|
||||
if(cheat.count() > 0 || fexists(get_cheat_filename(cart.fn, "cht"))) {
|
||||
cheat.save(cheatfn);
|
||||
cheat.clear();
|
||||
}
|
||||
|
||||
cart.loaded = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Cartridge::Cartridge() {
|
||||
cart.loaded = false;
|
||||
}
|
||||
|
||||
Cartridge::~Cartridge() {
|
||||
if(cart.loaded == true) unload();
|
||||
}
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
class Cartridge {
|
||||
public:
|
||||
enum CartridgeType {
|
||||
CartridgeNormal,
|
||||
CartridgeBSX,
|
||||
CartridgeBSC,
|
||||
CartridgeSufamiTurbo,
|
||||
};
|
||||
|
||||
enum HeaderField {
|
||||
CART_NAME = 0x00,
|
||||
MAPPER = 0x15,
|
||||
ROM_TYPE = 0x16,
|
||||
ROM_SIZE = 0x17,
|
||||
RAM_SIZE = 0x18,
|
||||
REGION = 0x19,
|
||||
COMPANY = 0x1a,
|
||||
VERSION = 0x1b,
|
||||
ICKSUM = 0x1c,
|
||||
CKSUM = 0x1e,
|
||||
RESL = 0x3c,
|
||||
RESH = 0x3d,
|
||||
};
|
||||
|
||||
enum Region {
|
||||
NTSC,
|
||||
PAL,
|
||||
};
|
||||
|
||||
enum MemoryMapper {
|
||||
LoROM,
|
||||
HiROM,
|
||||
ExLoROM,
|
||||
ExHiROM,
|
||||
BSXROM,
|
||||
BSCLoROM,
|
||||
BSCHiROM,
|
||||
STROM,
|
||||
};
|
||||
|
||||
enum DSP1MemoryMapper {
|
||||
DSP1Unmapped,
|
||||
DSP1LoROM1MB,
|
||||
DSP1LoROM2MB,
|
||||
DSP1HiROM,
|
||||
};
|
||||
|
||||
struct {
|
||||
bool loaded;
|
||||
char fn[PATH_MAX];
|
||||
uint8 *rom, *ram;
|
||||
uint rom_size, ram_size;
|
||||
} cart;
|
||||
|
||||
struct {
|
||||
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;
|
||||
|
||||
uint32 crc32;
|
||||
char filename[PATH_MAX * 4];
|
||||
char name[128];
|
||||
|
||||
Region region;
|
||||
MemoryMapper mapper;
|
||||
uint rom_size;
|
||||
uint ram_size;
|
||||
|
||||
bool bsxbase;
|
||||
bool bsxcart;
|
||||
bool bsxflash;
|
||||
bool st;
|
||||
bool superfx;
|
||||
bool sa1;
|
||||
bool srtc;
|
||||
bool sdd1;
|
||||
bool spc7110;
|
||||
bool cx4;
|
||||
bool dsp1;
|
||||
bool dsp2;
|
||||
bool dsp3;
|
||||
bool dsp4;
|
||||
bool obc1;
|
||||
bool st010;
|
||||
bool st011;
|
||||
bool st018;
|
||||
|
||||
DSP1MemoryMapper dsp1_mapper;
|
||||
|
||||
uint header_index;
|
||||
} info;
|
||||
|
||||
MemoryMapper mapper();
|
||||
Region region();
|
||||
|
||||
void load_cart_normal(const char*);
|
||||
void load_cart_bsx(const char*, const char*);
|
||||
void load_cart_bsc(const char*, const char*);
|
||||
void load_cart_st(const char*, const char*, const char*);
|
||||
|
||||
void unload_cart_normal();
|
||||
void unload_cart_bsx();
|
||||
void unload_cart_bsc();
|
||||
void unload_cart_st();
|
||||
|
||||
bool loaded();
|
||||
void load_begin(CartridgeType);
|
||||
void load_end();
|
||||
bool unload();
|
||||
|
||||
void find_header();
|
||||
void read_header();
|
||||
void read_extended_header();
|
||||
|
||||
enum CompressionMode {
|
||||
CompressionNone, //always load without compression
|
||||
CompressionInspect, //use file header inspection
|
||||
CompressionAuto, //use file extension or file header inspection (configured by user)
|
||||
};
|
||||
bool load_file(const char *fn, uint8 *&data, uint &size, CompressionMode compression = CompressionNone);
|
||||
bool save_file(const char *fn, uint8 *data, uint size);
|
||||
bool apply_patch(const uint8_t *pdata, unsigned psize, uint8_t *&data, unsigned &size);
|
||||
char* modify_extension(char *filename, const char *extension);
|
||||
char* get_base_filename(char *filename);
|
||||
char* get_path_filename(char *filename, const char *path, const char *source, const char *extension);
|
||||
char* get_patch_filename(const char *source, const char *extension);
|
||||
char* get_save_filename(const char *source, const char *extension);
|
||||
char* get_cheat_filename(const char *source, const char *extension);
|
||||
|
||||
Cartridge();
|
||||
~Cartridge();
|
||||
|
||||
private:
|
||||
char patchfn[PATH_MAX];
|
||||
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;
|
||||
@@ -0,0 +1,65 @@
|
||||
#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, CompressionAuto);
|
||||
cart.rom = data, cart.rom_size = size;
|
||||
|
||||
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||
apply_patch(data, size, cart.rom, cart.rom_size);
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
if(*bs.fn) {
|
||||
if(load_file(bs.fn, data, size, CompressionAuto) == true) {
|
||||
info.bsxflash = true;
|
||||
bs.ram = data, bs.ram_size = size;
|
||||
if(load_file(get_patch_filename(bs.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||
apply_patch(data, size, bs.ram, bs.ram_size);
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
find_header();
|
||||
read_header();
|
||||
|
||||
info.mapper = cartridge.info.header_index == 0x7fc0 ? BSCLoROM : BSCHiROM;
|
||||
info.region = NTSC;
|
||||
|
||||
if(info.ram_size > 0) {
|
||||
cart.ram = new uint8_t[cart.ram_size = info.ram_size];
|
||||
memset(cart.ram, 0xff, cart.ram_size);
|
||||
|
||||
if(load_file(get_save_filename(cart.fn, "srm"), data, size, CompressionNone) == true) {
|
||||
memcpy(cart.ram, data, min(size, cart.ram_size));
|
||||
delete[] 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
|
||||
@@ -0,0 +1,61 @@
|
||||
#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, CompressionAuto);
|
||||
cart.rom = data, cart.rom_size = size;
|
||||
cart.ram = 0, cart.ram_size = 0;
|
||||
|
||||
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||
apply_patch(data, size, cart.rom, cart.rom_size);
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
memset(bsxcart.sram.handle (), 0x00, bsxcart.sram.size ());
|
||||
memset(bsxcart.psram.handle(), 0x00, bsxcart.psram.size());
|
||||
|
||||
if(load_file(get_save_filename(cart.fn, "srm"), data, size, CompressionNone) == true) {
|
||||
memcpy(bsxcart.sram.handle (), data, min(bsxcart.sram.size (), size));
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
if(load_file(get_save_filename(cart.fn, "psr"), data, size, CompressionNone) == true) {
|
||||
memcpy(bsxcart.psram.handle(), data, min(bsxcart.psram.size(), size));
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
if(*bs.fn) {
|
||||
if(load_file(bs.fn, data, size, CompressionAuto) == true) {
|
||||
info.bsxflash = true;
|
||||
bs.ram = data, bs.ram_size = size;
|
||||
if(load_file(get_patch_filename(bs.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||
apply_patch(data, size, bs.ram, bs.ram_size);
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@@ -0,0 +1,179 @@
|
||||
#ifdef CART_CPP
|
||||
|
||||
#include "../reader/filereader.h"
|
||||
|
||||
#if defined(GZIP_SUPPORT)
|
||||
#include "../reader/gzreader.h"
|
||||
#include "../reader/zipreader.h"
|
||||
#endif
|
||||
|
||||
#if defined(JMA_SUPPORT)
|
||||
#include "../reader/jmareader.h"
|
||||
#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_patch_filename(const char *source, const char *extension) {
|
||||
return get_path_filename(patchfn, config::path.patch, source, extension);
|
||||
}
|
||||
|
||||
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, CompressionMode compression) {
|
||||
dprintf("* Loading \"%s\" ...", fn);
|
||||
|
||||
if(fexists(fn) == false) return false;
|
||||
|
||||
Reader::Type filetype = Reader::Normal;
|
||||
if(compression == CompressionInspect) filetype = Reader::detect(fn, true);
|
||||
if(compression == CompressionAuto) filetype = Reader::detect(fn, config::file.autodetect_type);
|
||||
|
||||
switch(filetype) {
|
||||
default:
|
||||
dprintf("* Warning: filetype detected as unsupported compression type.");
|
||||
dprintf("* Will attempt to load as uncompressed file -- may fail.");
|
||||
case Reader::Normal: {
|
||||
FileReader ff(fn);
|
||||
if(!ff.ready()) {
|
||||
alert("Error loading image file (%s)!", fn);
|
||||
return false;
|
||||
}
|
||||
size = ff.size();
|
||||
data = ff.read();
|
||||
} break;
|
||||
|
||||
#ifdef GZIP_SUPPORT
|
||||
case Reader::GZIP: {
|
||||
GZReader gf(fn);
|
||||
if(!gf.ready()) {
|
||||
alert("Error loading image file (%s)!", fn);
|
||||
return false;
|
||||
}
|
||||
size = gf.size();
|
||||
data = gf.read();
|
||||
} break;
|
||||
|
||||
case Reader::ZIP: {
|
||||
ZipReader zf(fn);
|
||||
size = zf.size();
|
||||
data = zf.read();
|
||||
} break;
|
||||
#endif
|
||||
|
||||
#ifdef JMA_SUPPORT
|
||||
case Reader::JMA: {
|
||||
try {
|
||||
JMAReader jf(fn);
|
||||
size = jf.size();
|
||||
data = jf.read();
|
||||
} catch(JMA::jma_errors jma_error) {
|
||||
alert("Error loading image file (%s)!", fn);
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cartridge::apply_patch(const uint8_t *pdata, const unsigned psize, uint8_t *&data, unsigned &size) {
|
||||
uint8_t *outdata = 0;
|
||||
unsigned outsize;
|
||||
ups patcher;
|
||||
ups::result result = patcher.apply(pdata, psize, data, size, outdata, outsize);
|
||||
|
||||
bool apply = false;
|
||||
if(result == ups::ok) apply = true;
|
||||
if(config::file.bypass_patch_crc32 == true) {
|
||||
if(result == ups::input_crc32_invalid) apply = true;
|
||||
if(result == ups::output_crc32_invalid) apply = true;
|
||||
}
|
||||
|
||||
if(apply == true) {
|
||||
delete[] data;
|
||||
data = new uint8_t[size = outsize];
|
||||
memcpy(data, outdata, outsize);
|
||||
} else {
|
||||
dprintf("* Warning: patch application failed!");
|
||||
}
|
||||
|
||||
if(outdata) delete[] outdata;
|
||||
}
|
||||
|
||||
bool Cartridge::save_file(const char *fn, uint8 *data, uint size) {
|
||||
FILE *fp = fopen(fn, "wb");
|
||||
if(!fp) return false;
|
||||
fwrite(data, 1, size, fp);
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif //ifdef CART_CPP
|
||||
@@ -0,0 +1,194 @@
|
||||
#ifdef CART_CPP
|
||||
|
||||
void Cartridge::read_header() {
|
||||
uint8 *rom = cart.rom;
|
||||
uint index = info.header_index;
|
||||
uint8 mapper = rom[index + MAPPER];
|
||||
uint8 rom_type = rom[index + ROM_TYPE];
|
||||
uint8 company = rom[index + COMPANY];
|
||||
uint8 region = rom[index + REGION] & 0x7f;
|
||||
|
||||
//detect presence of BS-X flash cartridge connector (reads extended header information)
|
||||
bool has_bsxflash = false;
|
||||
if(rom[index - 14] == 'Z') {
|
||||
if(rom[index - 11] == 'J') {
|
||||
uint8 n13 = rom[index - 13];
|
||||
if((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9')) {
|
||||
if(company == 0x33 || (rom[index - 10] == 0x00 && rom[index - 4] == 0x00)) {
|
||||
has_bsxflash = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(has_bsxflash == true) {
|
||||
info.mapper = index == 0x7fc0 ? BSCLoROM : BSCHiROM;
|
||||
} else if(index == 0x7fc0 && cart.rom_size >= 0x401000) {
|
||||
info.mapper = ExLoROM;
|
||||
} else if(index == 0x7fc0 && mapper == 0x32) {
|
||||
info.mapper = ExLoROM;
|
||||
} else if(index == 0x7fc0) {
|
||||
info.mapper = LoROM;
|
||||
} else if(index == 0xffc0) {
|
||||
info.mapper = HiROM;
|
||||
} else { //index == 0x40ffc0
|
||||
info.mapper = ExHiROM;
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && (rom_type == 0x13 || rom_type == 0x14 || rom_type == 0x15 || rom_type == 0x1a)) {
|
||||
info.superfx = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x23 && (rom_type == 0x34 || rom_type == 0x35)) {
|
||||
info.sa1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x35 && rom_type == 0x55) {
|
||||
info.srtc = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
|
||||
info.sdd1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x3a && (rom_type == 0xf5 || rom_type == 0xf9)) {
|
||||
//rom_type: 0xf5 = no S-RTC, 0xf9 = S-RTC
|
||||
info.spc7110 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && rom_type == 0xf3) {
|
||||
info.cx4 = true;
|
||||
}
|
||||
|
||||
if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x05 && company != 0xb2) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(info.dsp1 == true) {
|
||||
if((mapper & 0x2f) == 0x20 && cart.rom_size <= 0x100000) {
|
||||
info.dsp1_mapper = DSP1LoROM1MB;
|
||||
} else if((mapper & 0x2f) == 0x20) {
|
||||
info.dsp1_mapper = DSP1LoROM2MB;
|
||||
} else if((mapper & 0x2f) == 0x21) {
|
||||
info.dsp1_mapper = DSP1HiROM;
|
||||
}
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && rom_type == 0x05) {
|
||||
info.dsp2 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x05 && company == 0xb2) {
|
||||
info.dsp3 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x03) {
|
||||
info.dsp4 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x25) {
|
||||
info.obc1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0xf6) {
|
||||
//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) {
|
||||
info.ram_size = 1024 << (rom[info.header_index + RAM_SIZE] & 7);
|
||||
} else {
|
||||
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);
|
||||
info.name[21] = 0;
|
||||
trim(info.name);
|
||||
|
||||
//convert undisplayable characters (half-width katakana, etc) to '?' characters
|
||||
for(int i = 0; i < 21; i++) {
|
||||
if(info.name[i] & 0x80) info.name[i] = '?';
|
||||
}
|
||||
|
||||
//always display something
|
||||
if(!info.name[0]) strcpy(info.name, "(untitled)");
|
||||
}
|
||||
|
||||
void Cartridge::find_header() {
|
||||
int32 score_lo = 0, score_hi = 0, score_ex = 0;
|
||||
uint8_t *rom = cart.rom;
|
||||
|
||||
if(cart.rom_size < 0x010000) {
|
||||
//cart too small to be anything but lorom
|
||||
info.header_index = 0x007fc0;
|
||||
return;
|
||||
}
|
||||
|
||||
if((rom[0x7fc0 + MAPPER] & ~0x10) == 0x20) score_lo++;
|
||||
if((rom[0xffc0 + MAPPER] & ~0x10) == 0x21) score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + ROM_TYPE] < 0x08) score_lo++;
|
||||
if(rom[0xffc0 + ROM_TYPE] < 0x08) score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + ROM_SIZE] < 0x10) score_lo++;
|
||||
if(rom[0xffc0 + ROM_SIZE] < 0x10) score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + RAM_SIZE] < 0x08) score_lo++;
|
||||
if(rom[0xffc0 + RAM_SIZE] < 0x08) score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + REGION] < 14) score_lo++;
|
||||
if(rom[0xffc0 + REGION] < 14) score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + COMPANY] < 3) score_lo++;
|
||||
if(rom[0xffc0 + COMPANY] < 3) score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + RESH] & 0x80) score_lo += 2;
|
||||
if(rom[0xffc0 + RESH] & 0x80) score_hi += 2;
|
||||
|
||||
uint16 cksum, icksum;
|
||||
cksum = rom[0x7fc0 + CKSUM] | (rom[0x7fc0 + CKSUM + 1] << 8);
|
||||
icksum = rom[0x7fc0 + ICKSUM] | (rom[0x7fc0 + ICKSUM + 1] << 8);
|
||||
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
|
||||
score_lo += 8;
|
||||
}
|
||||
|
||||
cksum = rom[0xffc0 + CKSUM] | (rom[0xffc0 + CKSUM + 1] << 8);
|
||||
icksum = rom[0xffc0 + ICKSUM] | (rom[0xffc0 + ICKSUM + 1] << 8);
|
||||
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
|
||||
score_hi += 8;
|
||||
}
|
||||
|
||||
if(cart.rom_size < 0x401000) {
|
||||
score_ex = 0;
|
||||
} else {
|
||||
if(rom[0x7fc0 + MAPPER] == 0x32) score_lo++;
|
||||
else score_ex += 16;
|
||||
}
|
||||
|
||||
if(score_lo >= score_hi && score_lo >= score_ex) {
|
||||
info.header_index = 0x007fc0;
|
||||
} else if(score_hi >= score_ex) {
|
||||
info.header_index = 0x00ffc0;
|
||||
} else {
|
||||
info.header_index = 0x40ffc0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef CART_CPP
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifdef CART_CPP
|
||||
|
||||
void Cartridge::load_cart_normal(const char *filename) {
|
||||
if(!filename || !*filename) return;
|
||||
|
||||
uint8_t *data = 0;
|
||||
unsigned size;
|
||||
if(load_file(filename, data, size, CompressionAuto) == false) return;
|
||||
strcpy(cart.fn, filename);
|
||||
|
||||
load_begin(CartridgeNormal);
|
||||
|
||||
//load ROM data, ignore 512-byte header if detected
|
||||
if((size & 0x7fff) != 512) {
|
||||
cart.rom = new uint8_t[cart.rom_size = size];
|
||||
memcpy(cart.rom, data, size);
|
||||
} else {
|
||||
cart.rom = new uint8_t[cart.rom_size = size - 512];
|
||||
memcpy(cart.rom, data + 512, size - 512);
|
||||
}
|
||||
delete[] data;
|
||||
|
||||
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||
apply_patch(data, size, cart.rom, cart.rom_size);
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
info.crc32 = crc32_calculate(cart.rom, cart.rom_size);
|
||||
|
||||
find_header();
|
||||
read_header();
|
||||
|
||||
if(info.ram_size > 0) {
|
||||
cart.ram = new uint8_t[cart.ram_size = info.ram_size];
|
||||
memset(cart.ram, 0xff, cart.ram_size);
|
||||
|
||||
if(load_file(get_save_filename(cart.fn, "srm"), data, size, CompressionNone) == true) {
|
||||
memcpy(cart.ram, data, min(size, cart.ram_size));
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
|
||||
load_end();
|
||||
|
||||
//set base filename
|
||||
strcpy(info.filename, cart.fn);
|
||||
get_base_filename(info.filename);
|
||||
}
|
||||
|
||||
void Cartridge::unload_cart_normal() {
|
||||
if(cart.ram) save_file(get_save_filename(cart.fn, "srm"), cart.ram, cart.ram_size);
|
||||
}
|
||||
|
||||
#endif //ifdef CART_CPP
|
||||
@@ -0,0 +1,96 @@
|
||||
#ifdef CART_CPP
|
||||
|
||||
void Cartridge::load_cart_st(const char *base, const char *slotA, const char *slotB) {
|
||||
if(!base || !*base) return;
|
||||
|
||||
strcpy(cart.fn, base);
|
||||
strcpy(stA.fn, slotA ? slotA : "");
|
||||
strcpy(stB.fn, slotB ? slotB : "");
|
||||
|
||||
load_begin(CartridgeSufamiTurbo);
|
||||
info.st = true;
|
||||
info.mapper = STROM;
|
||||
info.region = NTSC;
|
||||
|
||||
uint8_t *data = 0;
|
||||
unsigned size;
|
||||
if(load_file(cart.fn, data, size, CompressionAuto) == true) {
|
||||
cart.rom = new(zeromemory) uint8_t[cart.rom_size = 0x040000];
|
||||
memcpy(cart.rom, data, min(size, cart.rom_size));
|
||||
delete[] data;
|
||||
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||
apply_patch(data, size, cart.rom, cart.rom_size);
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
|
||||
if(*stA.fn) {
|
||||
if(load_file(stA.fn, data, size, CompressionAuto) == true) {
|
||||
stA.rom = new(zeromemory) uint8_t[stA.rom_size = 0x100000];
|
||||
memcpy(stA.rom, data, min(size, stA.rom_size));
|
||||
delete[] data;
|
||||
if(load_file(get_patch_filename(stA.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||
apply_patch(data, size, stA.rom, stA.rom_size);
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
stA.ram = new uint8_t[stA.ram_size = 0x020000];
|
||||
memset(stA.ram, 0xff, stA.ram_size);
|
||||
|
||||
if(load_file(get_save_filename(stA.fn, "srm"), data, size, CompressionNone) == true) {
|
||||
memcpy(stA.ram, data, min(size, 0x020000U));
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(*stB.fn) {
|
||||
if(load_file(stB.fn, data, size, CompressionAuto) == true) {
|
||||
stB.rom = new(zeromemory) uint8_t[stB.rom_size = 0x100000];
|
||||
memcpy(stB.rom, data, min(size, stB.rom_size));
|
||||
delete[] data;
|
||||
if(load_file(get_patch_filename(stB.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||
apply_patch(data, size, stB.rom, stB.rom_size);
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
stB.ram = new uint8_t[stB.ram_size = 0x020000];
|
||||
memset(stB.ram, 0xff, stB.ram_size);
|
||||
|
||||
if(load_file(get_save_filename(stB.fn, "srm"), data, size, CompressionNone) == true) {
|
||||
memcpy(stB.ram, data, min(size, 0x020000U));
|
||||
delete[] 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::unload_cart_st() {
|
||||
if(stA.ram) save_file(get_save_filename(stA.fn, "srm"), stA.ram, stA.ram_size);
|
||||
if(stB.ram) save_file(get_save_filename(stB.fn, "srm"), stB.ram, stB.ram_size);
|
||||
}
|
||||
|
||||
#endif //ifdef CART_CPP
|
||||
@@ -0,0 +1,3 @@
|
||||
@make platform=win compiler=mingw32-gcc
|
||||
::@make platform=win compiler=mingw32-gcc enable_gzip=true enable_jma=true
|
||||
@pause
|
||||
@@ -0,0 +1,2 @@
|
||||
make platform=x compiler=gcc
|
||||
#make platform=x compiler=gcc enable_gzip=true enable_jma=true
|
||||
@@ -0,0 +1,329 @@
|
||||
#include "../base.h"
|
||||
#include "../reader/filereader.h"
|
||||
|
||||
Cheat cheat;
|
||||
|
||||
/*****
|
||||
* string <> binary code translation routines
|
||||
* decode() "7e1234:56" -> 0x7e123456
|
||||
* encode() 0x7e123456 -> "7e1234:56"
|
||||
*****/
|
||||
|
||||
bool Cheat::decode(char *str, uint32 &addr, uint8 &data, uint8 &type) {
|
||||
string t, part;
|
||||
strcpy(t, str);
|
||||
strlower(t());
|
||||
if(strlen(t) == 8 || (strlen(t) == 9 && t()[6] == ':')) {
|
||||
type = ProActionReplay;
|
||||
replace(t, ":", "");
|
||||
uint32 r = strhex((const char*)t);
|
||||
addr = r >> 8;
|
||||
data = r & 0xff;
|
||||
return true;
|
||||
} else if(strlen(t) == 9 && t()[4] == '-') {
|
||||
type = GameGenie;
|
||||
replace(t, "-", "");
|
||||
strtr(t, "df4709156bc8a23e", "0123456789abcdef");
|
||||
uint32 r = strhex((const char*)t);
|
||||
//8421 8421 8421 8421 8421 8421
|
||||
//abcd efgh ijkl mnop qrst uvwx
|
||||
//ijkl qrst opab cduv wxef ghmn
|
||||
addr = (!!(r & 0x002000) << 23) | (!!(r & 0x001000) << 22) |
|
||||
(!!(r & 0x000800) << 21) | (!!(r & 0x000400) << 20) |
|
||||
(!!(r & 0x000020) << 19) | (!!(r & 0x000010) << 18) |
|
||||
(!!(r & 0x000008) << 17) | (!!(r & 0x000004) << 16) |
|
||||
(!!(r & 0x800000) << 15) | (!!(r & 0x400000) << 14) |
|
||||
(!!(r & 0x200000) << 13) | (!!(r & 0x100000) << 12) |
|
||||
(!!(r & 0x000002) << 11) | (!!(r & 0x000001) << 10) |
|
||||
(!!(r & 0x008000) << 9) | (!!(r & 0x004000) << 8) |
|
||||
(!!(r & 0x080000) << 7) | (!!(r & 0x040000) << 6) |
|
||||
(!!(r & 0x020000) << 5) | (!!(r & 0x010000) << 4) |
|
||||
(!!(r & 0x000200) << 3) | (!!(r & 0x000100) << 2) |
|
||||
(!!(r & 0x000080) << 1) | (!!(r & 0x000040) << 0);
|
||||
data = r >> 24;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Cheat::encode(char *str, uint32 addr, uint8 data, uint8 type) {
|
||||
if(type == ProActionReplay) {
|
||||
sprintf(str, "%0.6x:%0.2x", addr, data);
|
||||
return true;
|
||||
} else if(type == GameGenie) {
|
||||
uint32 r = addr;
|
||||
addr = (!!(r & 0x008000) << 23) | (!!(r & 0x004000) << 22) |
|
||||
(!!(r & 0x002000) << 21) | (!!(r & 0x001000) << 20) |
|
||||
(!!(r & 0x000080) << 19) | (!!(r & 0x000040) << 18) |
|
||||
(!!(r & 0x000020) << 17) | (!!(r & 0x000010) << 16) |
|
||||
(!!(r & 0x000200) << 15) | (!!(r & 0x000100) << 14) |
|
||||
(!!(r & 0x800000) << 13) | (!!(r & 0x400000) << 12) |
|
||||
(!!(r & 0x200000) << 11) | (!!(r & 0x100000) << 10) |
|
||||
(!!(r & 0x000008) << 9) | (!!(r & 0x000004) << 8) |
|
||||
(!!(r & 0x000002) << 7) | (!!(r & 0x000001) << 6) |
|
||||
(!!(r & 0x080000) << 5) | (!!(r & 0x040000) << 4) |
|
||||
(!!(r & 0x020000) << 3) | (!!(r & 0x010000) << 2) |
|
||||
(!!(r & 0x000800) << 1) | (!!(r & 0x000400) << 0);
|
||||
sprintf(str, "%0.2x%0.2x-%0.4x", data, addr >> 16, addr & 0xffff);
|
||||
strtr(str, "0123456789abcdef", "df4709156bc8a23e");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*****
|
||||
* address lookup table manipulation and mirroring
|
||||
* mirror_address() 0x000000 -> 0x7e0000
|
||||
* set() enable specified address, mirror accordingly
|
||||
* clear() disable specified address, mirror accordingly
|
||||
*****/
|
||||
|
||||
uint Cheat::mirror_address(uint addr) {
|
||||
if((addr & 0x40e000) != 0x0000) return addr;
|
||||
//8k WRAM mirror
|
||||
//$[00-3f|80-bf]:[0000-1fff] -> $7e:[0000-1fff]
|
||||
return (0x7e0000 + (addr & 0x1fff));
|
||||
}
|
||||
|
||||
void Cheat::set(uint32 addr) {
|
||||
addr = mirror_address(addr);
|
||||
|
||||
mask[addr >> 3] |= 1 << (addr & 7);
|
||||
if((addr & 0xffe000) == 0x7e0000) {
|
||||
//mirror $7e:[0000-1fff] to $[00-3f|80-bf]:[0000-1fff]
|
||||
uint mirror;
|
||||
for(int x = 0; x <= 0x3f; x++) {
|
||||
mirror = ((0x00 + x) << 16) + (addr & 0x1fff);
|
||||
mask[mirror >> 3] |= 1 << (mirror & 7);
|
||||
mirror = ((0x80 + x) << 16) + (addr & 0x1fff);
|
||||
mask[mirror >> 3] |= 1 << (mirror & 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cheat::clear(uint32 addr) {
|
||||
addr = mirror_address(addr);
|
||||
|
||||
//is there more than one cheat code using the same address
|
||||
//(and likely a different override value) that is enabled?
|
||||
//if so, do not clear code lookup table entry for this address.
|
||||
uint8 r;
|
||||
if(read(addr, r) == true)return;
|
||||
|
||||
mask[addr >> 3] &= ~(1 << (addr & 7));
|
||||
if((addr & 0xffe000) == 0x7e0000) {
|
||||
//mirror $7e:[0000-1fff] to $[00-3f|80-bf]:[0000-1fff]
|
||||
uint mirror;
|
||||
for(int x = 0; x <= 0x3f; x++) {
|
||||
mirror = ((0x00 + x) << 16) + (addr & 0x1fff);
|
||||
mask[mirror >> 3] &= ~(1 << (mirror & 7));
|
||||
mirror = ((0x80 + x) << 16) + (addr & 0x1fff);
|
||||
mask[mirror >> 3] &= ~(1 << (mirror & 7));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****
|
||||
* read() is used by MemBus::read() if Cheat::enabled(addr)
|
||||
* returns true to look up cheat code.
|
||||
* returns true if cheat code was found, false if it was not.
|
||||
* when true, cheat code substitution value is stored in data.
|
||||
*****/
|
||||
|
||||
bool Cheat::read(uint32 addr, uint8 &data) {
|
||||
addr = mirror_address(addr);
|
||||
for(int i = 0; i < cheat_count; i++) {
|
||||
if(enabled(i) == false) continue;
|
||||
if(addr == mirror_address(index[i].addr)) {
|
||||
data = index[i].data;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//code not found, or code is disabled
|
||||
return false;
|
||||
}
|
||||
|
||||
/*****
|
||||
* update_cheat_status() will scan to see if any codes are
|
||||
* enabled. if any are, make sure the cheat system is on.
|
||||
* otherwise, turn cheat system off to speed up emulation.
|
||||
*****/
|
||||
|
||||
void Cheat::update_cheat_status() {
|
||||
for(unsigned i = 0; i < cheat_count; i++) {
|
||||
if(index[i].enabled) {
|
||||
cheat_enabled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
cheat_enabled = false;
|
||||
}
|
||||
|
||||
/*****
|
||||
* cheat list manipulation routines
|
||||
*****/
|
||||
|
||||
bool Cheat::add(bool enable, char *code, char *desc) {
|
||||
if(cheat_count >= CheatLimit) return false;
|
||||
|
||||
uint32 addr, len;
|
||||
uint8 data, type;
|
||||
if(decode(code, addr, data, type) == false) return false;
|
||||
|
||||
index[cheat_count].enabled = enable;
|
||||
index[cheat_count].addr = addr;
|
||||
index[cheat_count].data = data;
|
||||
len = strlen(code);
|
||||
len = len > 16 ? 16 : len;
|
||||
memcpy(index[cheat_count].code, code, len);
|
||||
index[cheat_count].code[len] = 0;
|
||||
len = strlen(desc);
|
||||
len = len > 128 ? 128 : len;
|
||||
memcpy(index[cheat_count].desc, desc, len);
|
||||
index[cheat_count].desc[len] = 0;
|
||||
cheat_count++;
|
||||
(enable) ? set(addr) : clear(addr);
|
||||
|
||||
update_cheat_status();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cheat::edit(uint32 n, bool enable, char *code, char *desc) {
|
||||
if(n >= cheat_count) return false;
|
||||
|
||||
uint32 addr, len;
|
||||
uint8 data, type;
|
||||
if(decode(code, addr, data, type) == false) return false;
|
||||
|
||||
//disable current code and clear from code lookup table
|
||||
index[n].enabled = false;
|
||||
clear(index[n].addr);
|
||||
|
||||
//update code and enable in code lookup table
|
||||
index[n].enabled = enable;
|
||||
index[n].addr = addr;
|
||||
index[n].data = data;
|
||||
len = strlen(code);
|
||||
len = len > 16 ? 16 : len;
|
||||
memcpy(index[n].code, code, len);
|
||||
index[n].code[len] = 0;
|
||||
len = strlen(desc);
|
||||
len = len > 128 ? 128 : len;
|
||||
memcpy(index[n].desc, desc, len);
|
||||
index[n].desc[len] = 0;
|
||||
set(addr);
|
||||
|
||||
update_cheat_status();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cheat::remove(uint32 n) {
|
||||
if(n >= cheat_count) return false;
|
||||
|
||||
for(unsigned i = n; i < cheat_count; i++) {
|
||||
index[i].enabled = index[i + 1].enabled;
|
||||
index[i].addr = index[i + 1].addr;
|
||||
index[i].data = index[i + 1].data;
|
||||
strcpy(index[i].desc, index[i + 1].desc);
|
||||
}
|
||||
|
||||
cheat_count--;
|
||||
|
||||
update_cheat_status();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cheat::get(uint32 n, bool &enable, uint32 &addr, uint8 &data, char *code, char *desc) {
|
||||
if(n >= cheat_count) return false;
|
||||
enable = index[n].enabled;
|
||||
addr = index[n].addr;
|
||||
data = index[n].data;
|
||||
strcpy(code, index[n].code);
|
||||
strcpy(desc, index[n].desc);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*****
|
||||
* code status modifier routines
|
||||
*****/
|
||||
|
||||
bool Cheat::enabled(uint32 n) {
|
||||
if(n >= cheat_count) return false;
|
||||
return index[n].enabled;
|
||||
}
|
||||
|
||||
void Cheat::enable(uint32 n) {
|
||||
if(n >= cheat_count) return;
|
||||
index[n].enabled = true;
|
||||
set(index[n].addr);
|
||||
update_cheat_status();
|
||||
}
|
||||
|
||||
void Cheat::disable(uint32 n) {
|
||||
if(n >= cheat_count) return;
|
||||
index[n].enabled = false;
|
||||
clear(index[n].addr);
|
||||
update_cheat_status();
|
||||
}
|
||||
|
||||
/*****
|
||||
* cheat file manipulation routines
|
||||
*****/
|
||||
|
||||
/* file format: */
|
||||
/* nnnn-nnnn = status, "description" \r\n */
|
||||
/* ... */
|
||||
|
||||
bool Cheat::load(const char *fn) {
|
||||
string data;
|
||||
if(!fread(data, fn)) return false;
|
||||
replace(data, "\r\n", "\n");
|
||||
qreplace(data, "=", ",");
|
||||
qreplace(data, " ", "");
|
||||
|
||||
lstring line;
|
||||
split(line, "\n", data);
|
||||
for(unsigned i = 0; i < ::count(line); i++) {
|
||||
lstring part;
|
||||
split(part, ",", line[i]);
|
||||
if(::count(part) != 3) continue;
|
||||
trim(part[2], "\"");
|
||||
add(part[1] == "enabled", part[0](), part[2]());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cheat::save(const char *fn) {
|
||||
FILE *fp = fopen(fn, "wb");
|
||||
if(!fp) return false;
|
||||
for(unsigned i = 0; i < cheat_count; i++) {
|
||||
fprintf(fp, "%9s = %8s, \"%s\"\r\n",
|
||||
index[i].code,
|
||||
index[i].enabled ? "enabled" : "disabled",
|
||||
index[i].desc);
|
||||
}
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*****
|
||||
* initialization routines
|
||||
*****/
|
||||
|
||||
void Cheat::clear() {
|
||||
cheat_enabled = false;
|
||||
cheat_count = 0;
|
||||
memset(mask, 0, 0x200000);
|
||||
for(unsigned i = 0; i <= CheatLimit; i++) {
|
||||
index[i].enabled = false;
|
||||
index[i].addr = 0x000000;
|
||||
index[i].data = 0x00;
|
||||
strcpy(index[i].code, "");
|
||||
strcpy(index[i].desc, "");
|
||||
}
|
||||
}
|
||||
|
||||
Cheat::Cheat() {
|
||||
clear();
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
class Cheat {
|
||||
public:
|
||||
enum { CheatLimit = 1024 };
|
||||
|
||||
enum Type {
|
||||
ProActionReplay,
|
||||
GameGenie,
|
||||
};
|
||||
|
||||
struct CheatIndex {
|
||||
bool enabled;
|
||||
uint32 addr;
|
||||
uint8 data;
|
||||
char code[ 16 + 1];
|
||||
char desc[128 + 1];
|
||||
} index[CheatLimit + 1];
|
||||
|
||||
bool cheat_enabled;
|
||||
uint32 cheat_count;
|
||||
uint8 mask[0x200000];
|
||||
|
||||
inline bool enabled() { return cheat_enabled; }
|
||||
inline uint count() { return cheat_count; }
|
||||
inline bool exists(uint32 addr) { return bool(mask[addr >> 3] & 1 << (addr & 7)); }
|
||||
|
||||
bool decode(char *str, uint32 &addr, uint8 &data, uint8 &type);
|
||||
bool encode(char *str, uint32 addr, uint8 data, uint8 type);
|
||||
|
||||
bool read(uint32 addr, uint8 &data);
|
||||
|
||||
void update_cheat_status();
|
||||
bool add(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 remove(uint32 n);
|
||||
bool enabled(uint32 n);
|
||||
void enable(uint32 n);
|
||||
void disable(uint32 n);
|
||||
bool load(const char *fn);
|
||||
bool save(const char *fn);
|
||||
void clear();
|
||||
|
||||
Cheat();
|
||||
|
||||
private:
|
||||
uint mirror_address(uint addr);
|
||||
void set(uint32 addr);
|
||||
void clear(uint32 addr);
|
||||
};
|
||||
|
||||
extern Cheat cheat;
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "../../base.h"
|
||||
#define BSX_CPP
|
||||
|
||||
#include "bsx_base.cpp"
|
||||
#include "bsx_cart.cpp"
|
||||
#include "bsx_flash.cpp"
|
||||
@@ -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;
|
||||
@@ -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
|
||||
@@ -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 = new uint8_t[ 32 * 1024];
|
||||
psram_data = new uint8_t[512 * 1024];
|
||||
|
||||
sram.map (sram_data, 32 * 1024);
|
||||
psram.map(psram_data, 512 * 1024);
|
||||
}
|
||||
|
||||
BSXCart::~BSXCart() {
|
||||
delete[] sram_data;
|
||||
delete[] psram_data;
|
||||
}
|
||||
|
||||
#endif //ifdef BSX_CPP
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
C4 emulation
|
||||
|
||||
Used in Rockman X2/X3 (Megaman X2/X3)
|
||||
Portions (c) anomie, Overload, zsKnight, Nach, byuu
|
||||
*/
|
||||
|
||||
#include "../../base.h"
|
||||
#define CX4_CPP
|
||||
|
||||
#include "cx4data.cpp"
|
||||
#include "cx4fn.cpp"
|
||||
#include "cx4oam.cpp"
|
||||
#include "cx4ops.cpp"
|
||||
|
||||
void Cx4::init() {}
|
||||
void Cx4::enable() {}
|
||||
|
||||
uint32 Cx4::ldr(uint8 r) {
|
||||
uint16 addr = 0x0080 + (r * 3);
|
||||
return (reg[addr]) | (reg[addr + 1] << 8) | (reg[addr + 2] << 16);
|
||||
}
|
||||
|
||||
void Cx4::str(uint8 r, uint32 data) {
|
||||
uint16 addr = 0x0080 + (r * 3);
|
||||
reg[addr ] = (data);
|
||||
reg[addr + 1] = (data >> 8);
|
||||
reg[addr + 2] = (data >> 16);
|
||||
}
|
||||
|
||||
void Cx4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) {
|
||||
int64 rx = x & 0xffffff;
|
||||
int64 ry = y & 0xffffff;
|
||||
if(rx & 0x800000)rx |= ~0x7fffff;
|
||||
if(ry & 0x800000)ry |= ~0x7fffff;
|
||||
|
||||
rx *= ry;
|
||||
|
||||
rl = (rx) & 0xffffff;
|
||||
rh = (rx >> 24) & 0xffffff;
|
||||
}
|
||||
|
||||
uint32 Cx4::sin(uint32 rx) {
|
||||
r0 = rx & 0x1ff;
|
||||
if(r0 & 0x100)r0 ^= 0x1ff;
|
||||
if(r0 & 0x080)r0 ^= 0x0ff;
|
||||
if(rx & 0x100) {
|
||||
return sin_table[r0 + 0x80];
|
||||
} else {
|
||||
return sin_table[r0];
|
||||
}
|
||||
}
|
||||
|
||||
uint32 Cx4::cos(uint32 rx) {
|
||||
return sin(rx + 0x080);
|
||||
}
|
||||
|
||||
void Cx4::immediate_reg(uint32 start) {
|
||||
r0 = ldr(0);
|
||||
for(uint32 i = start; i < 48; i++) {
|
||||
if((r0 & 0x0fff) < 0x0c00) {
|
||||
ram[r0 & 0x0fff] = immediate_data[i];
|
||||
}
|
||||
r0++;
|
||||
}
|
||||
str(0, r0);
|
||||
}
|
||||
|
||||
void Cx4::transfer_data() {
|
||||
uint32 src;
|
||||
uint16 dest, count;
|
||||
src = (reg[0x40]) | (reg[0x41] << 8) | (reg[0x42] << 16);
|
||||
count = (reg[0x43]) | (reg[0x44] << 8);
|
||||
dest = (reg[0x45]) | (reg[0x46] << 8);
|
||||
|
||||
for(uint32 i=0;i<count;i++) {
|
||||
write(dest++, bus.read(src++));
|
||||
}
|
||||
}
|
||||
|
||||
void Cx4::write(uint addr, uint8 data) {
|
||||
addr &= 0x1fff;
|
||||
|
||||
if(addr < 0x0c00) {
|
||||
//ram
|
||||
ram[addr] = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr < 0x1f00) {
|
||||
//unmapped
|
||||
return;
|
||||
}
|
||||
|
||||
//command register
|
||||
reg[addr & 0xff] = data;
|
||||
|
||||
if(addr == 0x1f47) {
|
||||
//memory transfer
|
||||
transfer_data();
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x1f4f) {
|
||||
//c4 command
|
||||
if(reg[0x4d] == 0x0e && !(data & 0xc3)) {
|
||||
//c4 test command
|
||||
reg[0x80] = data >> 2;
|
||||
return;
|
||||
}
|
||||
|
||||
switch(data) {
|
||||
case 0x00: op00(); break;
|
||||
case 0x01: op01(); break;
|
||||
case 0x05: op05(); break;
|
||||
case 0x0d: op0d(); break;
|
||||
case 0x10: op10(); break;
|
||||
case 0x13: op13(); break;
|
||||
case 0x15: op15(); break;
|
||||
case 0x1f: op1f(); break;
|
||||
case 0x22: op22(); break;
|
||||
case 0x25: op25(); break;
|
||||
case 0x2d: op2d(); break;
|
||||
case 0x40: op40(); break;
|
||||
case 0x54: op54(); break;
|
||||
case 0x5c: op5c(); break;
|
||||
case 0x5e: op5e(); break;
|
||||
case 0x60: op60(); break;
|
||||
case 0x62: op62(); break;
|
||||
case 0x64: op64(); break;
|
||||
case 0x66: op66(); break;
|
||||
case 0x68: op68(); break;
|
||||
case 0x6a: op6a(); break;
|
||||
case 0x6c: op6c(); break;
|
||||
case 0x6e: op6e(); break;
|
||||
case 0x70: op70(); break;
|
||||
case 0x72: op72(); break;
|
||||
case 0x74: op74(); break;
|
||||
case 0x76: op76(); break;
|
||||
case 0x78: op78(); break;
|
||||
case 0x7a: op7a(); break;
|
||||
case 0x7c: op7c(); break;
|
||||
case 0x89: op89(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cx4::writeb(uint16 addr, uint8 data) {
|
||||
write(addr, data);
|
||||
}
|
||||
|
||||
void Cx4::writew(uint16 addr, uint16 data) {
|
||||
write(addr, data);
|
||||
write(addr + 1, data >> 8);
|
||||
}
|
||||
|
||||
void Cx4::writel(uint16 addr, uint32 data) {
|
||||
write(addr, data);
|
||||
write(addr + 1, data >> 8);
|
||||
write(addr + 2, data >> 16);
|
||||
}
|
||||
|
||||
uint8 Cx4::read(uint addr) {
|
||||
addr &= 0x1fff;
|
||||
|
||||
if(addr < 0x0c00) {
|
||||
return ram[addr];
|
||||
}
|
||||
|
||||
if(addr >= 0x1f00) {
|
||||
return reg[addr & 0xff];
|
||||
}
|
||||
|
||||
return cpu.regs.mdr;
|
||||
}
|
||||
|
||||
uint8 Cx4::readb(uint16 addr) {
|
||||
return read(addr);
|
||||
}
|
||||
|
||||
uint16 Cx4::readw(uint16 addr) {
|
||||
return read(addr) | (read(addr + 1) << 8);
|
||||
}
|
||||
|
||||
uint32 Cx4::readl(uint16 addr) {
|
||||
return read(addr) | (read(addr + 1) << 8) + (read(addr + 2) << 16);
|
||||
}
|
||||
|
||||
void Cx4::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void Cx4::reset() {
|
||||
memset(ram, 0, 0x0c00);
|
||||
memset(reg, 0, 0x0100);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
class Cx4 : public Memory {
|
||||
private:
|
||||
uint8 ram[0x0c00];
|
||||
uint8 reg[0x0100];
|
||||
uint32 r0, r1, r2, r3, r4, r5, r6, r7,
|
||||
r8, r9, r10, r11, r12, r13, r14, r15;
|
||||
|
||||
static const uint8 immediate_data[48];
|
||||
static const uint16 wave_data[40];
|
||||
static const uint32 sin_table[256];
|
||||
|
||||
static const int16 SinTable[512];
|
||||
static const int16 CosTable[512];
|
||||
|
||||
int16 C4WFXVal, C4WFYVal, C4WFZVal, C4WFX2Val, C4WFY2Val, C4WFDist, C4WFScale;
|
||||
int16 C41FXVal, C41FYVal, C41FAngleRes, C41FDist, C41FDistVal;
|
||||
|
||||
double tanval;
|
||||
double c4x,c4y,c4z, c4x2,c4y2,c4z2;
|
||||
|
||||
void C4TransfWireFrame();
|
||||
void C4TransfWireFrame2();
|
||||
void C4CalcWireFrame();
|
||||
void C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color);
|
||||
void C4DrawWireFrame();
|
||||
void C4DoScaleRotate(int row_padding);
|
||||
|
||||
public:
|
||||
uint32 ldr(uint8 r);
|
||||
void str(uint8 r, uint32 data);
|
||||
void mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh);
|
||||
uint32 sin(uint32 rx);
|
||||
uint32 cos(uint32 rx);
|
||||
|
||||
void transfer_data();
|
||||
void immediate_reg(uint32 num);
|
||||
|
||||
void op00_00();
|
||||
void op00_03();
|
||||
void op00_05();
|
||||
void op00_07();
|
||||
void op00_08();
|
||||
void op00_0b();
|
||||
void op00_0c();
|
||||
|
||||
void op00();
|
||||
void op01();
|
||||
void op05();
|
||||
void op0d();
|
||||
void op10();
|
||||
void op13();
|
||||
void op15();
|
||||
void op1f();
|
||||
void op22();
|
||||
void op25();
|
||||
void op2d();
|
||||
void op40();
|
||||
void op54();
|
||||
void op5c();
|
||||
void op5e();
|
||||
void op60();
|
||||
void op62();
|
||||
void op64();
|
||||
void op66();
|
||||
void op68();
|
||||
void op6a();
|
||||
void op6c();
|
||||
void op6e();
|
||||
void op70();
|
||||
void op72();
|
||||
void op74();
|
||||
void op76();
|
||||
void op78();
|
||||
void op7a();
|
||||
void op7c();
|
||||
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 enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 read (uint addr);
|
||||
void write(uint addr, uint8 data);
|
||||
};
|
||||
|
||||
extern Cx4 cx4;
|
||||
@@ -0,0 +1,187 @@
|
||||
#ifdef CX4_CPP
|
||||
|
||||
const uint8 Cx4::immediate_data[48] = {
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
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, 0x00, 0x01, 0xff, 0xff, 0xfe, 0x00, 0x01, 0x00, 0xff, 0xfe, 0x00
|
||||
};
|
||||
|
||||
const uint16 Cx4::wave_data[40] = {
|
||||
0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e,
|
||||
0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020a, 0x020c, 0x020e,
|
||||
0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040a, 0x040c, 0x040e,
|
||||
0x0600, 0x0602, 0x0604, 0x0606, 0x0608, 0x060a, 0x060c, 0x060e,
|
||||
0x0800, 0x0802, 0x0804, 0x0806, 0x0808, 0x080a, 0x080c, 0x080e
|
||||
};
|
||||
|
||||
const uint32 Cx4::sin_table[256] = {
|
||||
0x000000, 0x000324, 0x000648, 0x00096c, 0x000c8f, 0x000fb2, 0x0012d5, 0x0015f6,
|
||||
0x001917, 0x001c37, 0x001f56, 0x002273, 0x002590, 0x0028aa, 0x002bc4, 0x002edb,
|
||||
0x0031f1, 0x003505, 0x003817, 0x003b26, 0x003e33, 0x00413e, 0x004447, 0x00474d,
|
||||
0x004a50, 0x004d50, 0x00504d, 0x005347, 0x00563e, 0x005931, 0x005c22, 0x005f0e,
|
||||
0x0061f7, 0x0064dc, 0x0067bd, 0x006a9b, 0x006d74, 0x007049, 0x007319, 0x0075e5,
|
||||
0x0078ad, 0x007b70, 0x007e2e, 0x0080e7, 0x00839c, 0x00864b, 0x0088f5, 0x008b9a,
|
||||
0x008e39, 0x0090d3, 0x009368, 0x0095f6, 0x00987f, 0x009b02, 0x009d7f, 0x009ff6,
|
||||
0x00a267, 0x00a4d2, 0x00a736, 0x00a994, 0x00abeb, 0x00ae3b, 0x00b085, 0x00b2c8,
|
||||
0x00b504, 0x00b73a, 0x00b968, 0x00bb8f, 0x00bdae, 0x00bfc7, 0x00c1d8, 0x00c3e2,
|
||||
0x00c5e4, 0x00c7de, 0x00c9d1, 0x00cbbb, 0x00cd9f, 0x00cf7a, 0x00d14d, 0x00d318,
|
||||
0x00d4db, 0x00d695, 0x00d848, 0x00d9f2, 0x00db94, 0x00dd2d, 0x00debe, 0x00e046,
|
||||
0x00e1c5, 0x00e33c, 0x00e4aa, 0x00e60f, 0x00e76b, 0x00e8bf, 0x00ea09, 0x00eb4b,
|
||||
0x00ec83, 0x00edb2, 0x00eed8, 0x00eff5, 0x00f109, 0x00f213, 0x00f314, 0x00f40b,
|
||||
0x00f4fa, 0x00f5de, 0x00f6ba, 0x00f78b, 0x00f853, 0x00f912, 0x00f9c7, 0x00fa73,
|
||||
0x00fb14, 0x00fbac, 0x00fc3b, 0x00fcbf, 0x00fd3a, 0x00fdab, 0x00fe13, 0x00fe70,
|
||||
0x00fec4, 0x00ff0e, 0x00ff4e, 0x00ff84, 0x00ffb1, 0x00ffd3, 0x00ffec, 0x00fffb,
|
||||
0x000000, 0xfffcdb, 0xfff9b7, 0xfff693, 0xfff370, 0xfff04d, 0xffed2a, 0xffea09,
|
||||
0xffe6e8, 0xffe3c8, 0xffe0a9, 0xffdd8c, 0xffda6f, 0xffd755, 0xffd43b, 0xffd124,
|
||||
0xffce0e, 0xffcafa, 0xffc7e8, 0xffc4d9, 0xffc1cc, 0xffbec1, 0xffbbb8, 0xffb8b2,
|
||||
0xffb5af, 0xffb2af, 0xffafb2, 0xffacb8, 0xffa9c1, 0xffa6ce, 0xffa3dd, 0xffa0f1,
|
||||
0xff9e08, 0xff9b23, 0xff9842, 0xff9564, 0xff928b, 0xff8fb6, 0xff8ce6, 0xff8a1a,
|
||||
0xff8752, 0xff848f, 0xff81d1, 0xff7f18, 0xff7c63, 0xff79b4, 0xff770a, 0xff7465,
|
||||
0xff71c6, 0xff6f2c, 0xff6c97, 0xff6a09, 0xff6780, 0xff64fd, 0xff6280, 0xff6009,
|
||||
0xff5d98, 0xff5b2d, 0xff58c9, 0xff566b, 0xff5414, 0xff51c4, 0xff4f7a, 0xff4d37,
|
||||
0xff4afb, 0xff48c5, 0xff4697, 0xff4470, 0xff4251, 0xff4038, 0xff3e27, 0xff3c1e,
|
||||
0xff3a1b, 0xff3821, 0xff362e, 0xff3444, 0xff3260, 0xff3085, 0xff2eb2, 0xff2ce7,
|
||||
0xff2b24, 0xff296a, 0xff27b7, 0xff260d, 0xff246b, 0xff22d2, 0xff2141, 0xff1fb9,
|
||||
0xff1e3a, 0xff1cc3, 0xff1b55, 0xff19f0, 0xff1894, 0xff1740, 0xff15f6, 0xff14b4,
|
||||
0xff137c, 0xff124d, 0xff1127, 0xff100a, 0xff0ef6, 0xff0dec, 0xff0ceb, 0xff0bf4,
|
||||
0xff0b05, 0xff0a21, 0xff0945, 0xff0874, 0xff07ac, 0xff06ed, 0xff0638, 0xff058d,
|
||||
0xff04eb, 0xff0453, 0xff03c4, 0xff0340, 0xff02c5, 0xff0254, 0xff01ec, 0xff018f,
|
||||
0xff013b, 0xff00f1, 0xff00b1, 0xff007b, 0xff004e, 0xff002c, 0xff0013, 0xff0004
|
||||
};
|
||||
|
||||
const int16 Cx4::SinTable[512] = {
|
||||
0, 402, 804, 1206, 1607, 2009, 2410, 2811,
|
||||
3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997,
|
||||
6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126,
|
||||
9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167,
|
||||
12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090,
|
||||
15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869,
|
||||
18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475,
|
||||
20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884,
|
||||
23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073,
|
||||
25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020,
|
||||
27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707,
|
||||
28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117,
|
||||
30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237,
|
||||
31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057,
|
||||
32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568,
|
||||
32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765,
|
||||
32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647,
|
||||
32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214,
|
||||
32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471,
|
||||
31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425,
|
||||
30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086,
|
||||
28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466,
|
||||
27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583,
|
||||
25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453,
|
||||
23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097,
|
||||
20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537,
|
||||
18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800,
|
||||
15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910,
|
||||
12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896,
|
||||
9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786,
|
||||
6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611,
|
||||
3211, 2811, 2410, 2009, 1607, 1206, 804, 402,
|
||||
0, -402, -804, -1206, -1607, -2009, -2410, -2811,
|
||||
-3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997,
|
||||
-6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126,
|
||||
-9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167,
|
||||
-12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090,
|
||||
-15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869,
|
||||
-18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475,
|
||||
-20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884,
|
||||
-23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073,
|
||||
-25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020,
|
||||
-27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707,
|
||||
-28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117,
|
||||
-30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237,
|
||||
-31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057,
|
||||
-32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568,
|
||||
-32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765,
|
||||
-32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647,
|
||||
-32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214,
|
||||
-32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471,
|
||||
-31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425,
|
||||
-30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086,
|
||||
-28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466,
|
||||
-27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583,
|
||||
-25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453,
|
||||
-23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097,
|
||||
-20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537,
|
||||
-18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800,
|
||||
-15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910,
|
||||
-12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896,
|
||||
-9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786,
|
||||
-6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611,
|
||||
-3211, -2811, -2410, -2009, -1607, -1206, -804, -402
|
||||
};
|
||||
|
||||
const int16 Cx4::CosTable[512] = {
|
||||
32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647,
|
||||
32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214,
|
||||
32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471,
|
||||
31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425,
|
||||
30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086,
|
||||
28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466,
|
||||
27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583,
|
||||
25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453,
|
||||
23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097,
|
||||
20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537,
|
||||
18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800,
|
||||
15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910,
|
||||
12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896,
|
||||
9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786,
|
||||
6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611,
|
||||
3211, 2811, 2410, 2009, 1607, 1206, 804, 402,
|
||||
0, -402, -804, -1206, -1607, -2009, -2410, -2811,
|
||||
-3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997,
|
||||
-6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126,
|
||||
-9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167,
|
||||
-12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090,
|
||||
-15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869,
|
||||
-18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475,
|
||||
-20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884,
|
||||
-23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073,
|
||||
-25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020,
|
||||
-27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707,
|
||||
-28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117,
|
||||
-30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237,
|
||||
-31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057,
|
||||
-32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568,
|
||||
-32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765,
|
||||
-32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647,
|
||||
-32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214,
|
||||
-32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471,
|
||||
-31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425,
|
||||
-30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086,
|
||||
-28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466,
|
||||
-27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583,
|
||||
-25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453,
|
||||
-23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097,
|
||||
-20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537,
|
||||
-18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800,
|
||||
-15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910,
|
||||
-12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896,
|
||||
-9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786,
|
||||
-6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611,
|
||||
-3211, -2811, -2410, -2009, -1607, -1206, -804, -402,
|
||||
0, 402, 804, 1206, 1607, 2009, 2410, 2811,
|
||||
3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997,
|
||||
6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126,
|
||||
9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167,
|
||||
12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090,
|
||||
15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869,
|
||||
18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475,
|
||||
20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884,
|
||||
23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073,
|
||||
25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020,
|
||||
27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707,
|
||||
28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117,
|
||||
30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237,
|
||||
31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057,
|
||||
32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568,
|
||||
32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765
|
||||
};
|
||||
|
||||
#endif //ifdef CX4_CPP
|
||||
@@ -0,0 +1,246 @@
|
||||
#ifdef CX4_CPP
|
||||
|
||||
#include <math.h>
|
||||
#define Tan(a) (CosTable[a] ? ((((int32)SinTable[a]) << 16) / CosTable[a]) : 0x80000000)
|
||||
#define sar(b, n) ((b) >> (n))
|
||||
#ifdef PI
|
||||
#undef PI
|
||||
#endif
|
||||
#define PI 3.1415926535897932384626433832795
|
||||
|
||||
//Wireframe Helpers
|
||||
void Cx4::C4TransfWireFrame() {
|
||||
c4x = (double)C4WFXVal;
|
||||
c4y = (double)C4WFYVal;
|
||||
c4z = (double)C4WFZVal - 0x95;
|
||||
|
||||
//Rotate X
|
||||
tanval = -(double)C4WFX2Val * PI * 2 / 128;
|
||||
c4y2 = c4y * ::cos(tanval) - c4z * ::sin(tanval);
|
||||
c4z2 = c4y * ::sin(tanval) + c4z * ::cos(tanval);
|
||||
|
||||
//Rotate Y
|
||||
tanval = -(double)C4WFY2Val * PI * 2 / 128;
|
||||
c4x2 = c4x * ::cos(tanval) + c4z2 * ::sin(tanval);
|
||||
c4z = c4x * -::sin(tanval) + c4z2 * ::cos(tanval);
|
||||
|
||||
//Rotate Z
|
||||
tanval = -(double)C4WFDist * PI * 2 / 128;
|
||||
c4x = c4x2 * ::cos(tanval) - c4y2 * ::sin(tanval);
|
||||
c4y = c4x2 * ::sin(tanval) + c4y2 * ::cos(tanval);
|
||||
|
||||
//Scale
|
||||
C4WFXVal = (int16)(c4x * C4WFScale / (0x90 * (c4z + 0x95)) * 0x95);
|
||||
C4WFYVal = (int16)(c4y * C4WFScale / (0x90 * (c4z + 0x95)) * 0x95);
|
||||
}
|
||||
|
||||
void Cx4::C4CalcWireFrame() {
|
||||
C4WFXVal = C4WFX2Val - C4WFXVal;
|
||||
C4WFYVal = C4WFY2Val - C4WFYVal;
|
||||
|
||||
if(abs(C4WFXVal) > abs(C4WFYVal)) {
|
||||
C4WFDist = abs(C4WFXVal) + 1;
|
||||
C4WFYVal = (256 * (long)C4WFYVal) / abs(C4WFXVal);
|
||||
C4WFXVal = (C4WFXVal < 0) ? -256 : 256;
|
||||
} else if(C4WFYVal != 0) {
|
||||
C4WFDist = abs(C4WFYVal) + 1;
|
||||
C4WFXVal = (256 * (long)C4WFXVal) / abs(C4WFYVal);
|
||||
C4WFYVal = (C4WFYVal < 0) ? -256 : 256;
|
||||
} else {
|
||||
C4WFDist = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Cx4::C4TransfWireFrame2() {
|
||||
c4x = (double)C4WFXVal;
|
||||
c4y = (double)C4WFYVal;
|
||||
c4z = (double)C4WFZVal;
|
||||
|
||||
//Rotate X
|
||||
tanval = -(double)C4WFX2Val * PI * 2 / 128;
|
||||
c4y2 = c4y * ::cos(tanval) - c4z * ::sin(tanval);
|
||||
c4z2 = c4y * ::sin(tanval) + c4z * ::cos(tanval);
|
||||
|
||||
//Rotate Y
|
||||
tanval = -(double)C4WFY2Val * PI * 2 / 128;
|
||||
c4x2 = c4x * ::cos(tanval) + c4z2 * ::sin(tanval);
|
||||
c4z = c4x * -::sin(tanval) + c4z2 * ::cos(tanval);
|
||||
|
||||
//Rotate Z
|
||||
tanval = -(double)C4WFDist * PI * 2 / 128;
|
||||
c4x = c4x2 * ::cos(tanval) - c4y2 * ::sin(tanval);
|
||||
c4y = c4x2 * ::sin(tanval) + c4y2 * ::cos(tanval);
|
||||
|
||||
//Scale
|
||||
C4WFXVal = (int16)(c4x * C4WFScale / 0x100);
|
||||
C4WFYVal = (int16)(c4y * C4WFScale / 0x100);
|
||||
}
|
||||
|
||||
void Cx4::C4DrawWireFrame() {
|
||||
uint32 line = readl(0x1f80);
|
||||
uint32 point1, point2;
|
||||
int16 X1, Y1, Z1;
|
||||
int16 X2, Y2, Z2;
|
||||
uint8 Color;
|
||||
for(int32 i = ram[0x0295]; i > 0; i--, line += 5) {
|
||||
if(bus.read(line) == 0xff && bus.read(line + 1) == 0xff) {
|
||||
int32 tmp = line - 5;
|
||||
while(bus.read(tmp + 2) == 0xff && bus.read(tmp + 3) == 0xff && (tmp + 2) >= 0) { tmp -= 5; }
|
||||
point1 = (read(0x1f82) << 16) | (bus.read(tmp + 2) << 8) | bus.read(tmp + 3);
|
||||
} else {
|
||||
point1 = (read(0x1f82) << 16) | (bus.read(line) << 8) | bus.read(line + 1);
|
||||
}
|
||||
point2 = (read(0x1f82) << 16) | (bus.read(line + 2) << 8) | bus.read(line + 3);
|
||||
|
||||
X1=(bus.read(point1 + 0) << 8) | bus.read(point1 + 1);
|
||||
Y1=(bus.read(point1 + 2) << 8) | bus.read(point1 + 3);
|
||||
Z1=(bus.read(point1 + 4) << 8) | bus.read(point1 + 5);
|
||||
X2=(bus.read(point2 + 0) << 8) | bus.read(point2 + 1);
|
||||
Y2=(bus.read(point2 + 2) << 8) | bus.read(point2 + 3);
|
||||
Z2=(bus.read(point2 + 4) << 8) | bus.read(point2 + 5);
|
||||
Color = bus.read(line + 4);
|
||||
C4DrawLine(X1, Y1, Z1, X2, Y2, Z2, Color);
|
||||
}
|
||||
}
|
||||
|
||||
void Cx4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color) {
|
||||
//Transform coordinates
|
||||
C4WFXVal = (int16)X1;
|
||||
C4WFYVal = (int16)Y1;
|
||||
C4WFZVal = Z1;
|
||||
C4WFScale = read(0x1f90);
|
||||
C4WFX2Val = read(0x1f86);
|
||||
C4WFY2Val = read(0x1f87);
|
||||
C4WFDist = read(0x1f88);
|
||||
C4TransfWireFrame2();
|
||||
X1 = (C4WFXVal + 48) << 8;
|
||||
Y1 = (C4WFYVal + 48) << 8;
|
||||
|
||||
C4WFXVal = (int16)X2;
|
||||
C4WFYVal = (int16)Y2;
|
||||
C4WFZVal = Z2;
|
||||
C4TransfWireFrame2();
|
||||
X2 = (C4WFXVal + 48) << 8;
|
||||
Y2 = (C4WFYVal + 48) << 8;
|
||||
|
||||
//Get line info
|
||||
C4WFXVal = (int16)(X1 >> 8);
|
||||
C4WFYVal = (int16)(Y1 >> 8);
|
||||
C4WFX2Val = (int16)(X2 >> 8);
|
||||
C4WFY2Val = (int16)(Y2 >> 8);
|
||||
C4CalcWireFrame();
|
||||
X2 = (int16)C4WFXVal;
|
||||
Y2 = (int16)C4WFYVal;
|
||||
|
||||
//Render line
|
||||
for(int32 i = C4WFDist ? C4WFDist : 1; i > 0; i--) {
|
||||
if(X1 > 0xff && Y1 > 0xff && X1 < 0x6000 && Y1 < 0x6000) {
|
||||
uint16 addr = (((Y1 >> 8) >> 3) << 8) - (((Y1 >> 8) >> 3) << 6) + (((X1 >> 8) >> 3) << 4) + ((Y1 >> 8) & 7) * 2;
|
||||
uint8 bit = 0x80 >> ((X1 >> 8) & 7);
|
||||
ram[addr + 0x300] &= ~bit;
|
||||
ram[addr + 0x301] &= ~bit;
|
||||
if(Color & 1) { ram[addr + 0x300] |= bit; }
|
||||
if(Color & 2) { ram[addr + 0x301] |= bit; }
|
||||
}
|
||||
X1 += X2;
|
||||
Y1 += Y2;
|
||||
}
|
||||
}
|
||||
|
||||
void Cx4::C4DoScaleRotate(int row_padding) {
|
||||
int16 A, B, C, D;
|
||||
|
||||
//Calculate matrix
|
||||
int32 XScale = readw(0x1f8f);
|
||||
int32 YScale = readw(0x1f92);
|
||||
if(XScale & 0x8000)XScale = 0x7fff;
|
||||
if(YScale & 0x8000)YScale = 0x7fff;
|
||||
|
||||
if(readw(0x1f80) == 0) { //no rotation
|
||||
A = (int16)XScale;
|
||||
B = 0;
|
||||
C = 0;
|
||||
D = (int16)YScale;
|
||||
} else if(readw(0x1f80) == 128) { //90 degree rotation
|
||||
A = 0;
|
||||
B = (int16)(-YScale);
|
||||
C = (int16)XScale;
|
||||
D = 0;
|
||||
} else if(readw(0x1f80) == 256) { //180 degree rotation
|
||||
A = (int16)(-XScale);
|
||||
B = 0;
|
||||
C = 0;
|
||||
D = (int16)(-YScale);
|
||||
} else if(readw(0x1f80) == 384) { //270 degree rotation
|
||||
A = 0;
|
||||
B = (int16)YScale;
|
||||
C = (int16)(-XScale);
|
||||
D = 0;
|
||||
} else {
|
||||
A = (int16) sar(CosTable[readw(0x1f80) & 0x1ff] * XScale, 15);
|
||||
B = (int16)(-sar(SinTable[readw(0x1f80) & 0x1ff] * YScale, 15));
|
||||
C = (int16) sar(SinTable[readw(0x1f80) & 0x1ff] * XScale, 15);
|
||||
D = (int16) sar(CosTable[readw(0x1f80) & 0x1ff] * YScale, 15);
|
||||
}
|
||||
|
||||
//Calculate Pixel Resolution
|
||||
uint8 w = read(0x1f89) & ~7;
|
||||
uint8 h = read(0x1f8c) & ~7;
|
||||
|
||||
//Clear the output RAM
|
||||
memset(ram, 0, (w + row_padding / 4) * h / 2);
|
||||
|
||||
int32 Cx = (int16)readw(0x1f83);
|
||||
int32 Cy = (int16)readw(0x1f86);
|
||||
|
||||
//Calculate start position (i.e. (Ox, Oy) = (0, 0))
|
||||
//The low 12 bits are fractional, so (Cx<<12) gives us the Cx we want in
|
||||
//the function. We do Cx*A etc normally because the matrix parameters
|
||||
//already have the fractional parts.
|
||||
int32 LineX = (Cx << 12) - Cx * A - Cx * B;
|
||||
int32 LineY = (Cy << 12) - Cy * C - Cy * D;
|
||||
|
||||
//Start loop
|
||||
uint32 X, Y;
|
||||
uint8 byte;
|
||||
int32 outidx = 0;
|
||||
uint8 bit = 0x80;
|
||||
for(int32 y = 0; y < h; y++) {
|
||||
X = LineX;
|
||||
Y = LineY;
|
||||
for(int32 x = 0; x < w; x++) {
|
||||
if((X >> 12) >= w || (Y >> 12) >= h) {
|
||||
byte = 0;
|
||||
} else {
|
||||
uint32 addr = (Y >> 12) * w + (X >> 12);
|
||||
byte = read(0x600 + (addr >> 1));
|
||||
if(addr & 1) { byte >>= 4; }
|
||||
}
|
||||
|
||||
//De-bitplanify
|
||||
if(byte & 1) { ram[outidx ] |= bit; }
|
||||
if(byte & 2) { ram[outidx + 1] |= bit; }
|
||||
if(byte & 4) { ram[outidx + 16] |= bit; }
|
||||
if(byte & 8) { ram[outidx + 17] |= bit; }
|
||||
|
||||
bit >>= 1;
|
||||
if(!bit) {
|
||||
bit = 0x80;
|
||||
outidx += 32;
|
||||
}
|
||||
|
||||
X += A; //Add 1 to output x => add an A and a C
|
||||
Y += C;
|
||||
}
|
||||
outidx += 2 + row_padding;
|
||||
if(outidx & 0x10) {
|
||||
outidx &= ~0x10;
|
||||
} else {
|
||||
outidx -= w * 4 + row_padding;
|
||||
}
|
||||
LineX += B; //Add 1 to output y => add a B and a D
|
||||
LineY += D;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef CX4_CPP
|
||||
@@ -0,0 +1,223 @@
|
||||
#ifdef CX4_CPP
|
||||
|
||||
//Build OAM
|
||||
void Cx4::op00_00() {
|
||||
uint32 oamptr = ram[0x626] << 2;
|
||||
for(int32 i = 0x1fd; i > oamptr && i >= 0; i -= 4) {
|
||||
//clear oam-to-be
|
||||
if(i >= 0)ram[i] = 0xe0;
|
||||
}
|
||||
|
||||
uint16 globalx, globaly;
|
||||
uint32 oamptr2;
|
||||
int16 sprx, spry;
|
||||
uint8 sprname, sprattr;
|
||||
uint8 sprcount;
|
||||
globalx = readw(0x621);
|
||||
globaly = readw(0x623);
|
||||
oamptr2 = 0x200 + (ram[0x626] >> 2);
|
||||
|
||||
if(!ram[0x620])return;
|
||||
|
||||
sprcount = 128 - ram[0x626];
|
||||
uint8 offset = (ram[0x626] & 3) * 2;
|
||||
uint32 srcptr = 0x220;
|
||||
for(int i = ram[0x620]; i > 0 && sprcount > 0; i--, srcptr += 16) {
|
||||
sprx = readw(srcptr) - globalx;
|
||||
spry = readw(srcptr + 2) - globaly;
|
||||
sprname = ram[srcptr + 5];
|
||||
sprattr = ram[srcptr + 4] | ram[srcptr + 6];
|
||||
|
||||
uint32 spraddr = readl(srcptr + 7);
|
||||
if(bus.read(spraddr)) {
|
||||
int16 x, y;
|
||||
for(int sprcnt = bus.read(spraddr++); sprcnt > 0 && sprcount > 0; sprcnt--, spraddr += 4) {
|
||||
x = (int8)bus.read(spraddr + 1);
|
||||
if(sprattr & 0x40) {
|
||||
x = -x - ((bus.read(spraddr) & 0x20) ? 16 : 8);
|
||||
}
|
||||
x += sprx;
|
||||
if(x >= -16 && x <= 272) {
|
||||
y = (int8)bus.read(spraddr + 2);
|
||||
if(sprattr & 0x80) {
|
||||
y = -y - ((bus.read(spraddr) & 0x20) ? 16 : 8);
|
||||
}
|
||||
y += spry;
|
||||
if(y >= -16 && y <= 224) {
|
||||
ram[oamptr ] = (uint8)x;
|
||||
ram[oamptr + 1] = (uint8)y;
|
||||
ram[oamptr + 2] = sprname + bus.read(spraddr + 3);
|
||||
ram[oamptr + 3] = sprattr ^ (bus.read(spraddr) & 0xc0);
|
||||
ram[oamptr2] &= ~(3 << offset);
|
||||
if(x & 0x100)ram[oamptr2] |= 1 << offset;
|
||||
if(bus.read(spraddr) & 0x20)ram[oamptr2] |= 2 << offset;
|
||||
oamptr += 4;
|
||||
sprcount--;
|
||||
offset = (offset + 2) & 6;
|
||||
if(!offset)oamptr2++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(sprcount > 0) {
|
||||
ram[oamptr ] = (uint8)sprx;
|
||||
ram[oamptr + 1] = (uint8)spry;
|
||||
ram[oamptr + 2] = sprname;
|
||||
ram[oamptr + 3] = sprattr;
|
||||
ram[oamptr2] &= ~(3 << offset);
|
||||
if(sprx & 0x100)ram[oamptr2] |= 3 << offset;
|
||||
else ram[oamptr2] |= 2 << offset;
|
||||
oamptr += 4;
|
||||
sprcount--;
|
||||
offset = (offset + 2) & 6;
|
||||
if(!offset)oamptr2++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Scale and Rotate
|
||||
void Cx4::op00_03() {
|
||||
C4DoScaleRotate(0);
|
||||
}
|
||||
|
||||
//Transform Lines
|
||||
void Cx4::op00_05() {
|
||||
C4WFX2Val = read(0x1f83);
|
||||
C4WFY2Val = read(0x1f86);
|
||||
C4WFDist = read(0x1f89);
|
||||
C4WFScale = read(0x1f8c);
|
||||
|
||||
//Transform Vertices
|
||||
uint32 ptr = 0;
|
||||
for(int32 i = readw(0x1f80); i > 0; i--, ptr += 0x10) {
|
||||
C4WFXVal = readw(ptr + 1);
|
||||
C4WFYVal = readw(ptr + 5);
|
||||
C4WFZVal = readw(ptr + 9);
|
||||
C4TransfWireFrame();
|
||||
|
||||
//Displace
|
||||
writew(ptr + 1, C4WFXVal + 0x80);
|
||||
writew(ptr + 5, C4WFYVal + 0x50);
|
||||
}
|
||||
|
||||
writew(0x600, 23);
|
||||
writew(0x602, 0x60);
|
||||
writew(0x605, 0x40);
|
||||
writew(0x600 + 8, 23);
|
||||
writew(0x602 + 8, 0x60);
|
||||
writew(0x605 + 8, 0x40);
|
||||
|
||||
ptr = 0xb02;
|
||||
uint32 ptr2 = 0;
|
||||
for(int32 i = readw(0xb00); i > 0; i--, ptr += 2, ptr2 += 8) {
|
||||
C4WFXVal = readw((read(ptr + 0) << 4) + 1);
|
||||
C4WFYVal = readw((read(ptr + 0) << 4) + 5);
|
||||
C4WFX2Val = readw((read(ptr + 1) << 4) + 1);
|
||||
C4WFY2Val = readw((read(ptr + 1) << 4) + 5);
|
||||
C4CalcWireFrame();
|
||||
writew(ptr2 + 0x600, C4WFDist ? C4WFDist : 1);
|
||||
writew(ptr2 + 0x602, C4WFXVal);
|
||||
writew(ptr2 + 0x605, C4WFYVal);
|
||||
}
|
||||
}
|
||||
|
||||
//Scale and Rotate
|
||||
void Cx4::op00_07() {
|
||||
C4DoScaleRotate(64);
|
||||
}
|
||||
|
||||
//Draw Wireframe
|
||||
void Cx4::op00_08() {
|
||||
C4DrawWireFrame();
|
||||
}
|
||||
|
||||
//Disintegrate
|
||||
void Cx4::op00_0b() {
|
||||
uint8 width, height;
|
||||
uint32 startx, starty;
|
||||
uint32 srcptr;
|
||||
uint32 x, y;
|
||||
int32 scalex, scaley;
|
||||
int32 cx, cy;
|
||||
int32 i, j;
|
||||
width = read(0x1f89);
|
||||
height = read(0x1f8c);
|
||||
cx = readw(0x1f80);
|
||||
cy = readw(0x1f83);
|
||||
|
||||
scalex = (int16)readw(0x1f86);
|
||||
scaley = (int16)readw(0x1f8f);
|
||||
startx = -cx * scalex + (cx << 8);
|
||||
starty = -cy * scaley + (cy << 8);
|
||||
srcptr = 0x600;
|
||||
|
||||
for(i = 0; i < (width * height) >> 1; i++) {
|
||||
write(i, 0);
|
||||
}
|
||||
|
||||
for(y = starty, i = 0;i < height; i++, y += scaley) {
|
||||
for(x = startx, j = 0;j < width; j++, x += scalex) {
|
||||
if((x >> 8) < width && (y >> 8) < height && (y >> 8) * width + (x >> 8) < 0x2000) {
|
||||
uint8 pixel = (j & 1) ? (ram[srcptr] >> 4) : (ram[srcptr]);
|
||||
int32 index = (y >> 11) * width * 4 + (x >> 11) * 32 + ((y >> 8) & 7) * 2;
|
||||
uint8 mask = 0x80 >> ((x >> 8) & 7);
|
||||
if(pixel & 1)ram[index ] |= mask;
|
||||
if(pixel & 2)ram[index + 1] |= mask;
|
||||
if(pixel & 4)ram[index + 16] |= mask;
|
||||
if(pixel & 8)ram[index + 17] |= mask;
|
||||
}
|
||||
if(j & 1)srcptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Bitplane Wave
|
||||
void Cx4::op00_0c() {
|
||||
uint32 destptr = 0;
|
||||
uint32 waveptr = read(0x1f83);
|
||||
uint16 mask1 = 0xc0c0;
|
||||
uint16 mask2 = 0x3f3f;
|
||||
|
||||
for(int j = 0; j < 0x10; j++) {
|
||||
do {
|
||||
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
|
||||
for(int i = 0; i < 40; i++) {
|
||||
uint16 temp = readw(destptr + wave_data[i]) & mask2;
|
||||
if(height >= 0) {
|
||||
if(height < 8) {
|
||||
temp |= mask1 & readw(0xa00 + height * 2);
|
||||
} else {
|
||||
temp |= mask1 & 0xff00;
|
||||
}
|
||||
}
|
||||
writew(destptr + wave_data[i], temp);
|
||||
height++;
|
||||
}
|
||||
waveptr = (waveptr + 1) & 0x7f;
|
||||
mask1 = (mask1 >> 2) | (mask1 << 6);
|
||||
mask2 = (mask2 >> 2) | (mask2 << 6);
|
||||
} while(mask1 != 0xc0c0);
|
||||
destptr += 16;
|
||||
|
||||
do {
|
||||
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
|
||||
for(int i = 0; i < 40; i++) {
|
||||
uint16 temp = readw(destptr + wave_data[i]) & mask2;
|
||||
if(height >= 0) {
|
||||
if(height < 8) {
|
||||
temp |= mask1 & readw(0xa10 + height * 2);
|
||||
} else {
|
||||
temp |= mask1 & 0xff00;
|
||||
}
|
||||
}
|
||||
writew(destptr + wave_data[i], temp);
|
||||
height++;
|
||||
}
|
||||
waveptr = (waveptr + 1) & 0x7f;
|
||||
mask1 = (mask1 >> 2) | (mask1 << 6);
|
||||
mask2 = (mask2 >> 2) | (mask2 << 6);
|
||||
} while(mask1 != 0xc0c0);
|
||||
destptr += 16;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef CX4_CPP
|
||||
@@ -0,0 +1,226 @@
|
||||
#ifdef CX4_CPP
|
||||
|
||||
//Sprite Functions
|
||||
void Cx4::op00() {
|
||||
switch(reg[0x4d]) {
|
||||
case 0x00:op00_00();break;
|
||||
case 0x03:op00_03();break;
|
||||
case 0x05:op00_05();break;
|
||||
case 0x07:op00_07();break;
|
||||
case 0x08:op00_08();break;
|
||||
case 0x0b:op00_0b();break;
|
||||
case 0x0c:op00_0c();break;
|
||||
}
|
||||
}
|
||||
|
||||
//Draw Wireframe
|
||||
void Cx4::op01() {
|
||||
memset(ram + 0x300, 0, 2304);
|
||||
C4DrawWireFrame();
|
||||
}
|
||||
|
||||
//Propulsion
|
||||
void Cx4::op05() {
|
||||
int32 temp = 0x10000;
|
||||
if(readw(0x1f83)) {
|
||||
temp = sar((temp / readw(0x1f83)) * readw(0x1f81), 8);
|
||||
}
|
||||
writew(0x1f80, temp);
|
||||
}
|
||||
|
||||
//Set Vector length
|
||||
void Cx4::op0d() {
|
||||
C41FXVal = readw(0x1f80);
|
||||
C41FYVal = readw(0x1f83);
|
||||
C41FDistVal = readw(0x1f86);
|
||||
tanval = sqrt(((double)C41FYVal) * ((double)C41FYVal) + ((double)C41FXVal) * ((double)C41FXVal));
|
||||
tanval = (double)C41FDistVal / tanval;
|
||||
C41FYVal = (int16)(((double)C41FYVal * tanval) * 0.99);
|
||||
C41FXVal = (int16)(((double)C41FXVal * tanval) * 0.98);
|
||||
writew(0x1f89, C41FXVal);
|
||||
writew(0x1f8c, C41FYVal);
|
||||
}
|
||||
|
||||
//Triangle
|
||||
void Cx4::op10() {
|
||||
r0 = ldr(0);
|
||||
r1 = ldr(1);
|
||||
|
||||
r4 = r0 & 0x1ff;
|
||||
if(r1 & 0x8000)r1 |= ~0x7fff;
|
||||
|
||||
mul(cos(r4), r1, r5, r2);
|
||||
r5 = (r5 >> 16) & 0xff;
|
||||
r2 = (r2 << 8) + r5;
|
||||
|
||||
mul(sin(r4), r1, r5, r3);
|
||||
r5 = (r5 >> 16) & 0xff;
|
||||
r3 = (r3 << 8) + r5;
|
||||
|
||||
str(0, r0);
|
||||
str(1, r1);
|
||||
str(2, r2);
|
||||
str(3, r3);
|
||||
str(4, r4);
|
||||
str(5, r5);
|
||||
}
|
||||
|
||||
//Triangle
|
||||
void Cx4::op13() {
|
||||
r0 = ldr(0);
|
||||
r1 = ldr(1);
|
||||
|
||||
r4 = r0 & 0x1ff;
|
||||
|
||||
mul(cos(r4), r1, r5, r2);
|
||||
r5 = (r5 >> 8) & 0xffff;
|
||||
r2 = (r2 << 16) + r5;
|
||||
|
||||
mul(sin(r4), r1, r5, r3);
|
||||
r5 = (r5 >> 8) & 0xffff;
|
||||
r3 = (r3 << 16) + r5;
|
||||
|
||||
str(0, r0);
|
||||
str(1, r1);
|
||||
str(2, r2);
|
||||
str(3, r3);
|
||||
str(4, r4);
|
||||
str(5, r5);
|
||||
}
|
||||
|
||||
//Pythagorean
|
||||
void Cx4::op15() {
|
||||
C41FXVal = readw(0x1f80);
|
||||
C41FYVal = readw(0x1f83);
|
||||
C41FDist = (int16)sqrt((double)C41FXVal * (double)C41FXVal + (double)C41FYVal * (double)C41FYVal);
|
||||
writew(0x1f80, C41FDist);
|
||||
}
|
||||
|
||||
//Calculate distance
|
||||
void Cx4::op1f() {
|
||||
C41FXVal = readw(0x1f80);
|
||||
C41FYVal = readw(0x1f83);
|
||||
if(!C41FXVal) {
|
||||
C41FAngleRes = (C41FYVal > 0) ? 0x080 : 0x180;
|
||||
} else {
|
||||
tanval = ((double)C41FYVal) / ((double)C41FXVal);
|
||||
C41FAngleRes = (short)(atan(tanval) / (PI * 2) * 512);
|
||||
C41FAngleRes = C41FAngleRes;
|
||||
if(C41FXVal < 0) {
|
||||
C41FAngleRes += 0x100;
|
||||
}
|
||||
C41FAngleRes &= 0x1ff;
|
||||
}
|
||||
writew(0x1f86, C41FAngleRes);
|
||||
}
|
||||
|
||||
//Trapezoid
|
||||
void Cx4::op22() {
|
||||
int16 angle1 = readw(0x1f8c) & 0x1ff;
|
||||
int16 angle2 = readw(0x1f8f) & 0x1ff;
|
||||
int32 tan1 = Tan(angle1);
|
||||
int32 tan2 = Tan(angle2);
|
||||
int16 y = readw(0x1f83) - readw(0x1f89);
|
||||
int16 left, right;
|
||||
for(int32 j = 0; j < 225; j++, y++) {
|
||||
if(y >= 0) {
|
||||
left = sar((int32)tan1 * y, 16) - readw(0x1f80) + readw(0x1f86);
|
||||
right = sar((int32)tan2 * y, 16) - readw(0x1f80) + readw(0x1f86) + readw(0x1f93);
|
||||
|
||||
if(left < 0 && right < 0) {
|
||||
left = 1;
|
||||
right = 0;
|
||||
} else if(left < 0) {
|
||||
left = 0;
|
||||
} else if(right < 0) {
|
||||
right = 0;
|
||||
}
|
||||
|
||||
if(left > 255 && right > 255) {
|
||||
left = 255;
|
||||
right = 254;
|
||||
} else if(left > 255) {
|
||||
left = 255;
|
||||
} else if(right > 255) {
|
||||
right = 255;
|
||||
}
|
||||
} else {
|
||||
left = 1;
|
||||
right = 0;
|
||||
}
|
||||
ram[j + 0x800] = (uint8)left;
|
||||
ram[j + 0x900] = (uint8)right;
|
||||
}
|
||||
}
|
||||
|
||||
//Multiply
|
||||
void Cx4::op25() {
|
||||
r0 = ldr(0);
|
||||
r1 = ldr(1);
|
||||
mul(r0, r1, r0, r1);
|
||||
str(0, r0);
|
||||
str(1, r1);
|
||||
}
|
||||
|
||||
//Transform Coords
|
||||
void Cx4::op2d() {
|
||||
C4WFXVal = readw(0x1f81);
|
||||
C4WFYVal = readw(0x1f84);
|
||||
C4WFZVal = readw(0x1f87);
|
||||
C4WFX2Val = read (0x1f89);
|
||||
C4WFY2Val = read (0x1f8a);
|
||||
C4WFDist = read (0x1f8b);
|
||||
C4WFScale = readw(0x1f90);
|
||||
C4TransfWireFrame2();
|
||||
writew(0x1f80, C4WFXVal);
|
||||
writew(0x1f83, C4WFYVal);
|
||||
}
|
||||
|
||||
//Sum
|
||||
void Cx4::op40() {
|
||||
r0 = 0;
|
||||
for(uint32 i=0;i<0x800;i++) {
|
||||
r0 += ram[i];
|
||||
}
|
||||
str(0, r0);
|
||||
}
|
||||
|
||||
//Square
|
||||
void Cx4::op54() {
|
||||
r0 = ldr(0);
|
||||
mul(r0, r0, r1, r2);
|
||||
str(1, r1);
|
||||
str(2, r2);
|
||||
}
|
||||
|
||||
//Immediate Register
|
||||
void Cx4::op5c() {
|
||||
str(0, 0x000000);
|
||||
immediate_reg(0);
|
||||
}
|
||||
|
||||
//Immediate Register (Multiple)
|
||||
void Cx4::op5e() { immediate_reg( 0); }
|
||||
void Cx4::op60() { immediate_reg( 3); }
|
||||
void Cx4::op62() { immediate_reg( 6); }
|
||||
void Cx4::op64() { immediate_reg( 9); }
|
||||
void Cx4::op66() { immediate_reg(12); }
|
||||
void Cx4::op68() { immediate_reg(15); }
|
||||
void Cx4::op6a() { immediate_reg(18); }
|
||||
void Cx4::op6c() { immediate_reg(21); }
|
||||
void Cx4::op6e() { immediate_reg(24); }
|
||||
void Cx4::op70() { immediate_reg(27); }
|
||||
void Cx4::op72() { immediate_reg(30); }
|
||||
void Cx4::op74() { immediate_reg(33); }
|
||||
void Cx4::op76() { immediate_reg(36); }
|
||||
void Cx4::op78() { immediate_reg(39); }
|
||||
void Cx4::op7a() { immediate_reg(42); }
|
||||
void Cx4::op7c() { immediate_reg(45); }
|
||||
|
||||
//Immediate ROM
|
||||
void Cx4::op89() {
|
||||
str(0, 0x054336);
|
||||
str(1, 0xffffff);
|
||||
}
|
||||
|
||||
#endif //ifdef CX4_CPP
|
||||
@@ -0,0 +1,57 @@
|
||||
#include "../../base.h"
|
||||
#define DSP1_CPP
|
||||
|
||||
#include "dsp1emu.cpp"
|
||||
|
||||
void DSP1::init() {}
|
||||
void DSP1::enable() {}
|
||||
|
||||
void DSP1::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void DSP1::reset() {
|
||||
dsp1.reset();
|
||||
}
|
||||
|
||||
/*****
|
||||
* addr_decode()
|
||||
* determine whether address is accessing
|
||||
* data register (DR) or status register (SR)
|
||||
* -- 0 (false) = DR
|
||||
* -- 1 (true ) = SR
|
||||
*
|
||||
* note: there is no need to bounds check addresses,
|
||||
* as memory mapper will not allow DSP1 accesses outside
|
||||
* of expected ranges
|
||||
*****/
|
||||
bool DSP1::addr_decode(uint16 addr) {
|
||||
switch(cartridge.info.dsp1_mapper) {
|
||||
case Cartridge::DSP1LoROM1MB: {
|
||||
//$[20-3f]:[8000-bfff] = DR, $[20-3f]:[c000-ffff] = SR
|
||||
return (addr >= 0xc000);
|
||||
}
|
||||
|
||||
case Cartridge::DSP1LoROM2MB: {
|
||||
//$[60-6f]:[0000-3fff] = DR, $[60-6f]:[4000-7fff] = SR
|
||||
return (addr >= 0x4000);
|
||||
}
|
||||
|
||||
case Cartridge::DSP1HiROM: {
|
||||
//$[00-1f]:[6000-6fff] = DR, $[00-1f]:[7000-7fff] = SR
|
||||
return (addr >= 0x7000);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8 DSP1::read(uint addr) {
|
||||
return (addr_decode(addr) == 0) ? dsp1.getDr() : dsp1.getSr();
|
||||
}
|
||||
|
||||
void DSP1::write(uint addr, uint8 data) {
|
||||
if(addr_decode(addr) == 0) {
|
||||
dsp1.setDr(data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "dsp1emu.h"
|
||||
|
||||
class DSP1 : public Memory {
|
||||
private:
|
||||
Dsp1 dsp1;
|
||||
bool addr_decode(uint16 addr);
|
||||
|
||||
public:
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 read(uint addr);
|
||||
void write(uint addr, uint8 data);
|
||||
};
|
||||
|
||||
extern DSP1 dsp1;
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,127 @@
|
||||
// DSP-1's emulation code
|
||||
//
|
||||
// Based on research by Overload, The Dumper, Neviksti and Andreas Naive
|
||||
// Date: June 2006
|
||||
|
||||
#ifndef __DSP1EMUL_H
|
||||
#define __DSP1EMUL_H
|
||||
|
||||
#define DSP1_VERSION 0x0102
|
||||
|
||||
class Dsp1
|
||||
{
|
||||
public:
|
||||
// The DSP-1 status register has 16 bits, but only
|
||||
// the upper 8 bits can be accessed from an external device, so all these
|
||||
// positions are referred to the upper byte (bits D8 to D15)
|
||||
enum SrFlags {DRC=0x04, DRS=0x10, RQM=0x80};
|
||||
|
||||
// According to Overload's docs, these are the meanings of the flags:
|
||||
// DRC: The Data Register Control (DRC) bit specifies the data transfer length to and from the host CPU.
|
||||
// 0: Data transfer to and from the DSP-1 is 16 bits.
|
||||
// 1: Data transfer to and from the DSP-1 is 8 bits.
|
||||
// DRS: The Data Register Status (DRS) bit indicates the data transfer status in the case of transfering 16-bit data.
|
||||
// 0: Data transfer has terminated.
|
||||
// 1: Data transfer in progress.
|
||||
// RQM: The Request for Master (RQM) indicates that the DSP1 is requesting host CPU for data read/write.
|
||||
// 0: Internal Data Register Transfer.
|
||||
// 1: External Data Register Transfer.
|
||||
|
||||
Dsp1();
|
||||
uint8 getSr(); // return the status register's high byte
|
||||
uint8 getDr();
|
||||
void setDr(uint8 iDr);
|
||||
void reset();
|
||||
|
||||
private:
|
||||
enum FsmMajorState {WAIT_COMMAND, READ_DATA, WRITE_DATA};
|
||||
enum MaxDataAccesses {MAX_READS=7, MAX_WRITES=1024};
|
||||
|
||||
struct Command {
|
||||
void (Dsp1::*callback)(int16 *, int16 *);
|
||||
unsigned int reads;
|
||||
unsigned int writes;
|
||||
};
|
||||
|
||||
static const Command mCommandTable[];
|
||||
static const int16 MaxAZS_Exp[16];
|
||||
static const int16 SinTable[];
|
||||
static const int16 MulTable[];
|
||||
static const uint16 DataRom[];
|
||||
|
||||
struct SharedData { // some RAM variables shared between commands
|
||||
int16 MatrixA[3][3]; // attitude matrix A
|
||||
int16 MatrixB[3][3];
|
||||
int16 MatrixC[3][3];
|
||||
int16 CentreX, CentreY, CentreZ; // center of projection
|
||||
int16 CentreZ_C, CentreZ_E;
|
||||
int16 VOffset; // vertical offset of the screen with regard to the centre of projection
|
||||
int16 Les, C_Les, E_Les;
|
||||
int16 SinAas, CosAas;
|
||||
int16 SinAzs, CosAzs;
|
||||
int16 SinAZS, CosAZS;
|
||||
int16 SecAZS_C1, SecAZS_E1;
|
||||
int16 SecAZS_C2, SecAZS_E2;
|
||||
int16 Nx, Ny, Nz; // normal vector to the screen (norm 1, points toward the center of projection)
|
||||
int16 Gx, Gy, Gz; // center of the screen (global coordinates)
|
||||
int16 Hx, Hy; // horizontal vector of the screen (Hz=0, norm 1, points toward the right of the screen)
|
||||
int16 Vx, Vy, Vz; // vertical vector of the screen (norm 1, points toward the top of the screen)
|
||||
|
||||
} shared;
|
||||
|
||||
uint8 mSr; // status register
|
||||
int mSrLowByteAccess;
|
||||
uint16 mDr; // "internal" representation of the data register
|
||||
FsmMajorState mFsmMajorState; // current major state of the FSM
|
||||
uint8 mCommand; // current command processed by the FSM
|
||||
uint8 mDataCounter; // #uint16 read/writes counter used by the FSM
|
||||
int16 mReadBuffer[MAX_READS];
|
||||
int16 mWriteBuffer[MAX_WRITES];
|
||||
bool mFreeze; // need explanation? ;)
|
||||
|
||||
void fsmStep(bool read, uint8 &data); // FSM logic
|
||||
|
||||
// commands
|
||||
void memoryTest(int16 *input, int16 *output);
|
||||
void memoryDump(int16 *input, int16 *output);
|
||||
void memorySize(int16 *input, int16 *output);
|
||||
void multiply(int16* input, int16* output);
|
||||
void multiply2(int16* input, int16* output);
|
||||
void inverse(int16 *input, int16 *output);
|
||||
void triangle(int16 *input, int16 *output);
|
||||
void radius(int16 *input, int16 *output);
|
||||
void range(int16 *input, int16 *output);
|
||||
void range2(int16 *input, int16 *output);
|
||||
void distance(int16 *input, int16 *output);
|
||||
void rotate(int16 *input, int16 *output);
|
||||
void polar(int16 *input, int16 *output);
|
||||
void attitudeA(int16 *input, int16 *output);
|
||||
void attitudeB(int16 *input, int16 *output);
|
||||
void attitudeC(int16 *input, int16 *output);
|
||||
void objectiveA(int16 *input, int16 *output);
|
||||
void objectiveB(int16 *input, int16 *output);
|
||||
void objectiveC(int16 *input, int16 *output);
|
||||
void subjectiveA(int16 *input, int16 *output);
|
||||
void subjectiveB(int16 *input, int16 *output);
|
||||
void subjectiveC(int16 *input, int16 *output);
|
||||
void scalarA(int16 *input, int16 *output);
|
||||
void scalarB(int16 *input, int16 *output);
|
||||
void scalarC(int16 *input, int16 *output);
|
||||
void gyrate(int16 *input, int16 *output);
|
||||
void parameter(int16 *input, int16 *output);
|
||||
void raster(int16 *input, int16 *output);
|
||||
void target(int16 *input, int16 *output);
|
||||
void project(int16 *input, int16 *output);
|
||||
|
||||
// auxiliar functions
|
||||
int16 sin(int16 Angle);
|
||||
int16 cos(int16 Angle);
|
||||
void inverse(int16 Coefficient, int16 Exponent, int16 &iCoefficient, int16 &iExponent);
|
||||
int16 denormalizeAndClip(int16 C, int16 E);
|
||||
void normalize(int16 m, int16 &Coefficient, int16 &Exponent);
|
||||
void normalizeDouble(int32 Product, int16 &Coefficient, int16 &Exponent);
|
||||
int16 shiftR(int16 C, int16 E);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
#include "../../base.h"
|
||||
#define DSP2_CPP
|
||||
|
||||
#include "dsp2_op.cpp"
|
||||
|
||||
void DSP2::init() {}
|
||||
void DSP2::enable() {}
|
||||
|
||||
void DSP2::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void DSP2::reset() {
|
||||
status.waiting_for_command = true;
|
||||
status.in_count = 0;
|
||||
status.in_index = 0;
|
||||
status.out_count = 0;
|
||||
status.out_index = 0;
|
||||
|
||||
status.op05transparent = 0;
|
||||
status.op05haslen = false;
|
||||
status.op05len = 0;
|
||||
status.op06haslen = false;
|
||||
status.op06len = 0;
|
||||
status.op09word1 = 0;
|
||||
status.op09word2 = 0;
|
||||
status.op0dhaslen = false;
|
||||
status.op0doutlen = 0;
|
||||
status.op0dinlen = 0;
|
||||
}
|
||||
|
||||
uint8 DSP2::read(uint addr) {
|
||||
uint8 r = 0xff;
|
||||
if(status.out_count) {
|
||||
r = status.output[status.out_index++];
|
||||
status.out_index &= 511;
|
||||
if(status.out_count == status.out_index) {
|
||||
status.out_count = 0;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void DSP2::write(uint addr, uint8 data) {
|
||||
if(status.waiting_for_command) {
|
||||
status.command = data;
|
||||
status.in_index = 0;
|
||||
status.waiting_for_command = false;
|
||||
|
||||
switch(data) {
|
||||
case 0x01: status.in_count = 32; break;
|
||||
case 0x03: status.in_count = 1; break;
|
||||
case 0x05: status.in_count = 1; break;
|
||||
case 0x06: status.in_count = 1; break;
|
||||
case 0x07: break;
|
||||
case 0x08: break;
|
||||
case 0x09: status.in_count = 4; break;
|
||||
case 0x0d: status.in_count = 2; break;
|
||||
case 0x0f: status.in_count = 0; break;
|
||||
}
|
||||
} else {
|
||||
status.parameters[status.in_index++] = data;
|
||||
status.in_index &= 511;
|
||||
}
|
||||
|
||||
if(status.in_count == status.in_index) {
|
||||
status.waiting_for_command = true;
|
||||
status.out_index = 0;
|
||||
switch(status.command) {
|
||||
case 0x01: {
|
||||
status.out_count = 32;
|
||||
op01();
|
||||
} break;
|
||||
|
||||
case 0x03: {
|
||||
op03();
|
||||
} break;
|
||||
|
||||
case 0x05: {
|
||||
if(status.op05haslen) {
|
||||
status.op05haslen = false;
|
||||
status.out_count = status.op05len;
|
||||
op05();
|
||||
} else {
|
||||
status.op05len = status.parameters[0];
|
||||
status.in_index = 0;
|
||||
status.in_count = status.op05len * 2;
|
||||
status.op05haslen = true;
|
||||
if(data)status.waiting_for_command = false;
|
||||
}
|
||||
} break;
|
||||
|
||||
case 0x06: {
|
||||
if(status.op06haslen) {
|
||||
status.op06haslen = false;
|
||||
status.out_count = status.op06len;
|
||||
op06();
|
||||
} else {
|
||||
status.op06len = status.parameters[0];
|
||||
status.in_index = 0;
|
||||
status.in_count = status.op06len;
|
||||
status.op06haslen = true;
|
||||
if(data)status.waiting_for_command = false;
|
||||
}
|
||||
} break;
|
||||
|
||||
case 0x07: break;
|
||||
case 0x08: break;
|
||||
|
||||
case 0x09: {
|
||||
op09();
|
||||
} break;
|
||||
|
||||
case 0x0d: {
|
||||
if(status.op0dhaslen) {
|
||||
status.op0dhaslen = false;
|
||||
status.out_count = status.op0doutlen;
|
||||
op0d();
|
||||
} else {
|
||||
status.op0dinlen = status.parameters[0];
|
||||
status.op0doutlen = status.parameters[1];
|
||||
status.in_index = 0;
|
||||
status.in_count = (status.op0dinlen + 1) >> 1;
|
||||
status.op0dhaslen = true;
|
||||
if(data)status.waiting_for_command = false;
|
||||
}
|
||||
} break;
|
||||
|
||||
case 0x0f: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DSP2::DSP2() {}
|
||||
DSP2::~DSP2() {}
|
||||
@@ -0,0 +1,44 @@
|
||||
class DSP2 : public Memory {
|
||||
public:
|
||||
struct {
|
||||
bool waiting_for_command;
|
||||
uint command;
|
||||
uint in_count, in_index;
|
||||
uint out_count, out_index;
|
||||
|
||||
uint8 parameters[512];
|
||||
uint8 output[512];
|
||||
|
||||
uint8 op05transparent;
|
||||
bool op05haslen;
|
||||
int op05len;
|
||||
bool op06haslen;
|
||||
int op06len;
|
||||
uint16 op09word1;
|
||||
uint16 op09word2;
|
||||
bool op0dhaslen;
|
||||
int op0doutlen;
|
||||
int op0dinlen;
|
||||
} status;
|
||||
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 read(uint addr);
|
||||
void write(uint addr, uint8 data);
|
||||
|
||||
DSP2();
|
||||
~DSP2();
|
||||
|
||||
protected:
|
||||
void op01();
|
||||
void op03();
|
||||
void op05();
|
||||
void op06();
|
||||
void op09();
|
||||
void op0d();
|
||||
};
|
||||
|
||||
extern DSP2 dsp2;
|
||||
@@ -0,0 +1,177 @@
|
||||
#ifdef DSP2_CPP
|
||||
|
||||
//convert bitmap to bitplane tile
|
||||
void DSP2::op01() {
|
||||
//op01 size is always 32 bytes input and output
|
||||
//the hardware does strange things if you vary the size
|
||||
|
||||
unsigned char c0, c1, c2, c3;
|
||||
unsigned char *p1 = status.parameters;
|
||||
unsigned char *p2a = status.output;
|
||||
unsigned char *p2b = status.output + 16; //halfway
|
||||
|
||||
//process 8 blocks of 4 bytes each
|
||||
for(int j = 0; j < 8; j++) {
|
||||
c0 = *p1++;
|
||||
c1 = *p1++;
|
||||
c2 = *p1++;
|
||||
c3 = *p1++;
|
||||
|
||||
*p2a++ = (c0 & 0x10) << 3 |
|
||||
(c0 & 0x01) << 6 |
|
||||
(c1 & 0x10) << 1 |
|
||||
(c1 & 0x01) << 4 |
|
||||
(c2 & 0x10) >> 1 |
|
||||
(c2 & 0x01) << 2 |
|
||||
(c3 & 0x10) >> 3 |
|
||||
(c3 & 0x01);
|
||||
|
||||
*p2a++ = (c0 & 0x20) << 2 |
|
||||
(c0 & 0x02) << 5 |
|
||||
(c1 & 0x20) |
|
||||
(c1 & 0x02) << 3 |
|
||||
(c2 & 0x20) >> 2 |
|
||||
(c2 & 0x02) << 1 |
|
||||
(c3 & 0x20) >> 4 |
|
||||
(c3 & 0x02) >> 1;
|
||||
|
||||
*p2b++ = (c0 & 0x40) << 1 |
|
||||
(c0 & 0x04) << 4 |
|
||||
(c1 & 0x40) >> 1 |
|
||||
(c1 & 0x04) << 2 |
|
||||
(c2 & 0x40) >> 3 |
|
||||
(c2 & 0x04) |
|
||||
(c3 & 0x40) >> 5 |
|
||||
(c3 & 0x04) >> 2;
|
||||
|
||||
*p2b++ = (c0 & 0x80) |
|
||||
(c0 & 0x08) << 3 |
|
||||
(c1 & 0x80) >> 2 |
|
||||
(c1 & 0x08) << 1 |
|
||||
(c2 & 0x80) >> 4 |
|
||||
(c2 & 0x08) >> 1 |
|
||||
(c3 & 0x80) >> 6 |
|
||||
(c3 & 0x08) >> 3;
|
||||
}
|
||||
}
|
||||
|
||||
//set transparent color
|
||||
void DSP2::op03() {
|
||||
status.op05transparent = status.parameters[0];
|
||||
}
|
||||
|
||||
//replace bitmap using transparent color
|
||||
void DSP2::op05() {
|
||||
uint8 color;
|
||||
// Overlay bitmap with transparency.
|
||||
// Input:
|
||||
//
|
||||
// Bitmap 1: i[0] <=> i[size-1]
|
||||
// Bitmap 2: i[size] <=> i[2*size-1]
|
||||
//
|
||||
// Output:
|
||||
//
|
||||
// Bitmap 3: o[0] <=> o[size-1]
|
||||
//
|
||||
// Processing:
|
||||
//
|
||||
// Process all 4-bit pixels (nibbles) in the bitmap
|
||||
//
|
||||
// if ( BM2_pixel == transparent_color )
|
||||
// pixelout = BM1_pixel
|
||||
// else
|
||||
// pixelout = BM2_pixel
|
||||
|
||||
// The max size bitmap is limited to 255 because the size parameter is a byte
|
||||
// I think size=0 is an error. The behavior of the chip on size=0 is to
|
||||
// return the last value written to DR if you read DR on Op05 with
|
||||
// size = 0. I don't think it's worth implementing this quirk unless it's
|
||||
// proven necessary.
|
||||
|
||||
unsigned char c1, c2;
|
||||
unsigned char *p1 = status.parameters;
|
||||
unsigned char *p2 = status.parameters + status.op05len;
|
||||
unsigned char *p3 = status.output;
|
||||
|
||||
color = status.op05transparent & 0x0f;
|
||||
|
||||
for(int n = 0; n < status.op05len; n++) {
|
||||
c1 = *p1++;
|
||||
c2 = *p2++;
|
||||
*p3++ = ( ((c2 >> 4) == color ) ? c1 & 0xf0 : c2 & 0xf0 ) |
|
||||
( ((c2 & 0x0f) == color ) ? c1 & 0x0f : c2 & 0x0f );
|
||||
}
|
||||
}
|
||||
|
||||
//reverse bitmap
|
||||
void DSP2::op06() {
|
||||
// Input:
|
||||
// size
|
||||
// bitmap
|
||||
|
||||
int i, j;
|
||||
for(i = 0, j = status.op06len - 1; i < status.op06len; i++, j--) {
|
||||
status.output[j] = (status.parameters[i] << 4) | (status.parameters[i] >> 4);
|
||||
}
|
||||
}
|
||||
|
||||
//multiply
|
||||
void DSP2::op09() {
|
||||
status.out_count = 4;
|
||||
|
||||
status.op09word1 = status.parameters[0] | (status.parameters[1] << 8);
|
||||
status.op09word2 = status.parameters[2] | (status.parameters[3] << 8);
|
||||
|
||||
uint32 r;
|
||||
r = status.op09word1 * status.op09word2;
|
||||
status.output[0] = r;
|
||||
status.output[1] = r >> 8;
|
||||
status.output[2] = r >> 16;
|
||||
status.output[3] = r >> 24;
|
||||
}
|
||||
|
||||
//scale bitmap
|
||||
void DSP2::op0d() {
|
||||
// Bit accurate hardware algorithm - uses fixed point math
|
||||
// This should match the DSP2 Op0D output exactly
|
||||
// I wouldn't recommend using this unless you're doing hardware debug.
|
||||
// In some situations it has small visual artifacts that
|
||||
// are not readily apparent on a TV screen but show up clearly
|
||||
// on a monitor. Use Overload's scaling instead.
|
||||
// This is for hardware verification testing.
|
||||
//
|
||||
// One note: the HW can do odd byte scaling but since we divide
|
||||
// by two to get the count of bytes this won't work well for
|
||||
// odd byte scaling (in any of the current algorithm implementations).
|
||||
// So far I haven't seen Dungeon Master use it.
|
||||
// If it does we can adjust the parameters and code to work with it
|
||||
|
||||
uint32 multiplier; // Any size int >= 32-bits
|
||||
uint32 pixloc; // match size of multiplier
|
||||
int i, j;
|
||||
uint8 pixelarray[512];
|
||||
if(status.op0dinlen <= status.op0doutlen) {
|
||||
multiplier = 0x10000; // In our self defined fixed point 0x10000 == 1
|
||||
} else {
|
||||
multiplier = (status.op0dinlen << 17) / ((status.op0doutlen << 1) + 1);
|
||||
}
|
||||
|
||||
pixloc = 0;
|
||||
for(i = 0; i < status.op0doutlen * 2; i++) {
|
||||
j = pixloc >> 16;
|
||||
|
||||
if(j & 1) {
|
||||
pixelarray[i] = (status.parameters[j >> 1] & 0x0f);
|
||||
} else {
|
||||
pixelarray[i] = (status.parameters[j >> 1] & 0xf0) >> 4;
|
||||
}
|
||||
|
||||
pixloc += multiplier;
|
||||
}
|
||||
|
||||
for(i = 0; i < status.op0doutlen; i++) {
|
||||
status.output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1];
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef DSP2_CPP
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
File diff suppressed because it is too large.
Load diff
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
File diff suppressed because it is too large.
Load diff
@@ -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
|
||||
@@ -0,0 +1,89 @@
|
||||
#include "../../base.h"
|
||||
|
||||
void OBC1::init() {}
|
||||
void OBC1::enable() {}
|
||||
|
||||
void OBC1::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void OBC1::reset() {
|
||||
for(uint i = 0x0000; i <= 0x1fff; i++) ram_write(i, 0xff);
|
||||
|
||||
status.baseptr = (ram_read(0x1ff5) & 1) ? 0x1800 : 0x1c00;
|
||||
status.address = (ram_read(0x1ff6) & 0x7f);
|
||||
status.shift = (ram_read(0x1ff6) & 3) << 1;
|
||||
}
|
||||
|
||||
uint8 OBC1::read(uint addr) {
|
||||
addr &= 0x1fff;
|
||||
if((addr & 0x1ff8) != 0x1ff0) return ram_read(addr);
|
||||
|
||||
switch(addr) {
|
||||
case 0x1ff0:
|
||||
return ram_read(status.baseptr + (status.address << 2) + 0);
|
||||
case 0x1ff1:
|
||||
return ram_read(status.baseptr + (status.address << 2) + 1);
|
||||
case 0x1ff2:
|
||||
return ram_read(status.baseptr + (status.address << 2) + 2);
|
||||
case 0x1ff3:
|
||||
return ram_read(status.baseptr + (status.address << 2) + 3);
|
||||
case 0x1ff4:
|
||||
return ram_read(status.baseptr + (status.address >> 2) + 0x200);
|
||||
case 0x1ff5:
|
||||
case 0x1ff6:
|
||||
case 0x1ff7:
|
||||
return ram_read(addr);
|
||||
}
|
||||
|
||||
return 0x00; //never used, avoids compiler warning
|
||||
}
|
||||
|
||||
void OBC1::write(uint addr, uint8 data) {
|
||||
addr &= 0x1fff;
|
||||
if((addr & 0x1ff8) != 0x1ff0) return ram_write(addr, data);
|
||||
|
||||
switch(addr) {
|
||||
case 0x1ff0:
|
||||
ram_write(status.baseptr + (status.address << 2) + 0, data);
|
||||
break;
|
||||
case 0x1ff1:
|
||||
ram_write(status.baseptr + (status.address << 2) + 1, data);
|
||||
break;
|
||||
case 0x1ff2:
|
||||
ram_write(status.baseptr + (status.address << 2) + 2, data);
|
||||
break;
|
||||
case 0x1ff3:
|
||||
ram_write(status.baseptr + (status.address << 2) + 3, data);
|
||||
break;
|
||||
case 0x1ff4: {
|
||||
uint8 temp;
|
||||
temp = ram_read(status.baseptr + (status.address >> 2) + 0x200);
|
||||
temp = (temp & ~(3 << status.shift)) | ((data & 3) << status.shift);
|
||||
ram_write(status.baseptr + (status.address >> 2) + 0x200, temp);
|
||||
} break;
|
||||
case 0x1ff5:
|
||||
status.baseptr = (data & 1) ? 0x1800 : 0x1c00;
|
||||
ram_write(addr, data);
|
||||
break;
|
||||
case 0x1ff6:
|
||||
status.address = (data & 0x7f);
|
||||
status.shift = (data & 3) << 1;
|
||||
ram_write(addr, data);
|
||||
break;
|
||||
case 0x1ff7:
|
||||
ram_write(addr, data);
|
||||
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() {}
|
||||
@@ -0,0 +1,25 @@
|
||||
class OBC1 : public Memory {
|
||||
public:
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 read(uint addr);
|
||||
void write(uint addr, uint8 data);
|
||||
|
||||
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;
|
||||
+70
-63
@@ -1,13 +1,12 @@
|
||||
#include "../../base.h"
|
||||
#include "../../base.h"
|
||||
#define SDD1_CPP
|
||||
|
||||
#include "sdd1emu.cpp"
|
||||
|
||||
void SDD1::init() {
|
||||
}
|
||||
void SDD1::init() {}
|
||||
|
||||
void SDD1::enable() {
|
||||
for(int i=0x4800;i<=0x4807;i++) {
|
||||
mem_bus->set_mmio_mapper(i, mmio);
|
||||
}
|
||||
for(int i = 0x4800; i <= 0x4807; i++) memory::mmio.map(i, *this);
|
||||
}
|
||||
|
||||
void SDD1::power() {
|
||||
@@ -15,60 +14,80 @@ void SDD1::power() {
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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 b = (addr >> 16) & 0xff;
|
||||
if(b <= 0xbf)return 0;
|
||||
|
||||
b -= 0xc0; //b = 0x00-0x3f
|
||||
b >>= 4; //b = 0-3
|
||||
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;
|
||||
uint8 SDD1::mmio_read(uint addr) {
|
||||
switch(addr & 0xffff) {
|
||||
case 0x4804: return regs.r4804;
|
||||
case 0x4805: return regs.r4805;
|
||||
case 0x4806: return regs.r4806;
|
||||
case 0x4807: return regs.r4807;
|
||||
}
|
||||
|
||||
return cpu->regs.mdr;
|
||||
return cpu.regs.mdr;
|
||||
}
|
||||
|
||||
void SDD1::mmio_write(uint16 addr, uint8 data) {
|
||||
int i;
|
||||
switch(addr) {
|
||||
case 0x4801:
|
||||
for(i=0;i<8;i++) {
|
||||
sdd1.active[i] = !!(data & (1 << i));
|
||||
}
|
||||
break;
|
||||
//<<20 == 0x100000 == 1mb
|
||||
case 0x4804:sdd1.index[0] = (data & 7) << 20;break;
|
||||
case 0x4805:sdd1.index[1] = (data & 7) << 20;break;
|
||||
case 0x4806:sdd1.index[2] = (data & 7) << 20;break;
|
||||
case 0x4807:sdd1.index[3] = (data & 7) << 20;break;
|
||||
void SDD1::mmio_write(uint addr, uint8 data) {
|
||||
switch(addr & 0xffff) {
|
||||
case 0x4800: {
|
||||
regs.r4800 = data;
|
||||
} 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;
|
||||
|
||||
case 0x4805: {
|
||||
if(regs.r4805 != data) {
|
||||
regs.r4805 = data;
|
||||
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) {
|
||||
if(sdd1.active[channel] == true) {
|
||||
sdd1.active[channel] = false;
|
||||
if(regs.r4800 & (1 << channel) && regs.r4801 & (1 << channel)) {
|
||||
regs.r4801 &= ~(1 << channel);
|
||||
sdd1.dma_active = true;
|
||||
sdd1.buffer_index = 0;
|
||||
sdd1.buffer_size = length;
|
||||
@@ -81,23 +100,11 @@ bool SDD1::dma_active() {
|
||||
}
|
||||
|
||||
uint8 SDD1::dma_read() {
|
||||
if(--sdd1.buffer_size == 0) {
|
||||
sdd1.dma_active = false;
|
||||
}
|
||||
if(--sdd1.buffer_size == 0) sdd1.dma_active = false;
|
||||
|
||||
//sdd1.buffer[] is 65536 bytes, and sdd1.buffer_index
|
||||
//is of type uint16, so no buffer overflow is possible
|
||||
return sdd1.buffer[sdd1.buffer_index++];
|
||||
}
|
||||
|
||||
SDD1::SDD1() {
|
||||
mmio = new SDD1MMIO();
|
||||
}
|
||||
|
||||
uint8 SDD1MMIO::read(uint32 addr) {
|
||||
return sdd1->mmio_read(addr);
|
||||
}
|
||||
|
||||
void SDD1MMIO::write(uint32 addr, uint8 value) {
|
||||
sdd1->mmio_write(addr, value);
|
||||
}
|
||||
SDD1::SDD1() {}
|
||||
+31
-29
@@ -1,37 +1,39 @@
|
||||
#include "sdd1emu.h"
|
||||
|
||||
class SDD1MMIO : public MMIO {
|
||||
class SDD1 : public MMIO {
|
||||
public:
|
||||
inline uint8 read (uint32 addr);
|
||||
inline void write(uint32 addr, uint8 value);
|
||||
};
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
class SDD1 {
|
||||
public:
|
||||
SDD1emu sdd1emu;
|
||||
SDD1MMIO *mmio;
|
||||
uint8 mmio_read (uint addr);
|
||||
void mmio_write(uint addr, uint8 data);
|
||||
|
||||
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 enable();
|
||||
void power();
|
||||
void reset();
|
||||
uint32 offset(uint32 addr);
|
||||
|
||||
void dma_begin(uint8 channel, uint32 addr, uint16 length);
|
||||
bool dma_active();
|
||||
uint8 dma_read();
|
||||
|
||||
uint8 mmio_read(uint16 addr);
|
||||
void mmio_write(uint16 addr, uint8 data);
|
||||
void dma_begin(uint8 channel, uint32 addr, uint16 length);
|
||||
bool dma_active();
|
||||
uint8 dma_read();
|
||||
|
||||
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;
|
||||
@@ -1,3 +1,5 @@
|
||||
#ifdef SDD1_CPP
|
||||
|
||||
/************************************************************************
|
||||
|
||||
S-DD1'algorithm emulation code
|
||||
@@ -28,7 +30,7 @@ understood.
|
||||
|
||||
************************************************************************/
|
||||
|
||||
#define SDD1_read(__addr) (mem_bus->read(__addr))
|
||||
#define SDD1_read(__addr) (bus.read(__addr))
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
@@ -445,3 +447,5 @@ SDD1emu::SDD1emu() :
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
#endif //ifdef SDD1_CPP
|
||||
@@ -28,6 +28,7 @@ understood.
|
||||
|
||||
************************************************************************/
|
||||
|
||||
typedef uint8_t bool8;
|
||||
|
||||
class SDD1_IM { //Input Manager
|
||||
|
||||
|
||||
+86
-83
@@ -74,12 +74,11 @@ tm *t;
|
||||
srtc.data[12] = t->tm_wday;
|
||||
}
|
||||
|
||||
void SRTC::init() {
|
||||
}
|
||||
void SRTC::init() {}
|
||||
|
||||
void SRTC::enable() {
|
||||
mem_bus->set_mmio_mapper(0x2800, mmio);
|
||||
mem_bus->set_mmio_mapper(0x2801, mmio);
|
||||
memory::mmio.map(0x2800, *this);
|
||||
memory::mmio.map(0x2801, *this);
|
||||
}
|
||||
|
||||
void SRTC::power() {
|
||||
@@ -89,7 +88,35 @@ void SRTC::power() {
|
||||
|
||||
void SRTC::reset() {
|
||||
srtc.index = -1;
|
||||
srtc.mode = SRTC_READ;
|
||||
srtc.mode = SRTC_READ;
|
||||
}
|
||||
|
||||
uint8 SRTC::mmio_read(uint addr) {
|
||||
switch(addr & 0xffff) {
|
||||
|
||||
case 0x2800: {
|
||||
if(srtc.mode == SRTC_READ) {
|
||||
if(srtc.index < 0) {
|
||||
set_time();
|
||||
srtc.index++;
|
||||
return 0x0f; //send start message
|
||||
} else if(srtc.index > MAX_SRTC_INDEX) {
|
||||
srtc.index = -1;
|
||||
return 0x0f; //send finished message
|
||||
} else {
|
||||
return srtc.data[srtc.index++];
|
||||
}
|
||||
} else {
|
||||
return 0x00;
|
||||
}
|
||||
} break;
|
||||
|
||||
case 0x2801: {
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
return cpu.regs.mdr;
|
||||
}
|
||||
|
||||
//Please see notes above about the implementation of the S-RTC
|
||||
@@ -97,90 +124,66 @@ void SRTC::reset() {
|
||||
//as reads will refresh the data array with the current system
|
||||
//time. The write method is only here for the sake of faux
|
||||
//emulation of the real hardware.
|
||||
void SRTC::write(uint8 data) {
|
||||
data &= 0x0f; //only the low four bits are used
|
||||
void SRTC::mmio_write(uint addr, uint8 data) {
|
||||
switch(addr & 0xffff) {
|
||||
|
||||
if(data >= 0x0d) {
|
||||
switch(data) {
|
||||
case 0x0d:
|
||||
srtc.mode = SRTC_READ;
|
||||
srtc.index = -1;
|
||||
break;
|
||||
case 0x0e:
|
||||
srtc.mode = SRTC_COMMAND;
|
||||
break;
|
||||
case 0x0f:
|
||||
//unknown behaviour
|
||||
break;
|
||||
case 0x2800: {
|
||||
} break;
|
||||
|
||||
case 0x2801: {
|
||||
data &= 0x0f; //only the low four bits are used
|
||||
|
||||
if(data >= 0x0d) {
|
||||
switch(data) {
|
||||
case 0x0d:
|
||||
srtc.mode = SRTC_READ;
|
||||
srtc.index = -1;
|
||||
break;
|
||||
case 0x0e:
|
||||
srtc.mode = SRTC_COMMAND;
|
||||
break;
|
||||
case 0x0f:
|
||||
//unknown behaviour
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(srtc.mode == SRTC_WRITE) {
|
||||
if(srtc.index >= 0 && srtc.index < MAX_SRTC_INDEX) {
|
||||
srtc.data[srtc.index++] = data;
|
||||
if(srtc.mode == SRTC_WRITE) {
|
||||
if(srtc.index >= 0 && srtc.index < MAX_SRTC_INDEX) {
|
||||
srtc.data[srtc.index++] = data;
|
||||
|
||||
if(srtc.index == MAX_SRTC_INDEX) {
|
||||
//all S-RTC data has been loaded by program
|
||||
srtc.data[srtc.index++] = 0x00; //day_of_week
|
||||
if(srtc.index == MAX_SRTC_INDEX) {
|
||||
//all S-RTC data has been loaded by program
|
||||
srtc.data[srtc.index++] = 0x00; //day_of_week
|
||||
}
|
||||
}
|
||||
} else if(srtc.mode == SRTC_COMMAND) {
|
||||
switch(data) {
|
||||
case SRTC_COMMAND_CLEAR:
|
||||
memset(srtc.data, 0, MAX_SRTC_INDEX + 1);
|
||||
srtc.index = -1;
|
||||
srtc.mode = SRTC_READY;
|
||||
break;
|
||||
case SRTC_COMMAND_WRITE:
|
||||
srtc.index = 0;
|
||||
srtc.mode = SRTC_WRITE;
|
||||
break;
|
||||
default:
|
||||
//unknown behaviour
|
||||
srtc.mode = SRTC_READY;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(srtc.mode == SRTC_READ) {
|
||||
//ignore writes while in read mode
|
||||
} else if(srtc.mode == SRTC_READY) {
|
||||
//unknown behaviour
|
||||
}
|
||||
}
|
||||
} else if(srtc.mode == SRTC_COMMAND) {
|
||||
switch(data) {
|
||||
case SRTC_COMMAND_CLEAR:
|
||||
memset(srtc.data, 0, MAX_SRTC_INDEX + 1);
|
||||
srtc.index = -1;
|
||||
srtc.mode = SRTC_READY;
|
||||
break;
|
||||
case SRTC_COMMAND_WRITE:
|
||||
srtc.index = 0;
|
||||
srtc.mode = SRTC_WRITE;
|
||||
break;
|
||||
default:
|
||||
//unknown behaviour
|
||||
srtc.mode = SRTC_READY;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(srtc.mode == SRTC_READ) {
|
||||
//ignore writes while in read mode
|
||||
} else if(srtc.mode == SRTC_READY) {
|
||||
//unknown behaviour
|
||||
}
|
||||
} break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
uint8 SRTC::read() {
|
||||
if(srtc.mode == SRTC_READ) {
|
||||
if(srtc.index < 0) {
|
||||
set_time();
|
||||
srtc.index++;
|
||||
return 0x0f; //send start message
|
||||
} else if(srtc.index > MAX_SRTC_INDEX) {
|
||||
srtc.index = -1;
|
||||
return 0x0f; //send finished message
|
||||
} else {
|
||||
return srtc.data[srtc.index++];
|
||||
}
|
||||
} else {
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
SRTC::SRTC() {
|
||||
mmio = new SRTCMMIO();
|
||||
}
|
||||
|
||||
uint8 SRTCMMIO::read(uint32 addr) {
|
||||
switch(addr) {
|
||||
case 0x2800:return srtc->read();
|
||||
}
|
||||
|
||||
return cpu->regs.mdr;
|
||||
}
|
||||
|
||||
void SRTCMMIO::write(uint32 addr, uint8 value) {
|
||||
switch(addr) {
|
||||
case 0x2801:srtc->write(value);break;
|
||||
}
|
||||
}
|
||||
SRTC::SRTC() {}
|
||||
+6
-11
@@ -1,10 +1,4 @@
|
||||
class SRTCMMIO : public MMIO {
|
||||
public:
|
||||
inline uint8 read (uint32 addr);
|
||||
inline void write(uint32 addr, uint8 value);
|
||||
};
|
||||
|
||||
class SRTC {
|
||||
class SRTC : public MMIO {
|
||||
public:
|
||||
enum { MAX_SRTC_INDEX = 0x0c };
|
||||
|
||||
@@ -20,8 +14,6 @@ enum {
|
||||
SRTC_COMMAND_CLEAR = 4
|
||||
};
|
||||
|
||||
SRTCMMIO *mmio;
|
||||
|
||||
/******************************
|
||||
[srtc.data structure]
|
||||
Index Description Range
|
||||
@@ -50,8 +42,11 @@ struct {
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
void write(uint8 data);
|
||||
uint8 read();
|
||||
|
||||
uint8 mmio_read (uint addr);
|
||||
void mmio_write(uint addr, uint8 data);
|
||||
|
||||
SRTC();
|
||||
};
|
||||
|
||||
extern SRTC srtc;
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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 }
|
||||
};
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
@make platform=win compiler=mingw32-gcc clean
|
||||
@@ -0,0 +1 @@
|
||||
make platform=x compiler=gcc clean
|
||||
+123
-21
@@ -1,28 +1,130 @@
|
||||
Config config_file;
|
||||
|
||||
namespace config {
|
||||
|
||||
SNES::VideoColorAdjust SNES::video_color_curve(&config_file, "snes.video_color_curve",
|
||||
"Applies contrast adjust filter to video output when enabled\n"
|
||||
"Works by lowering the brightness of darker colors,\n"
|
||||
"while leaving brighter colors alone; thus reducing saturation",
|
||||
true, Setting::TRUE_FALSE);
|
||||
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);
|
||||
|
||||
integral_setting File::bypass_patch_crc32(config(), "file.bypass_patch_crc32",
|
||||
"UPS patches contain CRC32s to validate that a patch was applied successfully.\n"
|
||||
"By default, if this validation fails, said patch will not be applied.\n"
|
||||
"Setting this option to true will bypass the validation,\n"
|
||||
"which may or may not result in a working image.\n"
|
||||
"Enabling this option is strongly discouraged.",
|
||||
integral_setting::boolean, false);
|
||||
|
||||
SNES::VideoColorAdjust SNES::video_color_adjust_mode(&config_file, "snes.video_color_adjust_mode",
|
||||
"Selects color adjustment filter for video output\n"
|
||||
" 0 = Normal (no filter, rgb555)\n"
|
||||
" 1 = Grayscale mode (l5)\n"
|
||||
" 2 = VGA mode (rgb332)\n"
|
||||
" 3 = Genesis mode (rgb333)",
|
||||
0, Setting::DEC);
|
||||
string file_updatepath(const char *req_file, const char *req_path) {
|
||||
string file(req_file);
|
||||
replace(file, "\\", "/");
|
||||
if(!req_path || strlen(req_path) == 0) { return file; }
|
||||
|
||||
void SNES::VideoColorAdjust::set(uint32 _data) {
|
||||
data = _data;
|
||||
::snes->update_color_lookup_table();
|
||||
string path(req_path);
|
||||
replace(path, "\\", "/");
|
||||
if(!strend(path, "/")) { strcat(path, "/"); }
|
||||
|
||||
if(strbegin(path, "./")) {
|
||||
ltrim(path(), "./");
|
||||
string temp;
|
||||
strcpy(temp, config::path.base);
|
||||
strcat(temp, path);
|
||||
strcpy(path, temp);
|
||||
}
|
||||
|
||||
lstring part;
|
||||
split(part, "/", file);
|
||||
strcat(path, part[count(part) - 1]);
|
||||
return path;
|
||||
}
|
||||
|
||||
Setting SNES::mute(&config_file, "snes.mute",
|
||||
"Mutes SNES audio output when enabled",
|
||||
true, Setting::TRUE_FALSE);
|
||||
string_setting Path::base("path.base", "Path that bsnes resides in", "");
|
||||
string_setting Path::user("path.user", "Path to user folder", "");
|
||||
|
||||
};
|
||||
string_setting Path::rom(config(), "path.rom",
|
||||
"Default path to look for ROM files in (\"\" = use default directory)", "");
|
||||
string_setting Path::patch(config(), "path.patch",
|
||||
"Default path for all UPS patch files (\"\" = use current directory)", "");
|
||||
string_setting Path::save(config(), "path.save",
|
||||
"Default path for all save RAM files (\"\" = use current directory)", "");
|
||||
string_setting Path::cheat(config(), "path.cheat",
|
||||
"Default path for all cheat files (\"\" = use current directory)", "");
|
||||
string_setting Path::bsx(config(), "path.bsx", "", "");
|
||||
string_setting Path::st(config(), "path.st", "", "");
|
||||
|
||||
integral_setting SNES::controller_port0(config(), "snes.controller_port_1",
|
||||
"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);
|
||||
|
||||
integral_setting CPU::ntsc_clock_rate(config(), "cpu.ntsc_clock_rate",
|
||||
"NTSC S-CPU clock rate (in hz)", integral_setting::decimal, 21477272);
|
||||
integral_setting CPU::pal_clock_rate(config(), "cpu.pal_clock_rate",
|
||||
"PAL S-CPU clock rate (in hz)", integral_setting::decimal, 21281370);
|
||||
integral_setting CPU::wram_init_value(config(), "cpu.wram_init_value",
|
||||
"Value to initialize 128k WRAM to upon power cycle.\n"
|
||||
"Note that on real hardware, this value is undefined; meaning it can vary\n"
|
||||
"per power-on, and per SNES unit. Such randomness is undesirable for an\n"
|
||||
"emulator, so a static value is needed. There is also some form of pattern\n"
|
||||
"to the randomness that has yet to be determined, which some games rely upon.\n"
|
||||
"A value of 0x55 is safe for all known commercial software, and should be used.\n"
|
||||
"However, some software written for SNES copiers, or backup units, relies on\n"
|
||||
"WRAM being initialized to 0x00; which was a side-effect of the BIOS program\n"
|
||||
"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);
|
||||
|
||||
integral_setting CPU::hdma_enable("cpu.hdma_enable",
|
||||
"Enable HDMA effects", integral_setting::boolean, true);
|
||||
|
||||
integral_setting SMP::ntsc_clock_rate(config(), "smp.ntsc_clock_rate",
|
||||
"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);
|
||||
|
||||
integral_setting PPU::Hack::render_scanline_position(config(), "ppu.hack.render_scanline_position",
|
||||
"Approximate HCLOCK position to render at for scanline-based renderers",
|
||||
integral_setting::decimal, 512);
|
||||
integral_setting PPU::Hack::obj_cache(config(), "ppu.hack.obj_cache",
|
||||
"Cache OAM OBJ attributes one scanline before rendering\n"
|
||||
"This is technically closer to the actual operation of the SNES,\n"
|
||||
"but can cause problems in some games if enabled",
|
||||
integral_setting::boolean, false);
|
||||
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"
|
||||
"data to render the display. Thusly, the address retrieved when accessing\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"
|
||||
"accurate to enable this setting, but one must *not* rely on the actual\n"
|
||||
"address to match hardware under emulation.",
|
||||
integral_setting::boolean, true);
|
||||
integral_setting PPU::Hack::cgram_address_invalidation(config(), "ppu.hack.cgram_address_invalidation",
|
||||
"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"
|
||||
"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"
|
||||
"under emulation.",
|
||||
integral_setting::boolean, true);
|
||||
|
||||
integral_setting PPU::opt_enable("ppu.opt_enable", "Enable offset-per-tile effects", integral_setting::boolean, true);
|
||||
integral_setting PPU::bg1_pri0_enable("ppu.bg1_pri0_enable", "Enable BG1 Priority 0", integral_setting::boolean, true);
|
||||
integral_setting PPU::bg1_pri1_enable("ppu.bg1_pri1_enable", "Enable BG1 Priority 1", integral_setting::boolean, true);
|
||||
integral_setting PPU::bg2_pri0_enable("ppu.bg2_pri0_enable", "Enable BG2 Priority 0", integral_setting::boolean, true);
|
||||
integral_setting PPU::bg2_pri1_enable("ppu.bg2_pri1_enable", "Enable BG2 Priority 1", integral_setting::boolean, true);
|
||||
integral_setting PPU::bg3_pri0_enable("ppu.bg3_pri0_enable", "Enable BG3 Priority 0", integral_setting::boolean, true);
|
||||
integral_setting PPU::bg3_pri1_enable("ppu.bg3_pri1_enable", "Enable BG3 Priority 1", integral_setting::boolean, true);
|
||||
integral_setting PPU::bg4_pri0_enable("ppu.bg4_pri0_enable", "Enable BG4 Priority 0", integral_setting::boolean, true);
|
||||
integral_setting PPU::bg4_pri1_enable("ppu.bg4_pri1_enable", "Enable BG4 Priority 1", integral_setting::boolean, true);
|
||||
integral_setting PPU::oam_pri0_enable("ppu.oam_pri0_enable", "Enable OAM Priority 0", integral_setting::boolean, true);
|
||||
integral_setting PPU::oam_pri1_enable("ppu.oam_pri1_enable", "Enable OAM Priority 1", integral_setting::boolean, true);
|
||||
integral_setting PPU::oam_pri2_enable("ppu.oam_pri2_enable", "Enable OAM Priority 2", integral_setting::boolean, true);
|
||||
integral_setting PPU::oam_pri3_enable("ppu.oam_pri3_enable", "Enable OAM Priority 3", integral_setting::boolean, true);
|
||||
|
||||
} //namespace config
|
||||
+43
-9
@@ -1,15 +1,49 @@
|
||||
extern Config config_file;
|
||||
|
||||
namespace config {
|
||||
|
||||
extern struct SNES {
|
||||
static class VideoColorAdjust : public Setting {
|
||||
public:
|
||||
void set(uint32 _data);
|
||||
SettingOperators(VideoColorAdjust);
|
||||
} video_color_curve, video_color_adjust_mode;
|
||||
extern configuration& config();
|
||||
|
||||
static Setting mute;
|
||||
string file_updatepath(const char*, const char*);
|
||||
|
||||
extern struct File {
|
||||
static integral_setting autodetect_type;
|
||||
static integral_setting bypass_patch_crc32;
|
||||
} file;
|
||||
|
||||
extern struct Path {
|
||||
static string_setting base, user, rom, patch, save, cheat;
|
||||
static string_setting bsx, st;
|
||||
} path;
|
||||
|
||||
extern struct SNES {
|
||||
static integral_setting controller_port0;
|
||||
static integral_setting controller_port1;
|
||||
} snes;
|
||||
|
||||
extern struct CPU {
|
||||
static integral_setting ntsc_clock_rate, pal_clock_rate;
|
||||
static integral_setting wram_init_value;
|
||||
static integral_setting hdma_enable;
|
||||
} cpu;
|
||||
|
||||
extern struct SMP {
|
||||
static integral_setting ntsc_clock_rate, pal_clock_rate;
|
||||
} smp;
|
||||
|
||||
extern struct PPU {
|
||||
struct Hack {
|
||||
static integral_setting render_scanline_position;
|
||||
static integral_setting obj_cache;
|
||||
static integral_setting oam_address_invalidation;
|
||||
static integral_setting cgram_address_invalidation;
|
||||
} hack;
|
||||
|
||||
static integral_setting opt_enable;
|
||||
static integral_setting bg1_pri0_enable, bg1_pri1_enable;
|
||||
static integral_setting bg2_pri0_enable, bg2_pri1_enable;
|
||||
static integral_setting bg3_pri0_enable, bg3_pri1_enable;
|
||||
static integral_setting bg4_pri0_enable, bg4_pri1_enable;
|
||||
static integral_setting oam_pri0_enable, oam_pri1_enable;
|
||||
static integral_setting oam_pri2_enable, oam_pri3_enable;
|
||||
} ppu;
|
||||
|
||||
};
|
||||
@@ -1,262 +0,0 @@
|
||||
#include "../../base.h"
|
||||
|
||||
#include "bcpu_opfn.cpp"
|
||||
#include "bcpu_op_read.cpp"
|
||||
#include "bcpu_op_rmw.cpp"
|
||||
#include "bcpu_op_write.cpp"
|
||||
#include "bcpu_op_pc.cpp"
|
||||
#include "bcpu_op_misc.cpp"
|
||||
|
||||
#include "bcpu_exec.cpp"
|
||||
#include "bcpu_mmio.cpp"
|
||||
#include "bcpu_dma.cpp"
|
||||
|
||||
#include "bcpu_timing.cpp"
|
||||
|
||||
#include "bcpu_int.cpp"
|
||||
|
||||
uint8 bCPU::pio_status() { return status.pio; }
|
||||
|
||||
void bCPU::run() {
|
||||
if(run_state.hdma) {
|
||||
exec_hdma();
|
||||
return;
|
||||
}
|
||||
|
||||
if(run_state.dma) {
|
||||
exec_dma();
|
||||
return;
|
||||
}
|
||||
|
||||
if(run_state.irq) {
|
||||
irq_run();
|
||||
return;
|
||||
}
|
||||
|
||||
if(run_state.stp) {
|
||||
exec_cycle();
|
||||
return;
|
||||
}
|
||||
|
||||
if(status.cycle_pos == 0) {
|
||||
//interrupts only trigger on opcode edges
|
||||
if(time.nmi_pending == true) {
|
||||
time.nmi_pending = false;
|
||||
aa.w = 0xffea;
|
||||
run_state.irq = true;
|
||||
return;
|
||||
}
|
||||
if(time.irq_pending == true) {
|
||||
time.irq_pending = false;
|
||||
aa.w = 0xffee;
|
||||
run_state.irq = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
exec_cycle();
|
||||
}
|
||||
|
||||
void bCPU::scanline() {
|
||||
time.hdma_triggered = false;
|
||||
|
||||
if(vcounter() == 225 && status.auto_joypad_poll == true) {
|
||||
snes->poll_input(SNES::DEV_JOYPAD1);
|
||||
snes->poll_input(SNES::DEV_JOYPAD2);
|
||||
//When the SNES auto-polls the joypads, it writes 1, then 0 to
|
||||
//$4016, then reads from each 16 times to get the joypad state
|
||||
//information. As a result, the joypad read positions are set
|
||||
//to 16 after such a poll. Position 16 is the controller
|
||||
//connected status bit.
|
||||
status.joypad1_read_pos = 16;
|
||||
status.joypad2_read_pos = 16;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::frame() {
|
||||
time.nmi_read = 1;
|
||||
time.nmi_line = 1;
|
||||
time.nmi_transition = 0;
|
||||
|
||||
if(cpu_version == 2) {
|
||||
time.hdmainit_trigger_pos = 12 + dma_counter();
|
||||
} else {
|
||||
time.hdmainit_trigger_pos = 12 + 8 - dma_counter();
|
||||
}
|
||||
time.hdmainit_triggered = false;
|
||||
}
|
||||
|
||||
void bCPU::power() {
|
||||
region = snes->region();
|
||||
|
||||
regs.a = regs.x = regs.y = 0x0000;
|
||||
regs.s = 0x01ff;
|
||||
reset();
|
||||
}
|
||||
|
||||
void bCPU::reset() {
|
||||
//reset vector location
|
||||
regs.pc = mem_bus->read(0xfffc) | (mem_bus->read(0xfffd) << 8);
|
||||
|
||||
//registers are not fully reset by SNES
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
regs.s.h = 0x01;
|
||||
regs.d = 0x0000;
|
||||
regs.db = 0x00;
|
||||
regs.p = 0x34;
|
||||
regs.e = 1;
|
||||
regs.mdr = 0x00;
|
||||
|
||||
time_reset();
|
||||
mmio_reset();
|
||||
dma_reset();
|
||||
|
||||
run_state.hdma = false;
|
||||
run_state.dma = false;
|
||||
run_state.irq = false;
|
||||
run_state.wai = false;
|
||||
run_state.stp = false;
|
||||
|
||||
status.cycle_pos = 0;
|
||||
status.cycle_count = 0;
|
||||
status.cycles_executed = 0;
|
||||
|
||||
apu_port[0] = 0x00;
|
||||
apu_port[1] = 0x00;
|
||||
apu_port[2] = 0x00;
|
||||
apu_port[3] = 0x00;
|
||||
|
||||
frame();
|
||||
|
||||
//initial latch values for $213c/$213d
|
||||
//[x]0035 : [y]0000 (53.0 -> 212) [lda $2137]
|
||||
//[x]0038 : [y]0000 (56.5 -> 226) [nop : lda $2137]
|
||||
add_cycles(186);
|
||||
}
|
||||
|
||||
uint8 bCPU::port_read(uint8 port) {
|
||||
return apu_port[port & 3];
|
||||
}
|
||||
|
||||
void bCPU::port_write(uint8 port, uint8 value) {
|
||||
apu_port[port & 3] = value;
|
||||
}
|
||||
|
||||
void bCPU::cpu_c2() {
|
||||
if(regs.d.l != 0x00) {
|
||||
cpu_io();
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::cpu_c4(uint16 x, uint16 y) {
|
||||
if(!regs.p.x && (x & 0xff00) != (y & 0xff00)) {
|
||||
cpu_io();
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::cpu_c6(uint16 addr) {
|
||||
if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) {
|
||||
cpu_io();
|
||||
}
|
||||
}
|
||||
|
||||
/* The next 3 functions control bus timing for the CPU.
|
||||
* cpu_io is an I/O cycle, and always 6 clock cycles long.
|
||||
* mem_read / mem_write indicate memory access bus cycle,
|
||||
* they are either 6, 8, or 12 bus cycles long, depending
|
||||
* both on location and the $420d.d0 FastROM enable bit.
|
||||
*/
|
||||
|
||||
void bCPU::cpu_io() {
|
||||
status.cycle_count = 6;
|
||||
pre_exec_cycle();
|
||||
add_cycles(6);
|
||||
}
|
||||
|
||||
uint8 bCPU::mem_read(uint32 addr) {
|
||||
status.cycle_count = mem_bus->speed(addr);
|
||||
pre_exec_cycle();
|
||||
add_cycles(status.cycle_count - 4);
|
||||
regs.mdr = mem_bus->read(addr);
|
||||
add_cycles(4);
|
||||
return regs.mdr;
|
||||
}
|
||||
|
||||
void bCPU::mem_write(uint32 addr, uint8 value) {
|
||||
status.cycle_count = mem_bus->speed(addr);
|
||||
pre_exec_cycle();
|
||||
add_cycles(status.cycle_count);
|
||||
mem_bus->write(addr, value);
|
||||
}
|
||||
|
||||
uint32 bCPU::op_addr(uint8 mode, uint32 addr) {
|
||||
switch(mode) {
|
||||
case OPMODE_ADDR:
|
||||
addr &= 0xffff;
|
||||
break;
|
||||
case OPMODE_LONG:
|
||||
addr &= 0xffffff;
|
||||
break;
|
||||
case OPMODE_DBR:
|
||||
addr = ((regs.db << 16) + addr) & 0xffffff;
|
||||
break;
|
||||
case OPMODE_PBR:
|
||||
addr &= 0xffff;
|
||||
addr = (regs.pc.b << 16) + addr;
|
||||
break;
|
||||
case OPMODE_DP:
|
||||
addr &= 0xffff;
|
||||
addr = (regs.d + addr) & 0xffff;
|
||||
break;
|
||||
case OPMODE_SP:
|
||||
addr &= 0xffff;
|
||||
addr = (regs.s + addr) & 0xffff;
|
||||
break;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
uint8 bCPU::op_read() {
|
||||
uint8 r;
|
||||
r = mem_read(regs.pc.d);
|
||||
regs.pc.w++;
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8 bCPU::op_read(uint8 mode, uint32 addr) {
|
||||
addr = op_addr(mode, addr);
|
||||
return mem_read(addr);
|
||||
}
|
||||
|
||||
void bCPU::op_write(uint8 mode, uint32 addr, uint8 value) {
|
||||
addr = op_addr(mode, addr);
|
||||
mem_write(addr, value);
|
||||
}
|
||||
|
||||
uint8 bCPU::stack_read() {
|
||||
if(regs.e) {
|
||||
regs.s.l++;
|
||||
} else {
|
||||
regs.s.w++;
|
||||
}
|
||||
return mem_read(regs.s);
|
||||
}
|
||||
|
||||
void bCPU::stack_write(uint8 value) {
|
||||
mem_write(regs.s, value);
|
||||
if(regs.e) {
|
||||
regs.s.l--;
|
||||
} else {
|
||||
regs.s.w--;
|
||||
}
|
||||
}
|
||||
|
||||
bCPU::bCPU() {
|
||||
mmio = new bCPUMMIO(this);
|
||||
init_op_tables();
|
||||
}
|
||||
|
||||
bCPU::~bCPU() {
|
||||
delete(mmio);
|
||||
}
|
||||
@@ -1,316 +0,0 @@
|
||||
class bCPU;
|
||||
|
||||
class bCPUMMIO : public MMIO {
|
||||
public:
|
||||
bCPU *cpu;
|
||||
inline uint8 read (uint32 addr);
|
||||
inline void write(uint32 addr, uint8 value);
|
||||
bCPUMMIO(bCPU *_cpu);
|
||||
};
|
||||
|
||||
class bCPU : public CPU {
|
||||
private:
|
||||
void (bCPU::*optbl[256])();
|
||||
|
||||
enum { NTSC = 0, PAL = 1 };
|
||||
uint8 region;
|
||||
|
||||
public:
|
||||
#include "bcpu_timing.h"
|
||||
|
||||
uint8 apu_port[4];
|
||||
inline uint8 port_read (uint8 port);
|
||||
inline void port_write(uint8 port, uint8 value);
|
||||
|
||||
enum {
|
||||
OPMODE_ADDR = 1, OPMODE_LONG = 2,
|
||||
OPMODE_DBR = 3, OPMODE_PBR = 4,
|
||||
OPMODE_DP = 5, OPMODE_SP = 6
|
||||
};
|
||||
|
||||
CPUReg24 aa, rd;
|
||||
uint8 dp, sp;
|
||||
|
||||
enum {
|
||||
DMASTATE_DMASYNC,
|
||||
DMASTATE_DMASYNC2,
|
||||
DMASTATE_DMASYNC3,
|
||||
DMASTATE_RUN,
|
||||
DMASTATE_CPUSYNC,
|
||||
|
||||
HDMASTATE_IDMASYNC,
|
||||
HDMASTATE_IDMASYNC2,
|
||||
HDMASTATE_IDMASYNC3,
|
||||
HDMASTATE_ICPUSYNC,
|
||||
|
||||
HDMASTATE_DMASYNC,
|
||||
HDMASTATE_DMASYNC2,
|
||||
HDMASTATE_DMASYNC3,
|
||||
HDMASTATE_RUN,
|
||||
HDMASTATE_CPUSYNC
|
||||
};
|
||||
|
||||
struct {
|
||||
bool hdma;
|
||||
bool dma;
|
||||
bool irq;
|
||||
bool stp;
|
||||
bool wai;
|
||||
} run_state;
|
||||
|
||||
struct {
|
||||
uint8 cycle_pos, cycle_count;
|
||||
uint8 opcode;
|
||||
uint32 cycles_executed;
|
||||
|
||||
uint8 dma_state, hdma_state;
|
||||
uint32 dma_cycle_count, hdma_cycle_count;
|
||||
|
||||
//$4207-$420a
|
||||
uint16 virq_trigger, hirq_trigger;
|
||||
|
||||
//$2181-$2183
|
||||
uint32 wram_addr;
|
||||
|
||||
//$4016-$4017
|
||||
uint8 joypad1_strobe_value, joypad2_strobe_value;
|
||||
uint8 joypad1_read_pos, joypad2_read_pos;
|
||||
|
||||
//$4200
|
||||
bool nmi_enabled;
|
||||
bool hirq_enabled, virq_enabled;
|
||||
bool auto_joypad_poll;
|
||||
|
||||
//$4201
|
||||
uint8 pio;
|
||||
|
||||
//$4202-$4203
|
||||
uint8 mul_a, mul_b;
|
||||
|
||||
//$4204-$4206
|
||||
uint16 div_a;
|
||||
uint8 div_b;
|
||||
|
||||
//$4207-$420a
|
||||
uint16 hirq_pos, virq_pos;
|
||||
|
||||
//$4214-$4216
|
||||
uint16 r4214;
|
||||
uint16 r4216;
|
||||
} status;
|
||||
|
||||
//$43x0.d7
|
||||
enum {
|
||||
DMA_CPUTOMMIO = 0,
|
||||
DMA_MMIOTOCPU = 1
|
||||
};
|
||||
|
||||
struct {
|
||||
uint32 read_index; //set to 0 at beginning of DMA/HDMA
|
||||
|
||||
//$420b
|
||||
bool active;
|
||||
//$420c
|
||||
bool hdma_enabled;
|
||||
//$43x0
|
||||
uint8 dmap;
|
||||
bool direction;
|
||||
bool hdma_indirect;
|
||||
int8 incmode;
|
||||
bool fixedxfer;
|
||||
uint8 xfermode;
|
||||
//$43x1
|
||||
uint8 destaddr;
|
||||
//$43x2-$43x3
|
||||
uint16 srcaddr;
|
||||
//$43x4
|
||||
uint8 srcbank;
|
||||
//$43x5-$43x6
|
||||
union {
|
||||
uint16 xfersize;
|
||||
uint16 hdma_iaddr;
|
||||
};
|
||||
//$43x7
|
||||
uint8 hdma_ibank;
|
||||
//$43x8-$43x9
|
||||
uint16 hdma_addr;
|
||||
//$43xa
|
||||
uint8 hdma_line_counter;
|
||||
//$43xb/$43xf
|
||||
uint8 hdma_unknown;
|
||||
|
||||
//hdma-specific
|
||||
bool hdma_active;
|
||||
bool hdma_do_transfer;
|
||||
} channel[8];
|
||||
|
||||
inline bool hdma_test();
|
||||
inline bool nmi_test();
|
||||
inline bool irq_test();
|
||||
|
||||
inline uint8 pio_status();
|
||||
inline void run();
|
||||
inline uint32 cycles_executed();
|
||||
inline void scanline();
|
||||
inline void frame();
|
||||
inline void power();
|
||||
inline void reset();
|
||||
|
||||
inline void irq_run();
|
||||
|
||||
//dma commands
|
||||
inline void dma_add_cycles(uint32 cycles);
|
||||
inline void hdma_add_cycles(uint32 cycles);
|
||||
inline void dma_run();
|
||||
inline void hdma_run();
|
||||
inline void hdma_update(uint8 i);
|
||||
inline uint8 hdma_enabled_channels();
|
||||
inline uint8 hdma_active_channels();
|
||||
inline void hdmainit_activate();
|
||||
inline void hdma_activate();
|
||||
inline void dma_cputommio(uint8 i, uint8 index);
|
||||
inline void dma_mmiotocpu(uint8 i, uint8 index);
|
||||
inline void dma_write(uint8 i, uint8 index);
|
||||
inline uint32 dma_addr(uint8 i);
|
||||
inline uint32 hdma_addr(uint8 i);
|
||||
inline uint32 hdma_iaddr(uint8 i);
|
||||
inline uint16 hdma_mmio(uint8 i);
|
||||
inline uint8 hdma_read(uint8 i);
|
||||
inline void hdma_write(uint8 i, uint8 x);
|
||||
inline void dma_reset();
|
||||
|
||||
//mmio commands
|
||||
void mmio_reset();
|
||||
uint8 mmio_r2180();
|
||||
uint8 mmio_r4016();
|
||||
uint8 mmio_r4017();
|
||||
uint8 mmio_r4210();
|
||||
uint8 mmio_r4211();
|
||||
uint8 mmio_r4212();
|
||||
uint8 mmio_r4213();
|
||||
uint8 mmio_r4214();
|
||||
uint8 mmio_r4215();
|
||||
uint8 mmio_r4216();
|
||||
uint8 mmio_r4217();
|
||||
uint8 mmio_r4218();
|
||||
uint8 mmio_r4219();
|
||||
uint8 mmio_r421a();
|
||||
uint8 mmio_r421b();
|
||||
uint8 mmio_r43x0(uint8 i);
|
||||
uint8 mmio_r43x1(uint8 i);
|
||||
uint8 mmio_r43x2(uint8 i);
|
||||
uint8 mmio_r43x3(uint8 i);
|
||||
uint8 mmio_r43x4(uint8 i);
|
||||
uint8 mmio_r43x5(uint8 i);
|
||||
uint8 mmio_r43x6(uint8 i);
|
||||
uint8 mmio_r43x7(uint8 i);
|
||||
uint8 mmio_r43x8(uint8 i);
|
||||
uint8 mmio_r43x9(uint8 i);
|
||||
uint8 mmio_r43xa(uint8 i);
|
||||
uint8 mmio_r43xb(uint8 i);
|
||||
void mmio_w2180(uint8 value);
|
||||
void mmio_w2181(uint8 value);
|
||||
void mmio_w2182(uint8 value);
|
||||
void mmio_w2183(uint8 value);
|
||||
void mmio_w4016(uint8 value);
|
||||
void mmio_w4017(uint8 value);
|
||||
void mmio_w4200(uint8 value);
|
||||
void mmio_w4201(uint8 value);
|
||||
void mmio_w4202(uint8 value);
|
||||
void mmio_w4203(uint8 value);
|
||||
void mmio_w4204(uint8 value);
|
||||
void mmio_w4205(uint8 value);
|
||||
void mmio_w4206(uint8 value);
|
||||
void mmio_w4207(uint8 value);
|
||||
void mmio_w4208(uint8 value);
|
||||
void mmio_w4209(uint8 value);
|
||||
void mmio_w420a(uint8 value);
|
||||
void mmio_w420b(uint8 value);
|
||||
void mmio_w420c(uint8 value);
|
||||
void mmio_w420d(uint8 value);
|
||||
void mmio_w43x0(uint8 value, uint8 i);
|
||||
void mmio_w43x1(uint8 value, uint8 i);
|
||||
void mmio_w43x2(uint8 value, uint8 i);
|
||||
void mmio_w43x3(uint8 value, uint8 i);
|
||||
void mmio_w43x4(uint8 value, uint8 i);
|
||||
void mmio_w43x5(uint8 value, uint8 i);
|
||||
void mmio_w43x6(uint8 value, uint8 i);
|
||||
void mmio_w43x7(uint8 value, uint8 i);
|
||||
void mmio_w43x8(uint8 value, uint8 i);
|
||||
void mmio_w43x9(uint8 value, uint8 i);
|
||||
void mmio_w43xa(uint8 value, uint8 i);
|
||||
void mmio_w43xb(uint8 value, uint8 i);
|
||||
|
||||
enum { CYCLE_OPREAD = 0, CYCLE_READ, CYCLE_WRITE, CYCLE_IO };
|
||||
inline void pre_exec_cycle();
|
||||
inline void exec_hdma();
|
||||
inline void exec_dma();
|
||||
inline void exec_cycle();
|
||||
inline void last_cycle();
|
||||
inline bool in_opcode();
|
||||
|
||||
//cpu extra-cycle conditions
|
||||
inline void cpu_c2();
|
||||
inline void cpu_c4(uint16 x, uint16 y);
|
||||
inline void cpu_c6(uint16 addr);
|
||||
inline void cpu_io();
|
||||
|
||||
inline uint8 mem_read (uint32 addr);
|
||||
inline void mem_write(uint32 addr, uint8 value);
|
||||
inline uint32 op_addr(uint8 mode, uint32 addr);
|
||||
inline uint8 op_read();
|
||||
inline uint8 op_read(uint8 mode, uint32 addr);
|
||||
inline void op_write(uint8 mode, uint32 addr, uint8 value);
|
||||
inline uint8 stack_read();
|
||||
inline void stack_write(uint8 value);
|
||||
|
||||
//opcode functions
|
||||
inline void init_op_tables();
|
||||
|
||||
//op_read
|
||||
inline void op_adc_b();
|
||||
inline void op_adc_w();
|
||||
inline void op_and_b();
|
||||
inline void op_and_w();
|
||||
inline void op_bit_b();
|
||||
inline void op_bit_w();
|
||||
inline void op_cmp_b();
|
||||
inline void op_cmp_w();
|
||||
inline void op_cpx_b();
|
||||
inline void op_cpx_w();
|
||||
inline void op_cpy_b();
|
||||
inline void op_cpy_w();
|
||||
inline void op_eor_b();
|
||||
inline void op_eor_w();
|
||||
inline void op_lda_b();
|
||||
inline void op_lda_w();
|
||||
inline void op_ldx_b();
|
||||
inline void op_ldx_w();
|
||||
inline void op_ldy_b();
|
||||
inline void op_ldy_w();
|
||||
inline void op_ora_b();
|
||||
inline void op_ora_w();
|
||||
inline void op_sbc_b();
|
||||
inline void op_sbc_w();
|
||||
//op_rmw
|
||||
inline void op_inc_b();
|
||||
inline void op_inc_w();
|
||||
inline void op_dec_b();
|
||||
inline void op_dec_w();
|
||||
inline void op_asl_b();
|
||||
inline void op_asl_w();
|
||||
inline void op_lsr_b();
|
||||
inline void op_lsr_w();
|
||||
inline void op_rol_b();
|
||||
inline void op_rol_w();
|
||||
inline void op_ror_b();
|
||||
inline void op_ror_w();
|
||||
inline void op_trb_b();
|
||||
inline void op_trb_w();
|
||||
inline void op_tsb_b();
|
||||
inline void op_tsb_w();
|
||||
#include "bcpu_op.h"
|
||||
|
||||
bCPU();
|
||||
~bCPU();
|
||||
};
|
||||
@@ -1,250 +0,0 @@
|
||||
void bCPU::dma_add_cycles(uint32 cycles) {
|
||||
status.dma_cycle_count += cycles;
|
||||
}
|
||||
|
||||
void bCPU::hdma_add_cycles(uint32 cycles) {
|
||||
if(run_state.dma) {
|
||||
status.dma_cycle_count += cycles;
|
||||
}
|
||||
status.hdma_cycle_count += cycles;
|
||||
}
|
||||
|
||||
uint32 bCPU::dma_addr(uint8 i) {
|
||||
uint32 r;
|
||||
r = (channel[i].srcbank << 16) | (channel[i].srcaddr);
|
||||
|
||||
if(channel[i].fixedxfer == false) {
|
||||
channel[i].srcaddr += channel[i].incmode;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void bCPU::dma_cputommio(uint8 i, uint8 index) {
|
||||
uint8 x;
|
||||
if(sdd1->dma_active() == true) {
|
||||
x = sdd1->dma_read();
|
||||
} else {
|
||||
x = mem_bus->read(dma_addr(i));
|
||||
}
|
||||
|
||||
mem_bus->write(0x2100 | ((channel[i].destaddr + index) & 0xff), x);
|
||||
|
||||
add_cycles(8);
|
||||
channel[i].xfersize--;
|
||||
}
|
||||
|
||||
void bCPU::dma_mmiotocpu(uint8 i, uint8 index) {
|
||||
uint8 x;
|
||||
x = mem_bus->read(0x2100 | ((channel[i].destaddr + index) & 0xff));
|
||||
mem_bus->write(dma_addr(i), x);
|
||||
|
||||
add_cycles(8);
|
||||
channel[i].xfersize--;
|
||||
}
|
||||
|
||||
void bCPU::dma_write(uint8 i, uint8 index) {
|
||||
if(channel[i].direction == 0) {
|
||||
dma_cputommio(i, index);
|
||||
} else {
|
||||
dma_mmiotocpu(i, index);
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::dma_run() {
|
||||
int i;
|
||||
for(i=0;i<8;i++) {
|
||||
if(channel[i].active == false)continue;
|
||||
|
||||
//first byte transferred?
|
||||
if(channel[i].read_index == 0) {
|
||||
sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr),
|
||||
channel[i].xfersize);
|
||||
}
|
||||
|
||||
switch(channel[i].xfermode) {
|
||||
case 0:dma_write(i, 0); break; //0
|
||||
case 1:dma_write(i, channel[i].read_index & 1); break; //0,1
|
||||
case 2:dma_write(i, 0); break; //0,0
|
||||
case 3:dma_write(i, (channel[i].read_index >> 1) & 1);break; //0,0,1,1
|
||||
case 4:dma_write(i, channel[i].read_index & 3); break; //0,1,2,3
|
||||
case 5:dma_write(i, channel[i].read_index & 1); break; //0,1,0,1
|
||||
case 6:dma_write(i, 0); break; //0,0 [2]
|
||||
case 7:dma_write(i, (channel[i].read_index >> 1) & 1);break; //0,0,1,1 [3]
|
||||
}
|
||||
|
||||
channel[i].read_index++;
|
||||
dma_add_cycles(8);
|
||||
|
||||
if(channel[i].xfersize == 0) {
|
||||
channel[i].active = false;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
status.dma_state = DMASTATE_CPUSYNC;
|
||||
}
|
||||
|
||||
uint32 bCPU::hdma_addr(uint8 i) {
|
||||
return (channel[i].srcbank << 16) | (channel[i].hdma_addr++);
|
||||
}
|
||||
|
||||
uint32 bCPU::hdma_iaddr(uint8 i) {
|
||||
return (channel[i].hdma_ibank << 16) | (channel[i].hdma_iaddr++);
|
||||
}
|
||||
|
||||
uint16 bCPU::hdma_mmio(uint8 i) {
|
||||
uint8 l = channel[i].read_index;
|
||||
uint16 index;
|
||||
switch(channel[i].xfermode) {
|
||||
case 0:index = 0; break; //0
|
||||
case 1:index = l & 1; break; //0,1
|
||||
case 2:index = 0; break; //0,0
|
||||
case 3:index = (l >> 1) & 1;break; //0,0,1,1
|
||||
case 4:index = l & 3; break; //0,1,2,3
|
||||
case 5:index = l & 1; break; //0,1,0,1
|
||||
case 6:index = 0; break; //0,0 [2]
|
||||
case 7:index = (l >> 1) & 1;break; //0,0,1,1 [3]
|
||||
}
|
||||
|
||||
return (0x2100 | ((channel[i].destaddr + index) & 0xff));
|
||||
}
|
||||
|
||||
uint8 bCPU::hdma_read(uint8 i) {
|
||||
if(channel[i].direction == DMA_MMIOTOCPU) {
|
||||
return mem_bus->read(hdma_mmio(i));
|
||||
} else if(!channel[i].hdma_indirect) {
|
||||
return mem_bus->read(hdma_addr(i));
|
||||
} else {
|
||||
return mem_bus->read(hdma_iaddr(i));
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::hdma_write(uint8 i, uint8 x) {
|
||||
if(channel[i].direction == DMA_CPUTOMMIO) {
|
||||
mem_bus->write(hdma_mmio(i), x);
|
||||
} else if(!channel[i].hdma_indirect) {
|
||||
mem_bus->write(hdma_addr(i), x);
|
||||
} else {
|
||||
mem_bus->write(hdma_iaddr(i), x);
|
||||
}
|
||||
|
||||
add_cycles(8);
|
||||
hdma_add_cycles(8);
|
||||
}
|
||||
|
||||
void bCPU::hdma_update(uint8 i) {
|
||||
channel[i].hdma_line_counter = mem_bus->read(hdma_addr(i));
|
||||
add_cycles(8);
|
||||
hdma_add_cycles(8);
|
||||
|
||||
if(channel[i].hdma_indirect) {
|
||||
channel[i].hdma_iaddr = mem_bus->read(hdma_addr(i)) << 8;
|
||||
add_cycles(8);
|
||||
hdma_add_cycles(8);
|
||||
}
|
||||
|
||||
if(channel[i].hdma_line_counter == 0) {
|
||||
channel[i].hdma_active = false;
|
||||
channel[i].hdma_do_transfer = false;
|
||||
return;
|
||||
}
|
||||
|
||||
channel[i].hdma_do_transfer = true;
|
||||
|
||||
if(channel[i].hdma_indirect) {
|
||||
channel[i].hdma_iaddr >>= 8;
|
||||
channel[i].hdma_iaddr |= mem_bus->read(hdma_addr(i)) << 8;
|
||||
add_cycles(8);
|
||||
hdma_add_cycles(8);
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::hdma_run() {
|
||||
static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
|
||||
for(int i=0;i<8;i++) {
|
||||
if(!channel[i].hdma_enabled || !channel[i].hdma_active)continue;
|
||||
|
||||
if(channel[i].hdma_do_transfer) {
|
||||
int xferlen = hdma_xferlen[channel[i].xfermode];
|
||||
for(channel[i].read_index=0;channel[i].read_index<xferlen;channel[i].read_index++) {
|
||||
hdma_write(i, hdma_read(i));
|
||||
}
|
||||
}
|
||||
|
||||
channel[i].hdma_line_counter--;
|
||||
channel[i].hdma_do_transfer = !!(channel[i].hdma_line_counter & 0x80);
|
||||
if((channel[i].hdma_line_counter & 0x7f) == 0) {
|
||||
hdma_update(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8 bCPU::hdma_enabled_channels() {
|
||||
int r = 0;
|
||||
for(int i=0;i<8;i++) {
|
||||
if(channel[i].hdma_enabled)r++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8 bCPU::hdma_active_channels() {
|
||||
int r = 0;
|
||||
for(int i=0;i<8;i++) {
|
||||
if(channel[i].hdma_enabled && channel[i].hdma_active)r++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* hdmainit_activate()
|
||||
* hdma_activate()
|
||||
*
|
||||
* Functions are called by CPU timing routine
|
||||
* when an HDMA event (init or run) occurs.
|
||||
*/
|
||||
|
||||
void bCPU::hdmainit_activate() {
|
||||
for(int i=0;i<8;i++) {
|
||||
channel[i].hdma_active = false;
|
||||
channel[i].hdma_do_transfer = false;
|
||||
}
|
||||
|
||||
if(hdma_enabled_channels() != 0) {
|
||||
status.hdma_state = HDMASTATE_IDMASYNC;
|
||||
run_state.hdma = true;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::hdma_activate() {
|
||||
if(hdma_active_channels() != 0) {
|
||||
status.hdma_state = HDMASTATE_DMASYNC;
|
||||
run_state.hdma = true;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::dma_reset() {
|
||||
for(int i=0;i<8;i++) {
|
||||
channel[i].read_index = 0;
|
||||
channel[i].active = false;
|
||||
channel[i].hdma_enabled = false;
|
||||
channel[i].dmap = 0x00;
|
||||
channel[i].direction = 0;
|
||||
channel[i].hdma_indirect = false;
|
||||
channel[i].incmode = 1;
|
||||
channel[i].fixedxfer = false;
|
||||
channel[i].xfermode = 0;
|
||||
channel[i].destaddr = 0;
|
||||
channel[i].srcaddr = 0;
|
||||
channel[i].xfersize = 0x0000;
|
||||
//xfersize and hdma_iaddr are of union { uint16 };
|
||||
//channel[i].hdma_iaddr = 0x0000;
|
||||
channel[i].hdma_ibank = 0;
|
||||
channel[i].hdma_addr = 0x0000;
|
||||
channel[i].hdma_line_counter = 0x00;
|
||||
channel[i].hdma_unknown = 0x00;
|
||||
|
||||
channel[i].hdma_active = false;
|
||||
channel[i].hdma_do_transfer = false;
|
||||
}
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
void bCPU::last_cycle() {
|
||||
time.nmi_pending = nmi_test();
|
||||
time.irq_pending = irq_test();
|
||||
}
|
||||
|
||||
void bCPU::pre_exec_cycle() {
|
||||
if(!run_state.dma && !run_state.hdma)return;
|
||||
|
||||
int c, z;
|
||||
if(run_state.hdma) {
|
||||
switch(status.hdma_state) {
|
||||
case HDMASTATE_ICPUSYNC:
|
||||
case HDMASTATE_CPUSYNC:
|
||||
c = status.cycle_count;
|
||||
z = c - (status.hdma_cycle_count % c);
|
||||
if(!z)z = c;
|
||||
add_cycles(z);
|
||||
run_state.hdma = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(run_state.dma) {
|
||||
switch(status.dma_state) {
|
||||
case DMASTATE_CPUSYNC:
|
||||
c = status.cycle_count;
|
||||
z = c - (status.dma_cycle_count % c);
|
||||
if(!z)z = c;
|
||||
add_cycles(z);
|
||||
run_state.dma = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::exec_hdma() {
|
||||
int n;
|
||||
static int z;
|
||||
switch(status.hdma_state) {
|
||||
case HDMASTATE_IDMASYNC:
|
||||
status.hdma_cycle_count = 0;
|
||||
z = 0;
|
||||
if(!run_state.dma) {
|
||||
exec_cycle();
|
||||
status.hdma_state = HDMASTATE_IDMASYNC2;
|
||||
} else {
|
||||
status.hdma_state = HDMASTATE_IDMASYNC3;
|
||||
}
|
||||
break;
|
||||
case HDMASTATE_IDMASYNC2:
|
||||
n = 8 - dma_counter() + 8;
|
||||
add_cycles(n);
|
||||
status.hdma_cycle_count += n;
|
||||
status.hdma_state = HDMASTATE_IDMASYNC3;
|
||||
break;
|
||||
case HDMASTATE_IDMASYNC3:
|
||||
channel[z].hdma_active = channel[z].hdma_enabled;
|
||||
if(channel[z].hdma_enabled) {
|
||||
channel[z].hdma_addr = channel[z].srcaddr;
|
||||
hdma_update(z); //updates status.hdma_cycle_count
|
||||
}
|
||||
if(++z < 8)break;
|
||||
if(!run_state.dma) {
|
||||
status.hdma_state = HDMASTATE_ICPUSYNC;
|
||||
} else {
|
||||
run_state.hdma = false;
|
||||
}
|
||||
break;
|
||||
case HDMASTATE_ICPUSYNC:
|
||||
exec_cycle();
|
||||
break;
|
||||
|
||||
case HDMASTATE_DMASYNC:
|
||||
status.hdma_cycle_count = 0;
|
||||
z = 0;
|
||||
if(!run_state.dma) {
|
||||
exec_cycle();
|
||||
status.hdma_state = HDMASTATE_DMASYNC2;
|
||||
} else {
|
||||
status.hdma_state = HDMASTATE_DMASYNC3;
|
||||
}
|
||||
break;
|
||||
case HDMASTATE_DMASYNC2:
|
||||
n = 8 - dma_counter() + 8;
|
||||
add_cycles(n);
|
||||
status.hdma_cycle_count += n;
|
||||
status.hdma_state = HDMASTATE_DMASYNC3;
|
||||
break;
|
||||
case HDMASTATE_DMASYNC3:
|
||||
if(channel[z].hdma_active) {
|
||||
add_cycles(8);
|
||||
status.hdma_cycle_count += 8;
|
||||
}
|
||||
if(++z < 8)break;
|
||||
status.hdma_state = HDMASTATE_RUN;
|
||||
break;
|
||||
case HDMASTATE_RUN:
|
||||
hdma_run(); //updates status.hdma_cycle_count
|
||||
if(!run_state.dma) {
|
||||
status.hdma_state = HDMASTATE_CPUSYNC;
|
||||
} else {
|
||||
run_state.hdma = false;
|
||||
}
|
||||
break;
|
||||
case HDMASTATE_CPUSYNC:
|
||||
exec_cycle();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::exec_dma() {
|
||||
int n;
|
||||
static int z;
|
||||
switch(status.dma_state) {
|
||||
case DMASTATE_DMASYNC:
|
||||
exec_cycle();
|
||||
status.dma_state = DMASTATE_DMASYNC2;
|
||||
break;
|
||||
case DMASTATE_DMASYNC2:
|
||||
n = 8 - dma_counter() + 8;
|
||||
add_cycles(n);
|
||||
status.dma_cycle_count = n;
|
||||
z = 0;
|
||||
status.dma_state = DMASTATE_DMASYNC3;
|
||||
break;
|
||||
case DMASTATE_DMASYNC3:
|
||||
if(channel[z].active == true) {
|
||||
add_cycles(8);
|
||||
status.dma_cycle_count += 8;
|
||||
}
|
||||
if(++z < 8)break;
|
||||
status.dma_state = DMASTATE_RUN;
|
||||
break;
|
||||
case DMASTATE_RUN:
|
||||
dma_run(); //updates status.dma_cycle_count
|
||||
break;
|
||||
case DMASTATE_CPUSYNC:
|
||||
exec_cycle();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::exec_cycle() {
|
||||
//on first cycle?
|
||||
if(status.cycle_pos == 0) {
|
||||
snes->notify(SNES::CPU_EXEC_OPCODE_BEGIN);
|
||||
status.opcode = op_read();
|
||||
status.cycle_pos = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
(this->*optbl[status.opcode])();
|
||||
if(status.cycle_pos == 0) {
|
||||
snes->notify(SNES::CPU_EXEC_OPCODE_END);
|
||||
}
|
||||
}
|
||||
|
||||
//only return true when we are on an opcode edge
|
||||
bool bCPU::in_opcode() {
|
||||
return (status.cycle_pos != 0);
|
||||
}
|
||||
|
||||
void bCPU::init_op_tables() {
|
||||
#include "bcpu_optable.cpp"
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
[IRQ cycles]
|
||||
[0] pbr,pc ; opcode
|
||||
[1] pbr,pc ; io
|
||||
[2] 0,s ; pbr
|
||||
[3] 0,s-1 ; pch
|
||||
[4] 0,s-2 ; pcl
|
||||
[5] 0,s-3 ; p
|
||||
[6] 0,va ; aavl
|
||||
[7] 0,va+1 ; aavh
|
||||
*/
|
||||
void bCPU::irq_run() {
|
||||
//WDC documentation is incorrect, first cycle
|
||||
//is a memory read fetch from PBR:PC
|
||||
switch(status.cycle_pos++) {
|
||||
case 0: add_cycles(mem_bus->speed(regs.pc.d)); break;
|
||||
case 1: add_cycles(6); break;
|
||||
case 2: stack_write(regs.pc.b); break;
|
||||
case 3: stack_write(regs.pc.h); break;
|
||||
case 4: stack_write(regs.pc.l); break;
|
||||
case 5: stack_write(regs.p); break;
|
||||
case 6: rd.l = op_read(OPMODE_ADDR, aa.w); break;
|
||||
case 7: rd.h = op_read(OPMODE_ADDR, aa.w + 1);
|
||||
regs.pc.b = 0x00;
|
||||
regs.pc.w = rd.w;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
//let debugger know the new IRQ opcode address
|
||||
snes->notify(SNES::CPU_EXEC_OPCODE_END);
|
||||
status.cycle_pos = 0;
|
||||
run_state.irq = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool bCPU::nmi_test() {
|
||||
if(time.nmi_transition == 0)return false;
|
||||
time.nmi_transition = 0;
|
||||
|
||||
run_state.wai = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bCPU::irq_test() {
|
||||
if(time.irq_transition == 1)goto _true;
|
||||
|
||||
if(time.irq_read == 0) {
|
||||
if(time.irq_line == 1 && (irq_trigger_pos_match(0) || irq_trigger_pos_match(2))) {
|
||||
return false;
|
||||
}
|
||||
goto _true;
|
||||
}
|
||||
|
||||
if(time.irq_line == 0) {
|
||||
time.irq_line = 1;
|
||||
goto _true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
_true:
|
||||
time.irq_transition = 0;
|
||||
|
||||
run_state.wai = false;
|
||||
if(regs.p.i)return false;
|
||||
return true;
|
||||
}
|
||||
@@ -1,653 +0,0 @@
|
||||
void bCPU::mmio_reset() {
|
||||
//$2181-$2183
|
||||
status.wram_addr = 0x000000;
|
||||
|
||||
//$4016-$4017
|
||||
status.joypad1_strobe_value = 0x00;
|
||||
status.joypad2_strobe_value = 0x00;
|
||||
status.joypad1_read_pos = 0;
|
||||
status.joypad2_read_pos = 0;
|
||||
|
||||
//$4200
|
||||
status.nmi_enabled = false;
|
||||
status.hirq_enabled = false;
|
||||
status.virq_enabled = false;
|
||||
status.auto_joypad_poll = false;
|
||||
|
||||
//$4201
|
||||
status.pio = 0xff;
|
||||
|
||||
//$4202-$4203
|
||||
status.mul_a = 0x00;
|
||||
status.mul_b = 0x00;
|
||||
|
||||
//$4204-$4206
|
||||
status.div_a = 0x0000;
|
||||
status.div_b = 0x00;
|
||||
|
||||
//$4207-$420a
|
||||
status.hirq_pos = 0;
|
||||
status.virq_pos = 0;
|
||||
|
||||
//$4214-$4217
|
||||
status.r4214 = 0x0000;
|
||||
status.r4216 = 0x0000;
|
||||
}
|
||||
|
||||
//WMDATA
|
||||
uint8 bCPU::mmio_r2180() {
|
||||
uint8 r;
|
||||
r = mem_bus->read(0x7e0000 | status.wram_addr);
|
||||
status.wram_addr++;
|
||||
status.wram_addr &= 0x01ffff;
|
||||
return r;
|
||||
}
|
||||
|
||||
//JOYSER0
|
||||
//7-2 = MDR
|
||||
//1-0 = Joypad serial data
|
||||
/* The joypad contains a small bit shifter that has 16 bits.
|
||||
* Reading from 4016 reads one bit from this buffer, then moves
|
||||
* the buffer left one, and adds a '1' to the rightmost bit.
|
||||
* Writing a one to $4016 will fill the buffer with the current
|
||||
* joypad button states, and lock the bit shifter at position
|
||||
* zero. All reads will be the first buffer state, or 'B'.
|
||||
* A zero must be written back to $4016 to unlock the buffer,
|
||||
* so that reads will increment the bit shifting position.
|
||||
*/
|
||||
uint8 bCPU::mmio_r4016() {
|
||||
uint8 r;
|
||||
r = regs.mdr & 0xfc;
|
||||
|
||||
if(status.joypad1_strobe_value == 1) {
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B);
|
||||
} else {
|
||||
switch(status.joypad1_read_pos) {
|
||||
case 0:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B); break;
|
||||
case 1:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_Y); break;
|
||||
case 2:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_SELECT);break;
|
||||
case 3:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_START); break;
|
||||
case 4:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_UP); break;
|
||||
case 5:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_DOWN); break;
|
||||
case 6:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_LEFT); break;
|
||||
case 7:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_RIGHT); break;
|
||||
case 8:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_A); break;
|
||||
case 9:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_X); break;
|
||||
case 10:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_L); break;
|
||||
case 11:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_R); break;
|
||||
case 16:r |= 1;break; //joypad connected bit
|
||||
default:r |= 1;break; //after 16th read, all subsequent reads return 1
|
||||
}
|
||||
if(++status.joypad1_read_pos > 17)status.joypad1_read_pos = 17;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
//JOYSER1
|
||||
//7-5 = MDR
|
||||
//4-2 = Always 1
|
||||
//1-0 = Joypad serial data
|
||||
uint8 bCPU::mmio_r4017() {
|
||||
uint8 r;
|
||||
r = regs.mdr & 0xe0;
|
||||
r |= 0x1c;
|
||||
|
||||
if(status.joypad2_strobe_value == 1) {
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_B);
|
||||
} else {
|
||||
switch(status.joypad2_read_pos) {
|
||||
case 0:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_B); break;
|
||||
case 1:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_Y); break;
|
||||
case 2:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_SELECT);break;
|
||||
case 3:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_START); break;
|
||||
case 4:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_UP); break;
|
||||
case 5:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_DOWN); break;
|
||||
case 6:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_LEFT); break;
|
||||
case 7:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_RIGHT); break;
|
||||
case 8:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_A); break;
|
||||
case 9:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_X); break;
|
||||
case 10:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_L); break;
|
||||
case 11:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_R); break;
|
||||
case 16:r |= 1;break; //joypad connected bit
|
||||
default:r |= 1;break; //after 16th read, all subsequent reads return 1
|
||||
}
|
||||
if(++status.joypad2_read_pos > 17)status.joypad2_read_pos = 17;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
//RDNMI
|
||||
//7 = NMI acknowledge
|
||||
//6-4 = MDR
|
||||
//3-0 = CPU (5a22) version
|
||||
uint8 bCPU::mmio_r4210() {
|
||||
uint8 r;
|
||||
r = regs.mdr & 0x70;
|
||||
r |= uint8(!time.nmi_read) << 7;
|
||||
|
||||
if(!nmi_trigger_pos_match(0) && !nmi_trigger_pos_match(2)) {
|
||||
time.nmi_read = 1;
|
||||
}
|
||||
|
||||
r |= (cpu_version & 0x0f);
|
||||
return r;
|
||||
}
|
||||
|
||||
//TIMEUP
|
||||
//7 = IRQ acknowledge
|
||||
//6-0 = MDR
|
||||
uint8 bCPU::mmio_r4211() {
|
||||
uint8 r;
|
||||
r = regs.mdr & 0x7f;
|
||||
r |= uint8(!time.irq_read) << 7;
|
||||
|
||||
if(!irq_trigger_pos_match(0) && !irq_trigger_pos_match(2)) {
|
||||
time.irq_read = 1;
|
||||
time.irq_line = 1;
|
||||
time.irq_transition = 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
//HVBJOY
|
||||
//7 = in vblank
|
||||
//6 = in hblank
|
||||
//5-1 = MDR
|
||||
//0 = joypad ready
|
||||
uint8 bCPU::mmio_r4212() {
|
||||
uint8 r;
|
||||
r = regs.mdr & 0x3e;
|
||||
|
||||
uint16 vs = overscan() ? 240 : 225;
|
||||
|
||||
//auto joypad polling
|
||||
if(time.v >= vs && time.v <= (vs + 2))r |= 0x01;
|
||||
|
||||
//hblank
|
||||
if(time.hc <= 2 || time.hc >= 1096)r |= 0x40;
|
||||
|
||||
//vblank
|
||||
if(time.v >= vs)r |= 0x80;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
//RDIO
|
||||
uint8 bCPU::mmio_r4213() {
|
||||
return status.pio;
|
||||
}
|
||||
|
||||
//RDDIVL
|
||||
uint8 bCPU::mmio_r4214() {
|
||||
return status.r4214;
|
||||
}
|
||||
|
||||
//RDDIVH
|
||||
uint8 bCPU::mmio_r4215() {
|
||||
return status.r4214 >> 8;
|
||||
}
|
||||
|
||||
//RDMPYL
|
||||
uint8 bCPU::mmio_r4216() {
|
||||
return status.r4216;
|
||||
}
|
||||
|
||||
//RDMPYH
|
||||
uint8 bCPU::mmio_r4217() {
|
||||
return status.r4216 >> 8;
|
||||
}
|
||||
|
||||
//JOY1L
|
||||
uint8 bCPU::mmio_r4218() {
|
||||
uint8 r = 0x00;
|
||||
uint16 v = vcounter();
|
||||
if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled
|
||||
//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_A) << 7;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_X) << 6;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_L) << 5;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_R) << 4;
|
||||
return r;
|
||||
}
|
||||
|
||||
//JOY1H
|
||||
uint8 bCPU::mmio_r4219() {
|
||||
uint8 r = 0x00;
|
||||
uint16 v = vcounter();
|
||||
if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled
|
||||
//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B) << 7;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_Y) << 6;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_SELECT) << 5;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_START) << 4;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_UP) << 3;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_DOWN) << 2;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_LEFT) << 1;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_RIGHT);
|
||||
return r;
|
||||
}
|
||||
|
||||
//JOY2L
|
||||
uint8 bCPU::mmio_r421a() {
|
||||
uint8 r = 0x00;
|
||||
uint16 v = vcounter();
|
||||
if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled
|
||||
//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_A) << 7;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_X) << 6;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_L) << 5;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_R) << 4;
|
||||
return r;
|
||||
}
|
||||
|
||||
//JOY2H
|
||||
uint8 bCPU::mmio_r421b() {
|
||||
uint8 r = 0x00;
|
||||
uint16 v = vcounter();
|
||||
if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled
|
||||
//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_B) << 7;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_Y) << 6;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_SELECT) << 5;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_START) << 4;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_UP) << 3;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_DOWN) << 2;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_LEFT) << 1;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_RIGHT);
|
||||
return r;
|
||||
}
|
||||
|
||||
//DMAPx
|
||||
uint8 bCPU::mmio_r43x0(uint8 i) {
|
||||
return channel[i].dmap;
|
||||
}
|
||||
|
||||
//BBADx
|
||||
uint8 bCPU::mmio_r43x1(uint8 i) {
|
||||
return channel[i].destaddr;
|
||||
}
|
||||
|
||||
//A1TxL
|
||||
uint8 bCPU::mmio_r43x2(uint8 i) {
|
||||
return channel[i].srcaddr;
|
||||
}
|
||||
|
||||
//A1TxH
|
||||
uint8 bCPU::mmio_r43x3(uint8 i) {
|
||||
return channel[i].srcaddr >> 8;
|
||||
}
|
||||
|
||||
//A1Bx
|
||||
uint8 bCPU::mmio_r43x4(uint8 i) {
|
||||
return channel[i].srcbank;
|
||||
}
|
||||
|
||||
//DASxL
|
||||
uint8 bCPU::mmio_r43x5(uint8 i) {
|
||||
return channel[i].xfersize;
|
||||
}
|
||||
|
||||
//DASxH
|
||||
uint8 bCPU::mmio_r43x6(uint8 i) {
|
||||
return channel[i].xfersize >> 8;
|
||||
}
|
||||
|
||||
//DASBx
|
||||
uint8 bCPU::mmio_r43x7(uint8 i) {
|
||||
return channel[i].hdma_ibank;
|
||||
}
|
||||
|
||||
//A2AxL
|
||||
uint8 bCPU::mmio_r43x8(uint8 i) {
|
||||
return channel[i].hdma_addr;
|
||||
}
|
||||
|
||||
//A2AxH
|
||||
uint8 bCPU::mmio_r43x9(uint8 i) {
|
||||
return channel[i].hdma_addr >> 8;
|
||||
}
|
||||
|
||||
//NTRLx
|
||||
uint8 bCPU::mmio_r43xa(uint8 i) {
|
||||
return channel[i].hdma_line_counter;
|
||||
}
|
||||
|
||||
//???
|
||||
uint8 bCPU::mmio_r43xb(uint8 i) {
|
||||
return channel[i].hdma_unknown;
|
||||
}
|
||||
|
||||
uint8 bCPUMMIO::read(uint32 addr) {
|
||||
uint i;
|
||||
//APU
|
||||
if(addr >= 0x2140 && addr <= 0x217f) {
|
||||
return apu->port_read(addr & 3);
|
||||
}
|
||||
|
||||
//HDMA
|
||||
if(addr >= 0x4300 && addr <= 0x437f) {
|
||||
i = (addr >> 4) & 7;
|
||||
switch(addr & 0xf) {
|
||||
case 0x0:return cpu->mmio_r43x0(i);
|
||||
case 0x1:return cpu->mmio_r43x1(i);
|
||||
case 0x2:return cpu->mmio_r43x2(i);
|
||||
case 0x3:return cpu->mmio_r43x3(i);
|
||||
case 0x4:return cpu->mmio_r43x4(i);
|
||||
case 0x5:return cpu->mmio_r43x5(i);
|
||||
case 0x6:return cpu->mmio_r43x6(i);
|
||||
case 0x7:return cpu->mmio_r43x7(i);
|
||||
case 0x8:return cpu->mmio_r43x8(i);
|
||||
case 0x9:return cpu->mmio_r43x9(i);
|
||||
case 0xa:return cpu->mmio_r43xa(i);
|
||||
case 0xb:return cpu->mmio_r43xb(i);
|
||||
case 0xc:return cpu->regs.mdr; //unmapped
|
||||
case 0xd:return cpu->regs.mdr; //unmapped
|
||||
case 0xe:return cpu->regs.mdr; //unmapped
|
||||
case 0xf:return cpu->mmio_r43xb(i); //mirror of 43xb
|
||||
}
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
case 0x2180:return cpu->mmio_r2180(); //WMDATA
|
||||
case 0x4016:return cpu->mmio_r4016(); //JOYSER0
|
||||
case 0x4017:return cpu->mmio_r4017(); //JOYSER1
|
||||
case 0x4210:return cpu->mmio_r4210(); //RDNMI
|
||||
case 0x4211:return cpu->mmio_r4211(); //TIMEUP
|
||||
case 0x4212:return cpu->mmio_r4212(); //HVBJOY
|
||||
case 0x4213:return cpu->mmio_r4213(); //RDIO
|
||||
case 0x4214:return cpu->mmio_r4214(); //RDDIVL
|
||||
case 0x4215:return cpu->mmio_r4215(); //RDDIVH
|
||||
case 0x4216:return cpu->mmio_r4216(); //RDMPYL
|
||||
case 0x4217:return cpu->mmio_r4217(); //RDMPYH
|
||||
case 0x4218:return cpu->mmio_r4218(); //JOY1L
|
||||
case 0x4219:return cpu->mmio_r4219(); //JOY1H
|
||||
case 0x421a:return cpu->mmio_r421a(); //JOY2L
|
||||
case 0x421b:return cpu->mmio_r421b(); //JOY2H
|
||||
case 0x421c:case 0x421d:case 0x421e:case 0x421f:return 0x00;
|
||||
}
|
||||
|
||||
return cpu->regs.mdr;
|
||||
}
|
||||
|
||||
//WMDATA
|
||||
void bCPU::mmio_w2180(uint8 value) {
|
||||
mem_bus->write(0x7e0000 | status.wram_addr, value);
|
||||
status.wram_addr++;
|
||||
status.wram_addr &= 0x01ffff;
|
||||
}
|
||||
|
||||
//WMADDL
|
||||
void bCPU::mmio_w2181(uint8 value) {
|
||||
status.wram_addr = (status.wram_addr & 0xffff00) | value;
|
||||
status.wram_addr &= 0x01ffff;
|
||||
}
|
||||
|
||||
//WMADDM
|
||||
void bCPU::mmio_w2182(uint8 value) {
|
||||
status.wram_addr = (status.wram_addr & 0xff00ff) | (value << 8);
|
||||
status.wram_addr &= 0x01ffff;
|
||||
}
|
||||
|
||||
//WMADDH
|
||||
void bCPU::mmio_w2183(uint8 value) {
|
||||
status.wram_addr = (status.wram_addr & 0x00ffff) | (value << 16);
|
||||
status.wram_addr &= 0x01ffff;
|
||||
}
|
||||
|
||||
//JOYSER0
|
||||
void bCPU::mmio_w4016(uint8 value) {
|
||||
status.joypad1_strobe_value = !!(value & 1);
|
||||
if(value == 1) {
|
||||
snes->poll_input(SNES::DEV_JOYPAD1);
|
||||
status.joypad1_read_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//JOYSER1
|
||||
void bCPU::mmio_w4017(uint8 value) {
|
||||
status.joypad2_strobe_value = !!(value & 1);
|
||||
if(value == 1) {
|
||||
snes->poll_input(SNES::DEV_JOYPAD2);
|
||||
status.joypad2_read_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//NMITIMEN
|
||||
void bCPU::mmio_w4200(uint8 value) {
|
||||
status.nmi_enabled = !!(value & 0x80);
|
||||
status.virq_enabled = !!(value & 0x20);
|
||||
status.hirq_enabled = !!(value & 0x10);
|
||||
status.auto_joypad_poll = !!(value & 0x01);
|
||||
|
||||
if(time.nmi_read == 0) {
|
||||
if(time.nmi_line == 1 && !status.nmi_enabled == 0) {
|
||||
time.nmi_transition = 1;
|
||||
}
|
||||
time.nmi_line = !status.nmi_enabled;
|
||||
}
|
||||
|
||||
if(status.virq_enabled == false && status.hirq_enabled == false) {
|
||||
time.irq_line = 1;
|
||||
time.irq_read = 1;
|
||||
time.irq_transition = 0;
|
||||
}
|
||||
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
//WRIO
|
||||
void bCPU::mmio_w4201(uint8 value) {
|
||||
if((status.pio & 0x80) && !(value & 0x80)) {
|
||||
ppu->latch_counters();
|
||||
}
|
||||
status.pio = value;
|
||||
}
|
||||
|
||||
//WRMPYA
|
||||
void bCPU::mmio_w4202(uint8 value) {
|
||||
status.mul_a = value;
|
||||
}
|
||||
|
||||
void bCPU::mmio_w4203(uint8 value) {
|
||||
status.mul_b = value;
|
||||
status.r4216 = status.mul_a * status.mul_b;
|
||||
}
|
||||
|
||||
//WRDIVL
|
||||
void bCPU::mmio_w4204(uint8 value) {
|
||||
status.div_a = (status.div_a & 0xff00) | value;
|
||||
}
|
||||
|
||||
//WRDIVH
|
||||
void bCPU::mmio_w4205(uint8 value) {
|
||||
status.div_a = (status.div_a & 0x00ff) | (value << 8);
|
||||
}
|
||||
|
||||
//WRDIVB
|
||||
void bCPU::mmio_w4206(uint8 value) {
|
||||
status.div_b = value;
|
||||
status.r4214 = (status.div_b) ? status.div_a / status.div_b : 0xffff;
|
||||
status.r4216 = (status.div_b) ? status.div_a % status.div_b : status.div_a;
|
||||
}
|
||||
|
||||
//HTIMEL
|
||||
void bCPU::mmio_w4207(uint8 value) {
|
||||
status.hirq_pos = (status.hirq_pos & 0xff00) | value;
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
//HTIMEH
|
||||
void bCPU::mmio_w4208(uint8 value) {
|
||||
status.hirq_pos = (status.hirq_pos & 0x00ff) | (value << 8);
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
//VTIMEL
|
||||
void bCPU::mmio_w4209(uint8 value) {
|
||||
status.virq_pos = (status.virq_pos & 0xff00) | value;
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
//VTIMEH
|
||||
void bCPU::mmio_w420a(uint8 value) {
|
||||
status.virq_pos = (status.virq_pos & 0x00ff) | (value << 8);
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
//DMAEN
|
||||
void bCPU::mmio_w420b(uint8 value) {
|
||||
int len;
|
||||
if(value != 0x00) {
|
||||
run_state.dma = true;
|
||||
status.dma_state = DMASTATE_DMASYNC;
|
||||
}
|
||||
|
||||
for(int i=0;i<8;i++) {
|
||||
if(value & (1 << i)) {
|
||||
channel[i].active = true;
|
||||
channel[i].hdma_enabled = false;
|
||||
channel[i].hdma_active = false;
|
||||
channel[i].read_index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//HDMAEN
|
||||
void bCPU::mmio_w420c(uint8 value) {
|
||||
for(int i=0;i<8;i++) {
|
||||
channel[i].hdma_enabled = !!(value & (1 << i));
|
||||
channel[i].hdma_active = !!(value & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
//MEMSEL
|
||||
void bCPU::mmio_w420d(uint8 value) {
|
||||
mem_bus->set_speed(value & 1);
|
||||
}
|
||||
|
||||
//DMAPx
|
||||
void bCPU::mmio_w43x0(uint8 value, uint8 i) {
|
||||
channel[i].dmap = value;
|
||||
channel[i].direction = !!(value & 0x80);
|
||||
channel[i].hdma_indirect = !!(value & 0x40);
|
||||
channel[i].incmode = (value & 0x10)?-1:1;
|
||||
channel[i].fixedxfer = !!(value & 0x08);
|
||||
channel[i].xfermode = value & 7;
|
||||
}
|
||||
|
||||
//BBADx
|
||||
void bCPU::mmio_w43x1(uint8 value, uint8 i) {
|
||||
channel[i].destaddr = value;
|
||||
}
|
||||
|
||||
//A1TxL
|
||||
void bCPU::mmio_w43x2(uint8 value, uint8 i) {
|
||||
channel[i].srcaddr = (channel[i].srcaddr & 0xff00) | value;
|
||||
}
|
||||
|
||||
//A1TxH
|
||||
void bCPU::mmio_w43x3(uint8 value, uint8 i) {
|
||||
channel[i].srcaddr = (channel[i].srcaddr & 0x00ff) | (value << 8);
|
||||
}
|
||||
|
||||
//A1Bx
|
||||
void bCPU::mmio_w43x4(uint8 value, uint8 i) {
|
||||
channel[i].srcbank = value;
|
||||
}
|
||||
|
||||
//DASxL
|
||||
void bCPU::mmio_w43x5(uint8 value, uint8 i) {
|
||||
channel[i].xfersize = (channel[i].xfersize & 0xff00) | value;
|
||||
}
|
||||
|
||||
//DASxH
|
||||
void bCPU::mmio_w43x6(uint8 value, uint8 i) {
|
||||
channel[i].xfersize = (channel[i].xfersize & 0x00ff) | (value << 8);
|
||||
}
|
||||
|
||||
//DASBx
|
||||
void bCPU::mmio_w43x7(uint8 value, uint8 i) {
|
||||
channel[i].hdma_ibank = value;
|
||||
}
|
||||
|
||||
//A2AxL
|
||||
void bCPU::mmio_w43x8(uint8 value, uint8 i) {
|
||||
channel[i].hdma_addr = (channel[i].hdma_addr & 0xff00) | value;
|
||||
}
|
||||
|
||||
//A2AxH
|
||||
void bCPU::mmio_w43x9(uint8 value, uint8 i) {
|
||||
channel[i].hdma_addr = (channel[i].hdma_addr & 0x00ff) | (value << 8);
|
||||
}
|
||||
|
||||
//NTRLx
|
||||
void bCPU::mmio_w43xa(uint8 value, uint8 i) {
|
||||
channel[i].hdma_line_counter = value;
|
||||
}
|
||||
|
||||
//???
|
||||
void bCPU::mmio_w43xb(uint8 value, uint8 i) {
|
||||
channel[i].hdma_unknown = value;
|
||||
}
|
||||
|
||||
void bCPUMMIO::write(uint32 addr, uint8 value) {
|
||||
uint8 i;
|
||||
//APU
|
||||
if(addr >= 0x2140 && addr <= 0x217f) {
|
||||
cpu->port_write(addr & 3, value);
|
||||
return;
|
||||
}
|
||||
|
||||
//HDMA
|
||||
if(addr >= 0x4300 && addr <= 0x437f) {
|
||||
i = (addr >> 4) & 7;
|
||||
switch(addr & 0xf) {
|
||||
case 0x0:cpu->mmio_w43x0(value, i);return;
|
||||
case 0x1:cpu->mmio_w43x1(value, i);return;
|
||||
case 0x2:cpu->mmio_w43x2(value, i);return;
|
||||
case 0x3:cpu->mmio_w43x3(value, i);return;
|
||||
case 0x4:cpu->mmio_w43x4(value, i);return;
|
||||
case 0x5:cpu->mmio_w43x5(value, i);return;
|
||||
case 0x6:cpu->mmio_w43x6(value, i);return;
|
||||
case 0x7:cpu->mmio_w43x7(value, i);return;
|
||||
case 0x8:cpu->mmio_w43x8(value, i);return;
|
||||
case 0x9:cpu->mmio_w43x9(value, i);return;
|
||||
case 0xa:cpu->mmio_w43xa(value, i);return;
|
||||
case 0xb:cpu->mmio_w43xb(value, i);return;
|
||||
case 0xc:return; //unmapped
|
||||
case 0xd:return; //unmapped
|
||||
case 0xe:return; //unmapped
|
||||
case 0xf:cpu->mmio_w43xb(value, i);return; //mirror of 43xb
|
||||
}
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
case 0x2180:cpu->mmio_w2180(value);return; //WMDATA
|
||||
case 0x2181:cpu->mmio_w2181(value);return; //WMADDL
|
||||
case 0x2182:cpu->mmio_w2182(value);return; //WMADDM
|
||||
case 0x2183:cpu->mmio_w2183(value);return; //WMADDH
|
||||
case 0x4016:cpu->mmio_w4016(value);return; //JOYSER0
|
||||
case 0x4017:cpu->mmio_w4017(value);return; //JOYSER1
|
||||
case 0x4200:cpu->mmio_w4200(value);return; //NMITIMEN
|
||||
case 0x4201:cpu->mmio_w4201(value);return; //WRIO
|
||||
case 0x4202:cpu->mmio_w4202(value);return; //WRMPYA
|
||||
case 0x4203:cpu->mmio_w4203(value);return; //WRMPYB
|
||||
case 0x4204:cpu->mmio_w4204(value);return; //WRDIVL
|
||||
case 0x4205:cpu->mmio_w4205(value);return; //WRDIVH
|
||||
case 0x4206:cpu->mmio_w4206(value);return; //WRDIVB
|
||||
case 0x4207:cpu->mmio_w4207(value);return; //HTIMEL
|
||||
case 0x4208:cpu->mmio_w4208(value);return; //HTIMEH
|
||||
case 0x4209:cpu->mmio_w4209(value);return; //VTIMEL
|
||||
case 0x420a:cpu->mmio_w420a(value);return; //VTIMEH
|
||||
case 0x420b:cpu->mmio_w420b(value);return; //DMAEN
|
||||
case 0x420c:cpu->mmio_w420c(value);return; //HDMAEN
|
||||
case 0x420d:cpu->mmio_w420d(value);return; //MEMSEL
|
||||
}
|
||||
}
|
||||
|
||||
bCPUMMIO::bCPUMMIO(bCPU *_cpu) {
|
||||
cpu = _cpu;
|
||||
}
|
||||
@@ -1,256 +0,0 @@
|
||||
void op_adc_const();
|
||||
void op_and_const();
|
||||
void op_cmp_const();
|
||||
void op_cpx_const();
|
||||
void op_cpy_const();
|
||||
void op_eor_const();
|
||||
void op_lda_const();
|
||||
void op_ldx_const();
|
||||
void op_ldy_const();
|
||||
void op_ora_const();
|
||||
void op_sbc_const();
|
||||
void op_adc_addr();
|
||||
void op_and_addr();
|
||||
void op_bit_addr();
|
||||
void op_cmp_addr();
|
||||
void op_cpx_addr();
|
||||
void op_cpy_addr();
|
||||
void op_eor_addr();
|
||||
void op_lda_addr();
|
||||
void op_ldx_addr();
|
||||
void op_ldy_addr();
|
||||
void op_ora_addr();
|
||||
void op_sbc_addr();
|
||||
void op_adc_addrx();
|
||||
void op_and_addrx();
|
||||
void op_bit_addrx();
|
||||
void op_cmp_addrx();
|
||||
void op_eor_addrx();
|
||||
void op_lda_addrx();
|
||||
void op_ldy_addrx();
|
||||
void op_ora_addrx();
|
||||
void op_sbc_addrx();
|
||||
void op_adc_addry();
|
||||
void op_and_addry();
|
||||
void op_cmp_addry();
|
||||
void op_eor_addry();
|
||||
void op_lda_addry();
|
||||
void op_ldx_addry();
|
||||
void op_ora_addry();
|
||||
void op_sbc_addry();
|
||||
void op_adc_long();
|
||||
void op_and_long();
|
||||
void op_cmp_long();
|
||||
void op_eor_long();
|
||||
void op_lda_long();
|
||||
void op_ora_long();
|
||||
void op_sbc_long();
|
||||
void op_adc_longx();
|
||||
void op_and_longx();
|
||||
void op_cmp_longx();
|
||||
void op_eor_longx();
|
||||
void op_lda_longx();
|
||||
void op_ora_longx();
|
||||
void op_sbc_longx();
|
||||
void op_adc_dp();
|
||||
void op_and_dp();
|
||||
void op_bit_dp();
|
||||
void op_cmp_dp();
|
||||
void op_cpx_dp();
|
||||
void op_cpy_dp();
|
||||
void op_eor_dp();
|
||||
void op_lda_dp();
|
||||
void op_ldx_dp();
|
||||
void op_ldy_dp();
|
||||
void op_ora_dp();
|
||||
void op_sbc_dp();
|
||||
void op_adc_dpx();
|
||||
void op_and_dpx();
|
||||
void op_bit_dpx();
|
||||
void op_cmp_dpx();
|
||||
void op_eor_dpx();
|
||||
void op_lda_dpx();
|
||||
void op_ldy_dpx();
|
||||
void op_ora_dpx();
|
||||
void op_sbc_dpx();
|
||||
void op_ldx_dpy();
|
||||
void op_adc_idp();
|
||||
void op_and_idp();
|
||||
void op_cmp_idp();
|
||||
void op_eor_idp();
|
||||
void op_lda_idp();
|
||||
void op_ora_idp();
|
||||
void op_sbc_idp();
|
||||
void op_adc_idpx();
|
||||
void op_and_idpx();
|
||||
void op_cmp_idpx();
|
||||
void op_eor_idpx();
|
||||
void op_lda_idpx();
|
||||
void op_ora_idpx();
|
||||
void op_sbc_idpx();
|
||||
void op_adc_idpy();
|
||||
void op_and_idpy();
|
||||
void op_cmp_idpy();
|
||||
void op_eor_idpy();
|
||||
void op_lda_idpy();
|
||||
void op_ora_idpy();
|
||||
void op_sbc_idpy();
|
||||
void op_adc_ildp();
|
||||
void op_and_ildp();
|
||||
void op_cmp_ildp();
|
||||
void op_eor_ildp();
|
||||
void op_lda_ildp();
|
||||
void op_ora_ildp();
|
||||
void op_sbc_ildp();
|
||||
void op_adc_ildpy();
|
||||
void op_and_ildpy();
|
||||
void op_cmp_ildpy();
|
||||
void op_eor_ildpy();
|
||||
void op_lda_ildpy();
|
||||
void op_ora_ildpy();
|
||||
void op_sbc_ildpy();
|
||||
void op_adc_sr();
|
||||
void op_and_sr();
|
||||
void op_cmp_sr();
|
||||
void op_eor_sr();
|
||||
void op_lda_sr();
|
||||
void op_ora_sr();
|
||||
void op_sbc_sr();
|
||||
void op_adc_isry();
|
||||
void op_and_isry();
|
||||
void op_cmp_isry();
|
||||
void op_eor_isry();
|
||||
void op_lda_isry();
|
||||
void op_ora_isry();
|
||||
void op_sbc_isry();
|
||||
void op_bit_const();
|
||||
void op_inc();
|
||||
void op_inx();
|
||||
void op_iny();
|
||||
void op_dec();
|
||||
void op_dex();
|
||||
void op_dey();
|
||||
void op_asl();
|
||||
void op_lsr();
|
||||
void op_rol();
|
||||
void op_ror();
|
||||
void op_inc_addr();
|
||||
void op_dec_addr();
|
||||
void op_asl_addr();
|
||||
void op_lsr_addr();
|
||||
void op_rol_addr();
|
||||
void op_ror_addr();
|
||||
void op_trb_addr();
|
||||
void op_tsb_addr();
|
||||
void op_inc_addrx();
|
||||
void op_dec_addrx();
|
||||
void op_asl_addrx();
|
||||
void op_lsr_addrx();
|
||||
void op_rol_addrx();
|
||||
void op_ror_addrx();
|
||||
void op_inc_dp();
|
||||
void op_dec_dp();
|
||||
void op_asl_dp();
|
||||
void op_lsr_dp();
|
||||
void op_rol_dp();
|
||||
void op_ror_dp();
|
||||
void op_trb_dp();
|
||||
void op_tsb_dp();
|
||||
void op_inc_dpx();
|
||||
void op_dec_dpx();
|
||||
void op_asl_dpx();
|
||||
void op_lsr_dpx();
|
||||
void op_rol_dpx();
|
||||
void op_ror_dpx();
|
||||
void op_sta_addr();
|
||||
void op_stx_addr();
|
||||
void op_sty_addr();
|
||||
void op_stz_addr();
|
||||
void op_sta_addrx();
|
||||
void op_stz_addrx();
|
||||
void op_sta_addry();
|
||||
void op_sta_long();
|
||||
void op_sta_longx();
|
||||
void op_sta_dp();
|
||||
void op_stx_dp();
|
||||
void op_sty_dp();
|
||||
void op_stz_dp();
|
||||
void op_sta_dpx();
|
||||
void op_sty_dpx();
|
||||
void op_stz_dpx();
|
||||
void op_stx_dpy();
|
||||
void op_sta_idp();
|
||||
void op_sta_ildp();
|
||||
void op_sta_idpx();
|
||||
void op_sta_idpy();
|
||||
void op_sta_ildpy();
|
||||
void op_sta_sr();
|
||||
void op_sta_isry();
|
||||
void op_bcc();
|
||||
void op_bcs();
|
||||
void op_bne();
|
||||
void op_beq();
|
||||
void op_bpl();
|
||||
void op_bmi();
|
||||
void op_bvc();
|
||||
void op_bvs();
|
||||
void op_bra();
|
||||
void op_brl();
|
||||
void op_jmp_addr();
|
||||
void op_jmp_long();
|
||||
void op_jmp_iaddr();
|
||||
void op_jmp_iaddrx();
|
||||
void op_jmp_iladdr();
|
||||
void op_jsr_addr();
|
||||
void op_jsr_long();
|
||||
void op_jsr_iaddrx();
|
||||
void op_rti();
|
||||
void op_rts();
|
||||
void op_rtl();
|
||||
void op_nop();
|
||||
void op_wdm();
|
||||
void op_xba();
|
||||
void op_mvn();
|
||||
void op_mvp();
|
||||
void op_brk();
|
||||
void op_cop();
|
||||
void op_stp();
|
||||
void op_wai();
|
||||
void op_xce();
|
||||
void op_clc();
|
||||
void op_cld();
|
||||
void op_cli();
|
||||
void op_clv();
|
||||
void op_sec();
|
||||
void op_sed();
|
||||
void op_sei();
|
||||
void op_rep();
|
||||
void op_sep();
|
||||
void op_tax();
|
||||
void op_tay();
|
||||
void op_txa();
|
||||
void op_txy();
|
||||
void op_tya();
|
||||
void op_tyx();
|
||||
void op_tcd();
|
||||
void op_tcs();
|
||||
void op_tdc();
|
||||
void op_tsc();
|
||||
void op_tsx();
|
||||
void op_txs();
|
||||
void op_pha();
|
||||
void op_phx();
|
||||
void op_phy();
|
||||
void op_phd();
|
||||
void op_phb();
|
||||
void op_phk();
|
||||
void op_php();
|
||||
void op_pla();
|
||||
void op_plx();
|
||||
void op_ply();
|
||||
void op_pld();
|
||||
void op_plb();
|
||||
void op_plp();
|
||||
void op_pea();
|
||||
void op_pei();
|
||||
void op_per();
|
||||
@@ -1,858 +0,0 @@
|
||||
void bCPU::op_nop() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_wdm() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
op_read();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_xba() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
break;
|
||||
case 2:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.a.h ^= regs.a.l;
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_mvn() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 3:
|
||||
regs.db = dp;
|
||||
rd.l = op_read(OPMODE_LONG, (sp << 16) | regs.x.w);
|
||||
break;
|
||||
case 4:
|
||||
op_write(OPMODE_LONG, (dp << 16) | regs.y.w, rd.l);
|
||||
break;
|
||||
case 5:
|
||||
cpu_io();
|
||||
if(regs.p.x) { regs.x.l++; regs.y.l++; }
|
||||
else { regs.x.w++; regs.y.w++; }
|
||||
break;
|
||||
case 6:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.a.w--)regs.pc.w -= 3;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_mvp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 3:
|
||||
regs.db = dp;
|
||||
rd.l = op_read(OPMODE_LONG, (sp << 16) | regs.x.w);
|
||||
break;
|
||||
case 4:
|
||||
op_write(OPMODE_LONG, (dp << 16) | regs.y.w, rd.l);
|
||||
break;
|
||||
case 5:
|
||||
cpu_io();
|
||||
if(regs.p.x) { regs.x.l--; regs.y.l--; }
|
||||
else { regs.x.w--; regs.y.w--; }
|
||||
break;
|
||||
case 6:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.a.w--)regs.pc.w -= 3;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_brk() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
op_read();
|
||||
if(regs.e)status.cycle_pos++;
|
||||
break;
|
||||
case 2:
|
||||
stack_write(regs.pc.b);
|
||||
break;
|
||||
case 3:
|
||||
stack_write(regs.pc.h);
|
||||
break;
|
||||
case 4:
|
||||
stack_write(regs.pc.l);
|
||||
break;
|
||||
case 5:
|
||||
stack_write(regs.p);
|
||||
break;
|
||||
case 6:
|
||||
rd.l = op_read(OPMODE_LONG, (regs.e)?0xfffe:0xffe6);
|
||||
break;
|
||||
case 7:
|
||||
last_cycle();
|
||||
rd.h = op_read(OPMODE_LONG, (regs.e)?0xffff:0xffe7);
|
||||
regs.pc.b = 0x00;
|
||||
regs.pc.w = rd.w;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_cop() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
op_read();
|
||||
if(regs.e)status.cycle_pos++;
|
||||
break;
|
||||
case 2:
|
||||
stack_write(regs.pc.b);
|
||||
break;
|
||||
case 3:
|
||||
stack_write(regs.pc.h);
|
||||
break;
|
||||
case 4:
|
||||
stack_write(regs.pc.l);
|
||||
break;
|
||||
case 5:
|
||||
stack_write(regs.p);
|
||||
break;
|
||||
case 6:
|
||||
rd.l = op_read(OPMODE_LONG, (regs.e)?0xfff4:0xffe4);
|
||||
break;
|
||||
case 7:
|
||||
last_cycle();
|
||||
rd.h = op_read(OPMODE_LONG, (regs.e)?0xfff5:0xffe5);
|
||||
regs.pc.b = 0x00;
|
||||
regs.pc.w = rd.w;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
run_state.stp = true;
|
||||
break;
|
||||
case 2:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.pc.w--;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_wai() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
run_state.wai = true;
|
||||
break;
|
||||
case 2:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(run_state.wai) {
|
||||
//this can be cleared within last_cycle()
|
||||
regs.pc.w--;
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_xce() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
bool c = regs.p.c;
|
||||
regs.p.c = regs.e;
|
||||
regs.e = c;
|
||||
if(regs.e) {
|
||||
regs.p |= 0x30;
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_clc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.p.c = 0;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_cld() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.p.d = 0;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_cli() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.p.i = 0;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_clv() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.p.v = 0;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sec() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.p.c = 1;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sed() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.p.d = 1;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sei() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.p.i = 1;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_rep() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
rd.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.p &=~ rd.l;
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sep() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
rd.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.p |= rd.l;
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_tax() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.a.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.a.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_tay() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.p.x) {
|
||||
regs.y.l = regs.a.l;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w = regs.a.w;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_txa() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.p.m) {
|
||||
regs.a.l = regs.x.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w = regs.x.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_txy() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.p.x) {
|
||||
regs.y.l = regs.x.l;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w = regs.x.w;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_tya() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.p.m) {
|
||||
regs.a.l = regs.y.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w = regs.y.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_tyx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.y.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.y.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_tcd() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.d.w = regs.a.w;
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_tcs() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.s.w = regs.a.w;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_tdc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.a.w = regs.d.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_tsc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.a.w = regs.s.w;
|
||||
if(regs.e) {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_tsx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.s.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.s.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_txs() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.e) {
|
||||
regs.s.l = regs.x.l;
|
||||
regs.p.n = !!(regs.s.l & 0x80);
|
||||
regs.p.z = (regs.s.l == 0);
|
||||
} else {
|
||||
regs.s.w = regs.x.w;
|
||||
regs.p.n = !!(regs.s.w & 0x8000);
|
||||
regs.p.z = (regs.s.w == 0);
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_pha() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
if(regs.p.m)status.cycle_pos++;
|
||||
break;
|
||||
case 2:
|
||||
stack_write(regs.a.h);
|
||||
break;
|
||||
case 3:
|
||||
last_cycle();
|
||||
stack_write(regs.a.l);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_phx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
if(regs.p.x)status.cycle_pos++;
|
||||
break;
|
||||
case 2:
|
||||
stack_write(regs.x.h);
|
||||
break;
|
||||
case 3:
|
||||
last_cycle();
|
||||
stack_write(regs.x.l);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_phy() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
if(regs.p.x)status.cycle_pos++;
|
||||
break;
|
||||
case 2:
|
||||
stack_write(regs.y.h);
|
||||
break;
|
||||
case 3:
|
||||
last_cycle();
|
||||
stack_write(regs.y.l);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_phd() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
if(0)status.cycle_pos++;
|
||||
break;
|
||||
case 2:
|
||||
stack_write(regs. d.h);
|
||||
break;
|
||||
case 3:
|
||||
last_cycle();
|
||||
stack_write(regs. d.l);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_phb() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
break;
|
||||
case 2:
|
||||
last_cycle();
|
||||
stack_write(regs.db);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_phk() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
break;
|
||||
case 2:
|
||||
last_cycle();
|
||||
stack_write(regs.pc.b);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_php() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
break;
|
||||
case 2:
|
||||
last_cycle();
|
||||
stack_write(regs.p);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_pla() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
break;
|
||||
case 2:
|
||||
cpu_io();
|
||||
break;
|
||||
case 3:
|
||||
if(regs.p.m)last_cycle();
|
||||
regs.a.l = stack_read();
|
||||
if(regs.p.m) {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
last_cycle();
|
||||
regs.a.h = stack_read();
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_plx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
break;
|
||||
case 2:
|
||||
cpu_io();
|
||||
break;
|
||||
case 3:
|
||||
if(regs.p.x)last_cycle();
|
||||
regs.x.l = stack_read();
|
||||
if(regs.p.x) {
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
last_cycle();
|
||||
regs.x.h = stack_read();
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_ply() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
break;
|
||||
case 2:
|
||||
cpu_io();
|
||||
break;
|
||||
case 3:
|
||||
if(regs.p.x)last_cycle();
|
||||
regs.y.l = stack_read();
|
||||
if(regs.p.x) {
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
last_cycle();
|
||||
regs.y.h = stack_read();
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_pld() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
break;
|
||||
case 2:
|
||||
cpu_io();
|
||||
break;
|
||||
case 3:
|
||||
if(0)last_cycle();
|
||||
regs. d.l = stack_read();
|
||||
if(0) {
|
||||
regs.p.n = !!(regs. d.l & 0x80);
|
||||
regs.p.z = (regs. d.l == 0);
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
last_cycle();
|
||||
regs. d.h = stack_read();
|
||||
regs.p.n = !!(regs. d.w & 0x8000);
|
||||
regs.p.z = (regs. d.w == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_plb() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
break;
|
||||
case 2:
|
||||
cpu_io();
|
||||
break;
|
||||
case 3:
|
||||
last_cycle();
|
||||
regs.db = stack_read();
|
||||
regs.p.n = !!(regs.db & 0x80);
|
||||
regs.p.z = (regs.db == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_plp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
break;
|
||||
case 2:
|
||||
cpu_io();
|
||||
break;
|
||||
case 3:
|
||||
last_cycle();
|
||||
regs.p = stack_read();
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_pea() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
stack_write(aa.h);
|
||||
break;
|
||||
case 4:
|
||||
last_cycle();
|
||||
stack_write(aa.l);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_pei() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
aa.l = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 4:
|
||||
aa.h = op_read(OPMODE_DP, dp + 1);
|
||||
break;
|
||||
case 5:
|
||||
stack_write(aa.h);
|
||||
break;
|
||||
case 6:
|
||||
last_cycle();
|
||||
stack_write(aa.l);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_per() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
cpu_io();
|
||||
rd.w = regs.pc.d + (int16)aa.w;
|
||||
break;
|
||||
case 4:
|
||||
stack_write(rd.h);
|
||||
break;
|
||||
case 5:
|
||||
last_cycle();
|
||||
stack_write(rd.l);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,482 +0,0 @@
|
||||
void bCPU::op_bcc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
if(!!regs.p.c)last_cycle();
|
||||
rd.l = op_read();
|
||||
if(!regs.p.c) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
cpu_c6(aa.w);
|
||||
break;
|
||||
case 3:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bcs() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
if(!regs.p.c)last_cycle();
|
||||
rd.l = op_read();
|
||||
if(regs.p.c) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
cpu_c6(aa.w);
|
||||
break;
|
||||
case 3:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bne() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
if(!!regs.p.z)last_cycle();
|
||||
rd.l = op_read();
|
||||
if(!regs.p.z) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
cpu_c6(aa.w);
|
||||
break;
|
||||
case 3:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_beq() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
if(!regs.p.z)last_cycle();
|
||||
rd.l = op_read();
|
||||
if(regs.p.z) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
cpu_c6(aa.w);
|
||||
break;
|
||||
case 3:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bpl() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
if(!!regs.p.n)last_cycle();
|
||||
rd.l = op_read();
|
||||
if(!regs.p.n) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
cpu_c6(aa.w);
|
||||
break;
|
||||
case 3:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bmi() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
if(!regs.p.n)last_cycle();
|
||||
rd.l = op_read();
|
||||
if(regs.p.n) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
cpu_c6(aa.w);
|
||||
break;
|
||||
case 3:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bvc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
if(!!regs.p.v)last_cycle();
|
||||
rd.l = op_read();
|
||||
if(!regs.p.v) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
cpu_c6(aa.w);
|
||||
break;
|
||||
case 3:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bvs() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
if(!regs.p.v)last_cycle();
|
||||
rd.l = op_read();
|
||||
if(regs.p.v) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
cpu_c6(aa.w);
|
||||
break;
|
||||
case 3:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bra() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
rd.l = op_read();
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
break;
|
||||
case 2:
|
||||
cpu_c6(aa.w);
|
||||
break;
|
||||
case 3:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_brl() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
rd.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.pc.w = regs.pc.d + (int16)rd.w;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jmp_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
rd.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
last_cycle();
|
||||
rd.h = op_read();
|
||||
regs.pc.w = rd.w;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jmp_long() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
rd.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
rd.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
last_cycle();
|
||||
rd.b = op_read();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jmp_iaddr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
rd.l = op_read(OPMODE_ADDR, aa.w);
|
||||
break;
|
||||
case 4:
|
||||
last_cycle();
|
||||
rd.h = op_read(OPMODE_ADDR, aa.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jmp_iaddrx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
cpu_io();
|
||||
break;
|
||||
case 4:
|
||||
rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w);
|
||||
break;
|
||||
case 5:
|
||||
last_cycle();
|
||||
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jmp_iladdr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
rd.l = op_read(OPMODE_ADDR, aa.w);
|
||||
break;
|
||||
case 4:
|
||||
rd.h = op_read(OPMODE_ADDR, aa.w + 1);
|
||||
break;
|
||||
case 5:
|
||||
last_cycle();
|
||||
rd.b = op_read(OPMODE_ADDR, aa.w + 2);
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jsr_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
cpu_io();
|
||||
break;
|
||||
case 4:
|
||||
regs.pc.w--;
|
||||
stack_write(regs.pc.h);
|
||||
break;
|
||||
case 5:
|
||||
last_cycle();
|
||||
stack_write(regs.pc.l);
|
||||
regs.pc.w = aa.w;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jsr_long() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
stack_write(regs.pc.b);
|
||||
break;
|
||||
case 4:
|
||||
cpu_io();
|
||||
break;
|
||||
case 5:
|
||||
aa.b = op_read();
|
||||
break;
|
||||
case 6:
|
||||
regs.pc.w--;
|
||||
stack_write(regs.pc.h);
|
||||
break;
|
||||
case 7:
|
||||
last_cycle();
|
||||
stack_write(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jsr_iaddrx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
stack_write(regs.pc.h);
|
||||
break;
|
||||
case 3:
|
||||
stack_write(regs.pc.l);
|
||||
break;
|
||||
case 4:
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 5:
|
||||
cpu_io();
|
||||
break;
|
||||
case 6:
|
||||
rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w);
|
||||
break;
|
||||
case 7:
|
||||
last_cycle();
|
||||
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_rti() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
break;
|
||||
case 2:
|
||||
cpu_io();
|
||||
break;
|
||||
case 3:
|
||||
regs.p = stack_read();
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
rd.l = stack_read();
|
||||
break;
|
||||
case 5:
|
||||
rd.h = stack_read();
|
||||
if(regs.e) {
|
||||
regs.pc.w = rd.w;
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
last_cycle();
|
||||
rd.b = stack_read();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_rts() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
break;
|
||||
case 2:
|
||||
cpu_io();
|
||||
break;
|
||||
case 3:
|
||||
rd.l = stack_read();
|
||||
break;
|
||||
case 4:
|
||||
rd.h = stack_read();
|
||||
break;
|
||||
case 5:
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.pc.w = rd.w;
|
||||
regs.pc.w++;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_rtl() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
cpu_io();
|
||||
break;
|
||||
case 2:
|
||||
cpu_io();
|
||||
break;
|
||||
case 3:
|
||||
rd.l = stack_read();
|
||||
break;
|
||||
case 4:
|
||||
rd.h = stack_read();
|
||||
break;
|
||||
case 5:
|
||||
last_cycle();
|
||||
rd.b = stack_read();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
regs.pc.w++;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,582 +0,0 @@
|
||||
void bCPU::op_sta_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w, regs.a.w);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 4:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + 1, regs.a.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stx_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
if(regs.p.x)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w, regs.x.w);
|
||||
if(regs.p.x)status.cycle_pos = 0;
|
||||
break;
|
||||
case 4:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + 1, regs.x.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sty_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
if(regs.p.x)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w, regs.y.w);
|
||||
if(regs.p.x)status.cycle_pos = 0;
|
||||
break;
|
||||
case 4:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + 1, regs.y.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stz_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w, 0x0000);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 4:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + 1, 0x0000 >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_addrx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
cpu_c4(aa.w, aa.w + regs.x.w);
|
||||
break;
|
||||
case 4:
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w, regs.a.w);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 5:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, regs.a.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stz_addrx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
cpu_c4(aa.w, aa.w + regs.x.w);
|
||||
break;
|
||||
case 4:
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w, 0x0000);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 5:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, 0x0000 >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_addry() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
cpu_c4(aa.w, aa.w + regs.y.w);
|
||||
break;
|
||||
case 4:
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 5:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_long() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
aa.b = op_read();
|
||||
break;
|
||||
case 4:
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_LONG, aa.d, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 5:
|
||||
last_cycle();
|
||||
op_write(OPMODE_LONG, aa.d + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_longx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
aa.b = op_read();
|
||||
break;
|
||||
case 4:
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_LONG, aa.d + regs.x.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 5:
|
||||
last_cycle();
|
||||
op_write(OPMODE_LONG, aa.d + regs.x.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DP, dp, regs.a.w);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 4:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DP, dp + 1, regs.a.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stx_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
if(regs.p.x)last_cycle();
|
||||
op_write(OPMODE_DP, dp, regs.x.w);
|
||||
if(regs.p.x)status.cycle_pos = 0;
|
||||
break;
|
||||
case 4:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DP, dp + 1, regs.x.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sty_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
if(regs.p.x)last_cycle();
|
||||
op_write(OPMODE_DP, dp, regs.y.w);
|
||||
if(regs.p.x)status.cycle_pos = 0;
|
||||
break;
|
||||
case 4:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DP, dp + 1, regs.y.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stz_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DP, dp, 0x0000);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 4:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DP, dp + 1, 0x0000 >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
cpu_io();
|
||||
break;
|
||||
case 4:
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DP, dp + regs.x.w, regs.a.w);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 5:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DP, dp + regs.x.w + 1, regs.a.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sty_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
cpu_io();
|
||||
break;
|
||||
case 4:
|
||||
if(regs.p.x)last_cycle();
|
||||
op_write(OPMODE_DP, dp + regs.x.w, regs.y.w);
|
||||
if(regs.p.x)status.cycle_pos = 0;
|
||||
break;
|
||||
case 5:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DP, dp + regs.x.w + 1, regs.y.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stz_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
cpu_io();
|
||||
break;
|
||||
case 4:
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DP, dp + regs.x.w, 0x0000);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 5:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DP, dp + regs.x.w + 1, 0x0000 >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stx_dpy() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
cpu_io();
|
||||
break;
|
||||
case 4:
|
||||
if(regs.p.x)last_cycle();
|
||||
op_write(OPMODE_DP, dp + regs.y.w, regs.x.l);
|
||||
if(regs.p.x)status.cycle_pos = 0;
|
||||
break;
|
||||
case 5:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DP, dp + regs.y.w + 1, regs.x.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_idp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
aa.l = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 4:
|
||||
aa.h = op_read(OPMODE_DP, dp + 1);
|
||||
break;
|
||||
case 5:
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 6:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_ildp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
aa.l = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 4:
|
||||
aa.h = op_read(OPMODE_DP, dp + 1);
|
||||
break;
|
||||
case 5:
|
||||
aa.b = op_read(OPMODE_DP, dp + 2);
|
||||
break;
|
||||
case 6:
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_LONG, aa.d, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 7:
|
||||
last_cycle();
|
||||
op_write(OPMODE_LONG, aa.d + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_idpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
cpu_io();
|
||||
break;
|
||||
case 4:
|
||||
aa.l = op_read(OPMODE_DP, dp + regs.x.w);
|
||||
break;
|
||||
case 5:
|
||||
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
|
||||
break;
|
||||
case 6:
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 7:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_idpy() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
aa.l = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 4:
|
||||
aa.h = op_read(OPMODE_DP, dp + 1);
|
||||
break;
|
||||
case 5:
|
||||
cpu_c4(aa.w, aa.w + regs.y.w);
|
||||
break;
|
||||
case 6:
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 7:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_ildpy() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
aa.l = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 4:
|
||||
aa.h = op_read(OPMODE_DP, dp + 1);
|
||||
break;
|
||||
case 5:
|
||||
aa.b = op_read(OPMODE_DP, dp + 2);
|
||||
break;
|
||||
case 6:
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_LONG, aa.d + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 7:
|
||||
last_cycle();
|
||||
op_write(OPMODE_LONG, aa.d + regs.y.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_sr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
cpu_io();
|
||||
break;
|
||||
case 3:
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_SP, sp, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 4:
|
||||
last_cycle();
|
||||
op_write(OPMODE_SP, sp + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_isry() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
cpu_io();
|
||||
break;
|
||||
case 3:
|
||||
aa.l = op_read(OPMODE_SP, sp);
|
||||
break;
|
||||
case 4:
|
||||
aa.h = op_read(OPMODE_SP, sp + 1);
|
||||
break;
|
||||
case 5:
|
||||
cpu_io();
|
||||
break;
|
||||
case 6:
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 7:
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,295 +0,0 @@
|
||||
//op_read
|
||||
inline void bCPU::op_adc_b() {
|
||||
int32 r = regs.a.l + rd.l + regs.p.c;
|
||||
//bcd
|
||||
if(regs.p.d) {
|
||||
if(((r ) & 15) > 9)r += 6;
|
||||
if(((r >> 4) & 15) > 9)r += 6 << 4;
|
||||
}
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.v = !!(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r > 0xff);
|
||||
regs.a.l = r;
|
||||
}
|
||||
|
||||
inline void bCPU::op_adc_w() {
|
||||
int32 r = regs.a.w + rd.w + regs.p.c;
|
||||
//bcd
|
||||
if(regs.p.d) {
|
||||
if(((r ) & 15) > 9)r += 6;
|
||||
if(((r >> 4) & 15) > 9)r += 6 << 4;
|
||||
if(((r >> 8) & 15) > 9)r += 6 << 8;
|
||||
if(((r >> 12) & 15) > 9)r += 6 << 12;
|
||||
}
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.v = !!(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r > 0xffff);
|
||||
regs.a.w = r;
|
||||
}
|
||||
|
||||
inline void bCPU::op_and_b() {
|
||||
regs.a.l &= rd.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_and_w() {
|
||||
regs.a.w &= rd.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_bit_b() {
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.v = !!(rd.l & 0x40);
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_bit_w() {
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.v = !!(rd.w & 0x4000);
|
||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_cmp_b() {
|
||||
int32 r = regs.a.l - rd.l;
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_cmp_w() {
|
||||
int32 r = regs.a.w - rd.w;
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_cpx_b() {
|
||||
int32 r = regs.x.l - rd.l;
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_cpx_w() {
|
||||
int32 r = regs.x.w - rd.w;
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_cpy_b() {
|
||||
int32 r = regs.y.l - rd.l;
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_cpy_w() {
|
||||
int32 r = regs.y.w - rd.w;
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_eor_b() {
|
||||
regs.a.l ^= rd.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_eor_w() {
|
||||
regs.a.w ^= rd.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_lda_b() {
|
||||
regs.a.l = rd.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_lda_w() {
|
||||
regs.a.w = rd.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_ldx_b() {
|
||||
regs.x.l = rd.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_ldx_w() {
|
||||
regs.x.w = rd.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_ldy_b() {
|
||||
regs.y.l = rd.l;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_ldy_w() {
|
||||
regs.y.w = rd.w;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_ora_b() {
|
||||
regs.a.l |= rd.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_ora_w() {
|
||||
regs.a.w |= rd.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_sbc_b() {
|
||||
int32 r = regs.a.l - rd.l - !regs.p.c;
|
||||
//bcd
|
||||
if(regs.p.d) {
|
||||
if(((r ) & 15) > 9)r -= 6;
|
||||
if(((r >> 4) & 15) > 9)r -= 6 << 4;
|
||||
}
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.v = !!((regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
|
||||
regs.p.z = ((byte)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
regs.a.l = r;
|
||||
}
|
||||
|
||||
inline void bCPU::op_sbc_w() {
|
||||
int32 r = regs.a.w - rd.w - !regs.p.c;
|
||||
//bcd
|
||||
if(regs.p.d) {
|
||||
if(((r ) & 15) > 9)r -= 6;
|
||||
if(((r >> 4) & 15) > 9)r -= 6 << 4;
|
||||
if(((r >> 8) & 15) > 9)r -= 6 << 8;
|
||||
if(((r >> 12) & 15) > 9)r -= 6 << 12;
|
||||
}
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.v = !!((regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
|
||||
regs.p.z = ((word)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
regs.a.w = r;
|
||||
}
|
||||
|
||||
//op_rmw
|
||||
inline void bCPU::op_inc_b() {
|
||||
rd.l++;
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_inc_w() {
|
||||
rd.w++;
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_dec_b() {
|
||||
rd.l--;
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_dec_w() {
|
||||
rd.w--;
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_asl_b() {
|
||||
regs.p.c = !!(rd.l & 0x80);
|
||||
rd.l <<= 1;
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_asl_w() {
|
||||
regs.p.c = !!(rd.w & 0x8000);
|
||||
rd.w <<= 1;
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_lsr_b() {
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_lsr_w() {
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_rol_b() {
|
||||
uint16 c = regs.p.c;
|
||||
regs.p.c = !!(rd.l & 0x80);
|
||||
rd.l <<= 1;
|
||||
rd.l |= c;
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_rol_w() {
|
||||
uint16 c = regs.p.c;
|
||||
regs.p.c = !!(rd.w & 0x8000);
|
||||
rd.w <<= 1;
|
||||
rd.w |= c;
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_ror_b() {
|
||||
uint16 c = (regs.p.c)?0x80:0;
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
rd.l |= c;
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_ror_w() {
|
||||
uint16 c = (regs.p.c)?0x8000:0;
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
rd.w |= c;
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_trb_b() {
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
rd.l &= ~regs.a.l;
|
||||
}
|
||||
|
||||
inline void bCPU::op_trb_w() {
|
||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
||||
rd.w &= ~regs.a.w;
|
||||
}
|
||||
|
||||
inline void bCPU::op_tsb_b() {
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
rd.l |= regs.a.l;
|
||||
}
|
||||
|
||||
inline void bCPU::op_tsb_w() {
|
||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
||||
rd.w |= regs.a.w;
|
||||
}
|
||||
@@ -1,256 +0,0 @@
|
||||
optbl[0x69] = &bCPU::op_adc_const;
|
||||
optbl[0x29] = &bCPU::op_and_const;
|
||||
optbl[0xc9] = &bCPU::op_cmp_const;
|
||||
optbl[0xe0] = &bCPU::op_cpx_const;
|
||||
optbl[0xc0] = &bCPU::op_cpy_const;
|
||||
optbl[0x49] = &bCPU::op_eor_const;
|
||||
optbl[0xa9] = &bCPU::op_lda_const;
|
||||
optbl[0xa2] = &bCPU::op_ldx_const;
|
||||
optbl[0xa0] = &bCPU::op_ldy_const;
|
||||
optbl[0x09] = &bCPU::op_ora_const;
|
||||
optbl[0xe9] = &bCPU::op_sbc_const;
|
||||
optbl[0x6d] = &bCPU::op_adc_addr;
|
||||
optbl[0x2d] = &bCPU::op_and_addr;
|
||||
optbl[0x2c] = &bCPU::op_bit_addr;
|
||||
optbl[0xcd] = &bCPU::op_cmp_addr;
|
||||
optbl[0xec] = &bCPU::op_cpx_addr;
|
||||
optbl[0xcc] = &bCPU::op_cpy_addr;
|
||||
optbl[0x4d] = &bCPU::op_eor_addr;
|
||||
optbl[0xad] = &bCPU::op_lda_addr;
|
||||
optbl[0xae] = &bCPU::op_ldx_addr;
|
||||
optbl[0xac] = &bCPU::op_ldy_addr;
|
||||
optbl[0x0d] = &bCPU::op_ora_addr;
|
||||
optbl[0xed] = &bCPU::op_sbc_addr;
|
||||
optbl[0x7d] = &bCPU::op_adc_addrx;
|
||||
optbl[0x3d] = &bCPU::op_and_addrx;
|
||||
optbl[0x3c] = &bCPU::op_bit_addrx;
|
||||
optbl[0xdd] = &bCPU::op_cmp_addrx;
|
||||
optbl[0x5d] = &bCPU::op_eor_addrx;
|
||||
optbl[0xbd] = &bCPU::op_lda_addrx;
|
||||
optbl[0xbc] = &bCPU::op_ldy_addrx;
|
||||
optbl[0x1d] = &bCPU::op_ora_addrx;
|
||||
optbl[0xfd] = &bCPU::op_sbc_addrx;
|
||||
optbl[0x79] = &bCPU::op_adc_addry;
|
||||
optbl[0x39] = &bCPU::op_and_addry;
|
||||
optbl[0xd9] = &bCPU::op_cmp_addry;
|
||||
optbl[0x59] = &bCPU::op_eor_addry;
|
||||
optbl[0xb9] = &bCPU::op_lda_addry;
|
||||
optbl[0xbe] = &bCPU::op_ldx_addry;
|
||||
optbl[0x19] = &bCPU::op_ora_addry;
|
||||
optbl[0xf9] = &bCPU::op_sbc_addry;
|
||||
optbl[0x6f] = &bCPU::op_adc_long;
|
||||
optbl[0x2f] = &bCPU::op_and_long;
|
||||
optbl[0xcf] = &bCPU::op_cmp_long;
|
||||
optbl[0x4f] = &bCPU::op_eor_long;
|
||||
optbl[0xaf] = &bCPU::op_lda_long;
|
||||
optbl[0x0f] = &bCPU::op_ora_long;
|
||||
optbl[0xef] = &bCPU::op_sbc_long;
|
||||
optbl[0x7f] = &bCPU::op_adc_longx;
|
||||
optbl[0x3f] = &bCPU::op_and_longx;
|
||||
optbl[0xdf] = &bCPU::op_cmp_longx;
|
||||
optbl[0x5f] = &bCPU::op_eor_longx;
|
||||
optbl[0xbf] = &bCPU::op_lda_longx;
|
||||
optbl[0x1f] = &bCPU::op_ora_longx;
|
||||
optbl[0xff] = &bCPU::op_sbc_longx;
|
||||
optbl[0x65] = &bCPU::op_adc_dp;
|
||||
optbl[0x25] = &bCPU::op_and_dp;
|
||||
optbl[0x24] = &bCPU::op_bit_dp;
|
||||
optbl[0xc5] = &bCPU::op_cmp_dp;
|
||||
optbl[0xe4] = &bCPU::op_cpx_dp;
|
||||
optbl[0xc4] = &bCPU::op_cpy_dp;
|
||||
optbl[0x45] = &bCPU::op_eor_dp;
|
||||
optbl[0xa5] = &bCPU::op_lda_dp;
|
||||
optbl[0xa6] = &bCPU::op_ldx_dp;
|
||||
optbl[0xa4] = &bCPU::op_ldy_dp;
|
||||
optbl[0x05] = &bCPU::op_ora_dp;
|
||||
optbl[0xe5] = &bCPU::op_sbc_dp;
|
||||
optbl[0x75] = &bCPU::op_adc_dpx;
|
||||
optbl[0x35] = &bCPU::op_and_dpx;
|
||||
optbl[0x34] = &bCPU::op_bit_dpx;
|
||||
optbl[0xd5] = &bCPU::op_cmp_dpx;
|
||||
optbl[0x55] = &bCPU::op_eor_dpx;
|
||||
optbl[0xb5] = &bCPU::op_lda_dpx;
|
||||
optbl[0xb4] = &bCPU::op_ldy_dpx;
|
||||
optbl[0x15] = &bCPU::op_ora_dpx;
|
||||
optbl[0xf5] = &bCPU::op_sbc_dpx;
|
||||
optbl[0xb6] = &bCPU::op_ldx_dpy;
|
||||
optbl[0x72] = &bCPU::op_adc_idp;
|
||||
optbl[0x32] = &bCPU::op_and_idp;
|
||||
optbl[0xd2] = &bCPU::op_cmp_idp;
|
||||
optbl[0x52] = &bCPU::op_eor_idp;
|
||||
optbl[0xb2] = &bCPU::op_lda_idp;
|
||||
optbl[0x12] = &bCPU::op_ora_idp;
|
||||
optbl[0xf2] = &bCPU::op_sbc_idp;
|
||||
optbl[0x61] = &bCPU::op_adc_idpx;
|
||||
optbl[0x21] = &bCPU::op_and_idpx;
|
||||
optbl[0xc1] = &bCPU::op_cmp_idpx;
|
||||
optbl[0x41] = &bCPU::op_eor_idpx;
|
||||
optbl[0xa1] = &bCPU::op_lda_idpx;
|
||||
optbl[0x01] = &bCPU::op_ora_idpx;
|
||||
optbl[0xe1] = &bCPU::op_sbc_idpx;
|
||||
optbl[0x71] = &bCPU::op_adc_idpy;
|
||||
optbl[0x31] = &bCPU::op_and_idpy;
|
||||
optbl[0xd1] = &bCPU::op_cmp_idpy;
|
||||
optbl[0x51] = &bCPU::op_eor_idpy;
|
||||
optbl[0xb1] = &bCPU::op_lda_idpy;
|
||||
optbl[0x11] = &bCPU::op_ora_idpy;
|
||||
optbl[0xf1] = &bCPU::op_sbc_idpy;
|
||||
optbl[0x67] = &bCPU::op_adc_ildp;
|
||||
optbl[0x27] = &bCPU::op_and_ildp;
|
||||
optbl[0xc7] = &bCPU::op_cmp_ildp;
|
||||
optbl[0x47] = &bCPU::op_eor_ildp;
|
||||
optbl[0xa7] = &bCPU::op_lda_ildp;
|
||||
optbl[0x07] = &bCPU::op_ora_ildp;
|
||||
optbl[0xe7] = &bCPU::op_sbc_ildp;
|
||||
optbl[0x77] = &bCPU::op_adc_ildpy;
|
||||
optbl[0x37] = &bCPU::op_and_ildpy;
|
||||
optbl[0xd7] = &bCPU::op_cmp_ildpy;
|
||||
optbl[0x57] = &bCPU::op_eor_ildpy;
|
||||
optbl[0xb7] = &bCPU::op_lda_ildpy;
|
||||
optbl[0x17] = &bCPU::op_ora_ildpy;
|
||||
optbl[0xf7] = &bCPU::op_sbc_ildpy;
|
||||
optbl[0x63] = &bCPU::op_adc_sr;
|
||||
optbl[0x23] = &bCPU::op_and_sr;
|
||||
optbl[0xc3] = &bCPU::op_cmp_sr;
|
||||
optbl[0x43] = &bCPU::op_eor_sr;
|
||||
optbl[0xa3] = &bCPU::op_lda_sr;
|
||||
optbl[0x03] = &bCPU::op_ora_sr;
|
||||
optbl[0xe3] = &bCPU::op_sbc_sr;
|
||||
optbl[0x73] = &bCPU::op_adc_isry;
|
||||
optbl[0x33] = &bCPU::op_and_isry;
|
||||
optbl[0xd3] = &bCPU::op_cmp_isry;
|
||||
optbl[0x53] = &bCPU::op_eor_isry;
|
||||
optbl[0xb3] = &bCPU::op_lda_isry;
|
||||
optbl[0x13] = &bCPU::op_ora_isry;
|
||||
optbl[0xf3] = &bCPU::op_sbc_isry;
|
||||
optbl[0x89] = &bCPU::op_bit_const;
|
||||
optbl[0x1a] = &bCPU::op_inc;
|
||||
optbl[0xe8] = &bCPU::op_inx;
|
||||
optbl[0xc8] = &bCPU::op_iny;
|
||||
optbl[0x3a] = &bCPU::op_dec;
|
||||
optbl[0xca] = &bCPU::op_dex;
|
||||
optbl[0x88] = &bCPU::op_dey;
|
||||
optbl[0x0a] = &bCPU::op_asl;
|
||||
optbl[0x4a] = &bCPU::op_lsr;
|
||||
optbl[0x2a] = &bCPU::op_rol;
|
||||
optbl[0x6a] = &bCPU::op_ror;
|
||||
optbl[0xee] = &bCPU::op_inc_addr;
|
||||
optbl[0xce] = &bCPU::op_dec_addr;
|
||||
optbl[0x0e] = &bCPU::op_asl_addr;
|
||||
optbl[0x4e] = &bCPU::op_lsr_addr;
|
||||
optbl[0x2e] = &bCPU::op_rol_addr;
|
||||
optbl[0x6e] = &bCPU::op_ror_addr;
|
||||
optbl[0x1c] = &bCPU::op_trb_addr;
|
||||
optbl[0x0c] = &bCPU::op_tsb_addr;
|
||||
optbl[0xfe] = &bCPU::op_inc_addrx;
|
||||
optbl[0xde] = &bCPU::op_dec_addrx;
|
||||
optbl[0x1e] = &bCPU::op_asl_addrx;
|
||||
optbl[0x5e] = &bCPU::op_lsr_addrx;
|
||||
optbl[0x3e] = &bCPU::op_rol_addrx;
|
||||
optbl[0x7e] = &bCPU::op_ror_addrx;
|
||||
optbl[0xe6] = &bCPU::op_inc_dp;
|
||||
optbl[0xc6] = &bCPU::op_dec_dp;
|
||||
optbl[0x06] = &bCPU::op_asl_dp;
|
||||
optbl[0x46] = &bCPU::op_lsr_dp;
|
||||
optbl[0x26] = &bCPU::op_rol_dp;
|
||||
optbl[0x66] = &bCPU::op_ror_dp;
|
||||
optbl[0x14] = &bCPU::op_trb_dp;
|
||||
optbl[0x04] = &bCPU::op_tsb_dp;
|
||||
optbl[0xf6] = &bCPU::op_inc_dpx;
|
||||
optbl[0xd6] = &bCPU::op_dec_dpx;
|
||||
optbl[0x16] = &bCPU::op_asl_dpx;
|
||||
optbl[0x56] = &bCPU::op_lsr_dpx;
|
||||
optbl[0x36] = &bCPU::op_rol_dpx;
|
||||
optbl[0x76] = &bCPU::op_ror_dpx;
|
||||
optbl[0x8d] = &bCPU::op_sta_addr;
|
||||
optbl[0x8e] = &bCPU::op_stx_addr;
|
||||
optbl[0x8c] = &bCPU::op_sty_addr;
|
||||
optbl[0x9c] = &bCPU::op_stz_addr;
|
||||
optbl[0x9d] = &bCPU::op_sta_addrx;
|
||||
optbl[0x9e] = &bCPU::op_stz_addrx;
|
||||
optbl[0x99] = &bCPU::op_sta_addry;
|
||||
optbl[0x8f] = &bCPU::op_sta_long;
|
||||
optbl[0x9f] = &bCPU::op_sta_longx;
|
||||
optbl[0x85] = &bCPU::op_sta_dp;
|
||||
optbl[0x86] = &bCPU::op_stx_dp;
|
||||
optbl[0x84] = &bCPU::op_sty_dp;
|
||||
optbl[0x64] = &bCPU::op_stz_dp;
|
||||
optbl[0x95] = &bCPU::op_sta_dpx;
|
||||
optbl[0x94] = &bCPU::op_sty_dpx;
|
||||
optbl[0x74] = &bCPU::op_stz_dpx;
|
||||
optbl[0x96] = &bCPU::op_stx_dpy;
|
||||
optbl[0x92] = &bCPU::op_sta_idp;
|
||||
optbl[0x87] = &bCPU::op_sta_ildp;
|
||||
optbl[0x81] = &bCPU::op_sta_idpx;
|
||||
optbl[0x91] = &bCPU::op_sta_idpy;
|
||||
optbl[0x97] = &bCPU::op_sta_ildpy;
|
||||
optbl[0x83] = &bCPU::op_sta_sr;
|
||||
optbl[0x93] = &bCPU::op_sta_isry;
|
||||
optbl[0x90] = &bCPU::op_bcc;
|
||||
optbl[0xb0] = &bCPU::op_bcs;
|
||||
optbl[0xd0] = &bCPU::op_bne;
|
||||
optbl[0xf0] = &bCPU::op_beq;
|
||||
optbl[0x10] = &bCPU::op_bpl;
|
||||
optbl[0x30] = &bCPU::op_bmi;
|
||||
optbl[0x50] = &bCPU::op_bvc;
|
||||
optbl[0x70] = &bCPU::op_bvs;
|
||||
optbl[0x80] = &bCPU::op_bra;
|
||||
optbl[0x82] = &bCPU::op_brl;
|
||||
optbl[0x4c] = &bCPU::op_jmp_addr;
|
||||
optbl[0x5c] = &bCPU::op_jmp_long;
|
||||
optbl[0x6c] = &bCPU::op_jmp_iaddr;
|
||||
optbl[0x7c] = &bCPU::op_jmp_iaddrx;
|
||||
optbl[0xdc] = &bCPU::op_jmp_iladdr;
|
||||
optbl[0x20] = &bCPU::op_jsr_addr;
|
||||
optbl[0x22] = &bCPU::op_jsr_long;
|
||||
optbl[0xfc] = &bCPU::op_jsr_iaddrx;
|
||||
optbl[0x40] = &bCPU::op_rti;
|
||||
optbl[0x60] = &bCPU::op_rts;
|
||||
optbl[0x6b] = &bCPU::op_rtl;
|
||||
optbl[0xea] = &bCPU::op_nop;
|
||||
optbl[0x42] = &bCPU::op_wdm;
|
||||
optbl[0xeb] = &bCPU::op_xba;
|
||||
optbl[0x54] = &bCPU::op_mvn;
|
||||
optbl[0x44] = &bCPU::op_mvp;
|
||||
optbl[0x00] = &bCPU::op_brk;
|
||||
optbl[0x02] = &bCPU::op_cop;
|
||||
optbl[0xdb] = &bCPU::op_stp;
|
||||
optbl[0xcb] = &bCPU::op_wai;
|
||||
optbl[0xfb] = &bCPU::op_xce;
|
||||
optbl[0x18] = &bCPU::op_clc;
|
||||
optbl[0xd8] = &bCPU::op_cld;
|
||||
optbl[0x58] = &bCPU::op_cli;
|
||||
optbl[0xb8] = &bCPU::op_clv;
|
||||
optbl[0x38] = &bCPU::op_sec;
|
||||
optbl[0xf8] = &bCPU::op_sed;
|
||||
optbl[0x78] = &bCPU::op_sei;
|
||||
optbl[0xc2] = &bCPU::op_rep;
|
||||
optbl[0xe2] = &bCPU::op_sep;
|
||||
optbl[0xaa] = &bCPU::op_tax;
|
||||
optbl[0xa8] = &bCPU::op_tay;
|
||||
optbl[0x8a] = &bCPU::op_txa;
|
||||
optbl[0x9b] = &bCPU::op_txy;
|
||||
optbl[0x98] = &bCPU::op_tya;
|
||||
optbl[0xbb] = &bCPU::op_tyx;
|
||||
optbl[0x5b] = &bCPU::op_tcd;
|
||||
optbl[0x1b] = &bCPU::op_tcs;
|
||||
optbl[0x7b] = &bCPU::op_tdc;
|
||||
optbl[0x3b] = &bCPU::op_tsc;
|
||||
optbl[0xba] = &bCPU::op_tsx;
|
||||
optbl[0x9a] = &bCPU::op_txs;
|
||||
optbl[0x48] = &bCPU::op_pha;
|
||||
optbl[0xda] = &bCPU::op_phx;
|
||||
optbl[0x5a] = &bCPU::op_phy;
|
||||
optbl[0x0b] = &bCPU::op_phd;
|
||||
optbl[0x8b] = &bCPU::op_phb;
|
||||
optbl[0x4b] = &bCPU::op_phk;
|
||||
optbl[0x08] = &bCPU::op_php;
|
||||
optbl[0x68] = &bCPU::op_pla;
|
||||
optbl[0xfa] = &bCPU::op_plx;
|
||||
optbl[0x7a] = &bCPU::op_ply;
|
||||
optbl[0x2b] = &bCPU::op_pld;
|
||||
optbl[0xab] = &bCPU::op_plb;
|
||||
optbl[0x28] = &bCPU::op_plp;
|
||||
optbl[0xf4] = &bCPU::op_pea;
|
||||
optbl[0xd4] = &bCPU::op_pei;
|
||||
optbl[0x62] = &bCPU::op_per;
|
||||
@@ -1,356 +0,0 @@
|
||||
/* Notes about PAL timing:
|
||||
* As I do not have PAL hardware to run timing tests on, I've
|
||||
* had to guess on a lot of things. Below is how I've arrived
|
||||
* at various calculations:
|
||||
*
|
||||
* NTSC timing crystal: ~21477272hz
|
||||
* PAL timing crystal: ~21281370hz
|
||||
* NTSC ~60fps, PAL ~50fps
|
||||
* NTSC ~262 lines/frame, PAL ~312 lines/frame
|
||||
* NTSC 21477272 / (262 * 60) = ~1366 cycles/line
|
||||
* PAL 21281370 / (312 * 50) = ~1364 cycles/line
|
||||
*
|
||||
* As the cycles/line are very close between the two systems,
|
||||
* I have left the known NTSC anomalies intact for PAL timing.
|
||||
* In reality, some of these may not exist, and some may be
|
||||
* slightly different.
|
||||
*
|
||||
* [known]
|
||||
* - DRAM refresh occurs at about the same time every
|
||||
* scanline on PAL units (per Overload).
|
||||
* [unknown]
|
||||
* - Are dots 323/327 still 2 cycles longer than the
|
||||
* other dots?
|
||||
* - Is scanline 240 on non-interlace odd frames still
|
||||
* 4 cycles short?
|
||||
*/
|
||||
|
||||
uint16 bCPU::vcounter() { return time.v; }
|
||||
uint16 bCPU::hcounter() { return get_hcounter(); }
|
||||
uint16 bCPU::hcycles() { return time.hc; }
|
||||
|
||||
bool bCPU::interlace() { return time.interlace; }
|
||||
bool bCPU::interlace_field() { return time.interlace_field; }
|
||||
bool bCPU::overscan() { return time.overscan; }
|
||||
uint16 bCPU::region_scanlines() { return time.region_scanlines; }
|
||||
|
||||
void bCPU::set_interlace(bool r) { time.interlace = r; update_interrupts(); }
|
||||
void bCPU::set_overscan (bool r) { time.overscan = r; update_interrupts(); }
|
||||
|
||||
uint8 bCPU::dma_counter() { return (time.dma_counter + time.hc) & 6; }
|
||||
|
||||
bool bCPU::nmi_trigger_pos_match(uint32 offset) {
|
||||
uint16 v = overscan() ? 240 : 225;
|
||||
uint16 hc = 2 + offset;
|
||||
return (time.v == v && time.hc == hc);
|
||||
}
|
||||
|
||||
bool bCPU::irq_trigger_pos_match(uint32 offset) {
|
||||
uint16 v = status.virq_pos;
|
||||
uint16 hc = (status.hirq_enabled) ? status.hirq_pos : 0;
|
||||
|
||||
//positions that can never be latched
|
||||
//region_scanlines() = 262/NTSC, 312/PAL
|
||||
//PAL results are unverified on hardware
|
||||
if(v == 240 && hc == 339 && interlace() == false && interlace_field() == 1)return false;
|
||||
if(v == (region_scanlines() - 1) && hc == 339 && interlace() == false)return false;
|
||||
if(v == region_scanlines() && interlace() == false)return false;
|
||||
if(v == region_scanlines() && hc == 339)return false;
|
||||
if(v > region_scanlines())return false;
|
||||
if(hc > 339)return false;
|
||||
|
||||
hc = (hc != 0) ? ((hc << 2) + 14) : 10;
|
||||
hc += offset;
|
||||
if(hc >= time.line_cycles) {
|
||||
hc -= time.line_cycles;
|
||||
if(++v >= time.frame_lines) {
|
||||
v = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if((status.virq_enabled == true && time.v == v) || status.virq_enabled == false) {
|
||||
return (time.hc == hc);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void bCPU::update_nmi() {
|
||||
if(time.v == (overscan() ? 240 : 225)) {
|
||||
time.nmi_read_trigger_pos = 2;
|
||||
time.nmi_line_trigger_pos = 6;
|
||||
} else {
|
||||
time.nmi_read_trigger_pos = -64;
|
||||
time.nmi_line_trigger_pos = -64;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::update_irq() {
|
||||
int vpos = status.virq_pos;
|
||||
int hpos = (status.hirq_enabled) ? status.hirq_pos : 0;
|
||||
|
||||
//positions that can never be latched
|
||||
//region_scanlines() = 262/NTSC, 312/PAL
|
||||
//PAL results are unverified on hardware
|
||||
if(vpos == 240 && hpos == 339 && interlace() == false && interlace_field() == 1)goto _nolatch;
|
||||
if(vpos == (region_scanlines() - 1) && hpos == 339 && interlace() == false)goto _nolatch;
|
||||
if(vpos == region_scanlines() && interlace() == false)goto _nolatch;
|
||||
if(vpos == region_scanlines() && hpos == 339)goto _nolatch;
|
||||
if(vpos > region_scanlines())goto _nolatch;
|
||||
if(hpos > 339)goto _nolatch;
|
||||
|
||||
hpos = (hpos != 0) ? ((hpos << 2) + 14) : 10;
|
||||
if(hpos >= time.line_cycles) {
|
||||
hpos -= time.line_cycles;
|
||||
if(++vpos >= time.frame_lines) {
|
||||
vpos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if((status.virq_enabled == true && time.v == vpos) || status.virq_enabled == false) {
|
||||
time.irq_read_trigger_pos = hpos;
|
||||
} else {
|
||||
time.irq_read_trigger_pos = -64;
|
||||
}
|
||||
|
||||
hpos += 4;
|
||||
if(hpos >= time.line_cycles) {
|
||||
hpos -= time.line_cycles;
|
||||
if(++vpos >= time.frame_lines) {
|
||||
vpos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if((status.virq_enabled == true && time.v == vpos) || status.virq_enabled == false) {
|
||||
time.irq_line_trigger_pos = hpos;
|
||||
} else {
|
||||
time.irq_line_trigger_pos = -64;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
_nolatch:
|
||||
time.irq_read_trigger_pos = -64;
|
||||
time.irq_line_trigger_pos = -64;
|
||||
}
|
||||
|
||||
void bCPU::update_interrupts() {
|
||||
update_nmi();
|
||||
update_irq();
|
||||
}
|
||||
|
||||
void bCPU::poll_interrupts(int cycles) {
|
||||
int16 hc, hc_end;
|
||||
if(time.hc == 0) {
|
||||
hc = -1;
|
||||
hc_end = cycles;
|
||||
} else {
|
||||
hc = time.hc;
|
||||
hc_end = time.hc + cycles;
|
||||
}
|
||||
|
||||
if(hc < time.nmi_read_trigger_pos && time.nmi_read_trigger_pos <= hc_end) {
|
||||
//nmi_read can go low even with NMI interrupts disabled in $4200.d7
|
||||
time.nmi_read = 0;
|
||||
}
|
||||
|
||||
if(hc < time.nmi_line_trigger_pos && time.nmi_line_trigger_pos <= hc_end) {
|
||||
if(status.nmi_enabled == true) {
|
||||
if(time.nmi_line == 1) {
|
||||
time.nmi_transition = 1;
|
||||
}
|
||||
time.nmi_line = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(hc < time.irq_read_trigger_pos && time.irq_read_trigger_pos <= hc_end) {
|
||||
if(status.virq_enabled == true || status.hirq_enabled == true) {
|
||||
time.irq_read = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(hc < time.irq_line_trigger_pos && time.irq_line_trigger_pos <= hc_end) {
|
||||
if(status.virq_enabled == true || status.hirq_enabled == true) {
|
||||
time.irq_line = 0;
|
||||
time.irq_transition = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//all scanlines are 1364 cycles long, except scanline 240
|
||||
//on non-interlace odd-frames, which is 1360 cycles long.
|
||||
//[NTSC]
|
||||
//interlace mode has 525 scanlines: 263 on the even frame,
|
||||
//and 262 on the odd.
|
||||
//non-interlace mode has 524 scanlines: 262 scanlines on
|
||||
//both even and odd frames.
|
||||
//[PAL] <PAL info is unverified on hardware>
|
||||
//interlace mode has 625 scanlines: 313 on the even frame,
|
||||
//and 312 on the odd.
|
||||
//non-interlace mode has 624 scanlines: 312 scanlines on
|
||||
//both even and odd frames.
|
||||
//
|
||||
//cycles per frame:
|
||||
// 263 * 1364 = 358732
|
||||
// 262 * 1364 = 357368
|
||||
// 262 * 1364 - 4 = 357364
|
||||
void bCPU::inc_vcounter() {
|
||||
time.v++;
|
||||
if(time.v >= time.frame_lines) {
|
||||
time.v = 0;
|
||||
time.interlace_field ^= 1;
|
||||
|
||||
if(time.interlace == true && time.interlace_field == 0) {
|
||||
time.frame_lines = time.region_scanlines + 1;
|
||||
} else {
|
||||
time.frame_lines = time.region_scanlines;
|
||||
}
|
||||
}
|
||||
|
||||
time.dma_counter += time.line_cycles;
|
||||
if(time.v == 240 && time.interlace == false && time.interlace_field == 1) {
|
||||
time.line_cycles = 1360;
|
||||
} else {
|
||||
time.line_cycles = 1364;
|
||||
}
|
||||
time.dram_refreshed = false;
|
||||
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
//all dots are 4 cycles long, except dots 323 and 327. dots 323 and 327
|
||||
//are 6 cycles long. this holds true for all scanlines except scanline
|
||||
//240 on non-interlace odd frames. the reason for this is because this
|
||||
//scanline is only 1360 cycles long, instead of 1364 like all other
|
||||
//scanlines.
|
||||
//this makes the effective range of hscan_pos 0-339 at all times.
|
||||
//dot 323 range = { 1292, 1294, 1296 }
|
||||
//dot 327 range = { 1310, 1312, 1314 }
|
||||
uint16 bCPU::get_hcounter() {
|
||||
if(time.v == 240 && time.interlace == false && time.interlace_field == 1) {
|
||||
return time.hc >> 2;
|
||||
}
|
||||
return (time.hc - ((time.hc > 1292) << 1) - ((time.hc > 1310) << 1)) >> 2;
|
||||
}
|
||||
|
||||
uint32 bCPU::cycles_executed() {
|
||||
uint32 r = status.cycles_executed;
|
||||
status.cycles_executed = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
void bCPU::add_cycles(int cycles) {
|
||||
status.cycles_executed += cycles;
|
||||
|
||||
poll_interrupts(cycles);
|
||||
|
||||
if(time.hc + cycles >= time.line_cycles) {
|
||||
cycles = (time.hc + cycles) - time.line_cycles;
|
||||
time.hc = 0;
|
||||
|
||||
inc_vcounter();
|
||||
poll_interrupts(cycles);
|
||||
|
||||
if(time.v == 0) {
|
||||
frame();
|
||||
ppu->frame();
|
||||
snes->frame();
|
||||
}
|
||||
|
||||
scanline();
|
||||
ppu->scanline();
|
||||
snes->scanline();
|
||||
time.line_rendered = false;
|
||||
}
|
||||
|
||||
if(time.hdmainit_triggered == false) {
|
||||
if(time.hc + cycles >= time.hdmainit_trigger_pos || time.v) {
|
||||
time.hdmainit_triggered = true;
|
||||
hdmainit_activate();
|
||||
}
|
||||
}
|
||||
|
||||
if(time.dram_refreshed == false) {
|
||||
if(time.hc + cycles >= time.dram_refresh_pos) {
|
||||
time.dram_refreshed = true;
|
||||
status.cycles_executed += 40;
|
||||
cycles = (time.hc + cycles) - time.dram_refresh_pos;
|
||||
time.hc = time.dram_refresh_pos + 40;
|
||||
|
||||
if(cpu_version == 2) {
|
||||
if(time.v != 240 || time.interlace != false || time.interlace_field != 1) {
|
||||
if(time.dram_refresh_pos == 534) {
|
||||
time.dram_refresh_pos = 538;
|
||||
} else {
|
||||
time.dram_refresh_pos = 534;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(time.line_rendered == false) {
|
||||
//rendering should start at H=18 (+256=274), but since the
|
||||
//current PPU emulation renders the entire scanline at once,
|
||||
//PPU register changes mid-scanline do not show up.
|
||||
//therefore, wait a few dots before rendering the scanline
|
||||
if(time.hc + cycles >= (48 * 4)) {
|
||||
time.line_rendered = true;
|
||||
ppu->render_scanline();
|
||||
}
|
||||
}
|
||||
|
||||
if(time.hdma_triggered == false) {
|
||||
if(time.v <= (overscan() ? 239 : 224)) {
|
||||
if(time.hc + cycles >= 1106) {
|
||||
time.hdma_triggered = true;
|
||||
hdma_activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
time.hc += cycles;
|
||||
}
|
||||
|
||||
void bCPU::time_reset() {
|
||||
time.v = 0;
|
||||
time.hc = 0;
|
||||
|
||||
//upon SNES reset, start at scanline 0 non-interlace
|
||||
time.interlace = false;
|
||||
time.interlace_field = false;
|
||||
time.overscan = false;
|
||||
time.line_cycles = 1364;
|
||||
|
||||
time.dram_refreshed = false;
|
||||
time.dram_refresh_pos = (cpu_version == 2) ? 538 : 530;
|
||||
|
||||
time.dma_counter = 0;
|
||||
|
||||
//set at V=0,H=0
|
||||
time.hdmainit_trigger_pos = 0;
|
||||
time.hdmainit_triggered = true;
|
||||
|
||||
time.hdma_triggered = false;
|
||||
|
||||
time.nmi_pending = false;
|
||||
time.irq_pending = false;
|
||||
time.nmi_line = time.nmi_read = 1;
|
||||
time.irq_line = time.irq_read = 1;
|
||||
|
||||
time.nmi_transition = 0;
|
||||
time.irq_transition = 0;
|
||||
|
||||
update_interrupts();
|
||||
|
||||
switch(region) {
|
||||
case NTSC:
|
||||
time.region_scanlines = 262;
|
||||
break;
|
||||
case PAL:
|
||||
time.region_scanlines = 312;
|
||||
break;
|
||||
}
|
||||
|
||||
time.frame_lines = time.region_scanlines;
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
struct {
|
||||
uint16 v, hc;
|
||||
|
||||
bool interlace, interlace_field, overscan;
|
||||
uint16 line_cycles, frame_lines;
|
||||
|
||||
bool line_rendered;
|
||||
|
||||
bool dram_refreshed;
|
||||
uint16 dram_refresh_pos;
|
||||
|
||||
uint8 dma_counter;
|
||||
|
||||
uint16 hdmainit_trigger_pos;
|
||||
bool hdmainit_triggered;
|
||||
|
||||
bool hdma_triggered;
|
||||
|
||||
uint16 region_scanlines;
|
||||
|
||||
//nmi_pending, irq_pending are used by last_cycle()
|
||||
//nmi_line = /NMI, nmi_read = $4210.7
|
||||
//irq_line = /IRQ, irq_read = $4211.7
|
||||
bool nmi_pending, nmi_line, nmi_read;
|
||||
bool irq_pending, irq_line, irq_read;
|
||||
|
||||
//NMI is edge-sensitive, meaning it triggers when /NMI
|
||||
//transitions from high to low. This value is set to 1
|
||||
//when that happens, and cleared after the nmi_test()
|
||||
//routine acknowledges it and invokes the NMI interrupt
|
||||
bool nmi_transition;
|
||||
|
||||
//IRQ is level-sensitive, so it does not need to keep
|
||||
//track of transitions from high to low. IRQs will
|
||||
//continue to fire as long as /IRQ stays low.
|
||||
//However, if a write to $4200 forces IRQs high at the
|
||||
//exact same clock cycle that /IRQ goes low, the /IRQ
|
||||
//will still occur. Hence the need for this variable.
|
||||
bool irq_transition;
|
||||
|
||||
//position is relative to time.hc, set at start of each scanline
|
||||
//-64 means no trigger point on this scanline
|
||||
//$4210/$4211 status bits get set before /NMI and /IRQ go low,
|
||||
//hence the need for two variables for each.
|
||||
int32 nmi_read_trigger_pos, nmi_line_trigger_pos;
|
||||
int32 irq_read_trigger_pos, irq_line_trigger_pos;
|
||||
} time;
|
||||
|
||||
inline uint16 vcounter();
|
||||
inline uint16 hcounter();
|
||||
inline uint16 hcycles();
|
||||
inline bool interlace();
|
||||
inline bool interlace_field();
|
||||
inline bool overscan();
|
||||
inline uint16 region_scanlines();
|
||||
|
||||
inline bool nmi_trigger_pos_match(uint32 offset);
|
||||
inline bool irq_trigger_pos_match(uint32 offset);
|
||||
|
||||
inline void update_nmi();
|
||||
inline void update_irq();
|
||||
inline void update_interrupts();
|
||||
inline void poll_interrupts(int cycles);
|
||||
|
||||
inline void set_interlace(bool r);
|
||||
inline void set_overscan (bool r);
|
||||
|
||||
inline uint8 dma_counter();
|
||||
|
||||
inline void inc_vcounter();
|
||||
inline uint16 get_hcounter();
|
||||
inline void add_cycles(int cycles);
|
||||
inline void time_reset();
|
||||
@@ -1,3 +0,0 @@
|
||||
cl /ML /O2 bcpugen.cpp
|
||||
@pause
|
||||
@del *.obj
|
||||
@@ -1,8 +0,0 @@
|
||||
@del *.exe
|
||||
@del bcpu_op_misc.cpp
|
||||
@del bcpu_op_pc.cpp
|
||||
@del bcpu_op_read.cpp
|
||||
@del bcpu_op_rmw.cpp
|
||||
@del bcpu_op_write.cpp
|
||||
@del bcpu_optable.cpp
|
||||
@del bcpu_op.h
|
||||
@@ -1,159 +0,0 @@
|
||||
bcc(0x90, !regs.p.c),
|
||||
bcs(0xb0, regs.p.c),
|
||||
bne(0xd0, !regs.p.z),
|
||||
beq(0xf0, regs.p.z),
|
||||
bpl(0x10, !regs.p.n),
|
||||
bmi(0x30, regs.p.n),
|
||||
bvc(0x50, !regs.p.v),
|
||||
bvs(0x70, regs.p.v) {
|
||||
1:if(!$1)last_cycle();
|
||||
rd.l = op_read();
|
||||
if($1) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
end;
|
||||
}
|
||||
2:cpu_c6(aa.w);
|
||||
3:last_cycle();
|
||||
cpu_io();
|
||||
}
|
||||
|
||||
bra(0x80) {
|
||||
1:rd.l = op_read();
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
2:cpu_c6(aa.w);
|
||||
3:last_cycle();
|
||||
cpu_io();
|
||||
}
|
||||
|
||||
brl(0x82) {
|
||||
1:rd.l = op_read();
|
||||
2:rd.h = op_read();
|
||||
3:last_cycle();
|
||||
cpu_io();
|
||||
regs.pc.w = regs.pc.d + (int16)rd.w;
|
||||
}
|
||||
|
||||
jmp_addr(0x4c) {
|
||||
1:rd.l = op_read();
|
||||
2:last_cycle();
|
||||
rd.h = op_read();
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
jmp_long(0x5c) {
|
||||
1:rd.l = op_read();
|
||||
2:rd.h = op_read();
|
||||
3:last_cycle();
|
||||
rd.b = op_read();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
jmp_iaddr(0x6c) {
|
||||
1:aa.l = op_read();
|
||||
2:aa.h = op_read();
|
||||
3:rd.l = op_read(OPMODE_ADDR, aa.w);
|
||||
4:last_cycle();
|
||||
rd.h = op_read(OPMODE_ADDR, aa.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
jmp_iaddrx(0x7c) {
|
||||
1:aa.l = op_read();
|
||||
2:aa.h = op_read();
|
||||
3:cpu_io();
|
||||
4:rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w);
|
||||
5:last_cycle();
|
||||
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
jmp_iladdr(0xdc) {
|
||||
1:aa.l = op_read();
|
||||
2:aa.h = op_read();
|
||||
3:rd.l = op_read(OPMODE_ADDR, aa.w);
|
||||
4:rd.h = op_read(OPMODE_ADDR, aa.w + 1);
|
||||
5:last_cycle();
|
||||
rd.b = op_read(OPMODE_ADDR, aa.w + 2);
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
jsr_addr(0x20) {
|
||||
1:aa.l = op_read();
|
||||
2:aa.h = op_read();
|
||||
3:cpu_io();
|
||||
4:regs.pc.w--;
|
||||
stack_write(regs.pc.h);
|
||||
5:last_cycle();
|
||||
stack_write(regs.pc.l);
|
||||
regs.pc.w = aa.w;
|
||||
}
|
||||
|
||||
jsr_long(0x22) {
|
||||
1:aa.l = op_read();
|
||||
2:aa.h = op_read();
|
||||
3:stack_write(regs.pc.b);
|
||||
4:cpu_io();
|
||||
5:aa.b = op_read();
|
||||
6:regs.pc.w--;
|
||||
stack_write(regs.pc.h);
|
||||
7:last_cycle();
|
||||
stack_write(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
}
|
||||
|
||||
jsr_iaddrx(0xfc) {
|
||||
1:aa.l = op_read();
|
||||
2:stack_write(regs.pc.h);
|
||||
3:stack_write(regs.pc.l);
|
||||
4:aa.h = op_read();
|
||||
5:cpu_io();
|
||||
6:rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w);
|
||||
7:last_cycle();
|
||||
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
rti(0x40) {
|
||||
1:cpu_io();
|
||||
2:cpu_io();
|
||||
3:regs.p = stack_read();
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
4:rd.l = stack_read();
|
||||
5:rd.h = stack_read();
|
||||
if(regs.e) {
|
||||
regs.pc.w = rd.w;
|
||||
end;
|
||||
}
|
||||
6:last_cycle();
|
||||
rd.b = stack_read();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
rts(0x60) {
|
||||
1:cpu_io();
|
||||
2:cpu_io();
|
||||
3:rd.l = stack_read();
|
||||
4:rd.h = stack_read();
|
||||
5:last_cycle();
|
||||
cpu_io();
|
||||
regs.pc.w = rd.w;
|
||||
regs.pc.w++;
|
||||
}
|
||||
|
||||
rtl(0x6b) {
|
||||
1:cpu_io();
|
||||
2:cpu_io();
|
||||
3:rd.l = stack_read();
|
||||
4:rd.h = stack_read();
|
||||
5:last_cycle();
|
||||
rd.b = stack_read();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
regs.pc.w++;
|
||||
}
|
||||
Loaded 100 of 583 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user