mirror of
https://github.com/ares-emulator/ares.git
synced 2026-11-07 17:01:59 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd83559786 | ||
|
|
100ef3a271 | ||
|
|
bccc5b5a12 | ||
|
|
acee547da9 | ||
|
|
b1b146fd7d | ||
|
|
53e913e225 | ||
|
|
0cf16ce784 | ||
|
|
ce38d577ef | ||
|
|
0a87b99370 | ||
|
|
82d5761705 | ||
|
|
9133129209 | ||
|
|
7d83cde40a | ||
|
|
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 | ||
|
|
c6c5f4669c | ||
|
|
397b9c4505 | ||
|
|
7e2cfb6d40 | ||
|
|
970dcea0ac | ||
|
|
402c146a53 | ||
|
|
a471c150c9 | ||
|
|
ea38ea2537 | ||
|
|
09b326ae86 |
No files matched your search
Binary file not shown.
+83
-9
@@ -1,10 +1,84 @@
|
||||
bsnes Licensing Agreement:
|
||||
bsnes (TM) Reference License
|
||||
Copyright (C) 2004 - 2008 byuu
|
||||
All rights reserved
|
||||
|
||||
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. You must also abide
|
||||
by the terms of any additional source code licenses contained within my code.
|
||||
At present, this only includes the mode7 renderer, which was derived from the
|
||||
snes9x mode7 renderer.
|
||||
1. Definitions
|
||||
|
||||
The terms "reproduce", "reproduction", "distribute" and "distribution" have the
|
||||
same meaning here as under U.S. copyright law.
|
||||
|
||||
"The software" means this software package as a whole, including, but not
|
||||
limited to, this license, binaries, source code, documentation, and data.
|
||||
|
||||
"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
|
||||
S-DD1 decompressor, author: Andreas Naive
|
||||
SPC7110 decompressor, author: neviksti
|
||||
|
||||
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
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
bsnes
|
||||
Version: 0.034
|
||||
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
|
||||
- "Glitch" when reading joypad registers during auto polling 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
|
||||
|
||||
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
|
||||
|
||||
=============
|
||||
Contributors:
|
||||
=============
|
||||
|
||||
Andreas Naive, anomie, blargg, DMV27, FitzRoy, GIGO, Jonas Quinn, kode54, krom,
|
||||
mudlord, Nach, neviksti, Overload, RedDwarf, Richard Bannister, tetsuo55, TRAC,
|
||||
zones
|
||||
+280
@@ -0,0 +1,280 @@
|
||||
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 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010
|
||||
|
||||
ifeq ($(enable_gzip),true)
|
||||
objects += adler32 compress crc32 deflate gzio inffast inflate inftrees ioapi trees unzip zip zutil
|
||||
flags += $(call mkdef,GZIP_SUPPORT)
|
||||
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/spc7110.$(obj): chip/spc7110/spc7110.cpp chip/spc7110/*
|
||||
obj/cx4.$(obj) : chip/cx4/cx4.cpp chip/cx4/*
|
||||
obj/dsp1.$(obj) : chip/dsp1/dsp1.cpp chip/dsp1/*
|
||||
obj/dsp2.$(obj) : chip/dsp2/dsp2.cpp chip/dsp2/*
|
||||
obj/dsp3.$(obj) : chip/dsp3/dsp3.cpp chip/dsp3/*
|
||||
obj/dsp4.$(obj) : chip/dsp4/dsp4.cpp chip/dsp4/*
|
||||
obj/obc1.$(obj) : chip/obc1/obc1.cpp chip/obc1/*
|
||||
obj/st010.$(obj) : chip/st010/st010.cpp chip/st010/*
|
||||
|
||||
############
|
||||
### 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 ""
|
||||
+43
-32
@@ -1,32 +1,43 @@
|
||||
//platform-independant includes
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
//typecasts
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short word;
|
||||
typedef unsigned long ulong;
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned long uint32;
|
||||
|
||||
typedef signed char int8;
|
||||
typedef signed short int16;
|
||||
typedef signed long int32;
|
||||
|
||||
//structs
|
||||
typedef struct {
|
||||
uint8 *data;
|
||||
uint32 size;
|
||||
}lfile;
|
||||
|
||||
//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.034"
|
||||
#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*, ...);
|
||||
|
||||
#include "interface.h"
|
||||
@@ -0,0 +1,141 @@
|
||||
#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, cartrtc;
|
||||
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 = cart.rtc = 0;
|
||||
bs.ram = 0;
|
||||
stA.rom = stA.ram = 0;
|
||||
stB.rom = stB.ram = 0;
|
||||
|
||||
cart.rom_size = cart.ram_size = cart.rtc_size = 0;
|
||||
bs.ram_size = 0;
|
||||
stA.rom_size = stA.ram_size = 0;
|
||||
stB.rom_size = stB.ram_size = 0;
|
||||
|
||||
info.type = cart_type;
|
||||
info.patched = false;
|
||||
|
||||
info.bsxbase = false;
|
||||
info.bsxcart = false;
|
||||
info.bsxflash = false;
|
||||
info.st = false;
|
||||
|
||||
info.superfx = false;
|
||||
info.sa1 = false;
|
||||
info.srtc = false;
|
||||
info.sdd1 = false;
|
||||
info.spc7110 = false;
|
||||
info.spc7110rtc = 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::cartrtc.map(cart.rtc, cart.rtc_size);
|
||||
memory::bscram.map(bs.ram, bs.ram_size);
|
||||
memory::stArom.map(stA.rom, stA.rom_size);
|
||||
memory::stAram.map(stA.ram, stA.ram_size);
|
||||
memory::stBrom.map(stB.rom, stB.rom_size);
|
||||
memory::stBram.map(stB.ram, stB.ram_size);
|
||||
|
||||
memory::cartrom.write_protect(true);
|
||||
memory::cartram.write_protect(false);
|
||||
memory::bscram.write_protect(true);
|
||||
memory::stArom.write_protect(true);
|
||||
memory::stAram.write_protect(false);
|
||||
memory::stBrom.write_protect(true);
|
||||
memory::stBram.write_protect(false);
|
||||
|
||||
if(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(cart.rtc) { delete[] cart.rtc; cart.rtc = 0; }
|
||||
if(bs.ram) { delete[] bs.ram; bs.ram = 0; }
|
||||
if(stA.rom) { delete[] stA.rom; stA.rom = 0; }
|
||||
if(stA.ram) { delete[] stA.ram; stA.ram = 0; }
|
||||
if(stB.rom) { delete[] stB.rom; stB.rom = 0; }
|
||||
if(stB.ram) { delete[] stB.ram; stB.ram = 0; }
|
||||
|
||||
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();
|
||||
}
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
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,
|
||||
SPC7110ROM,
|
||||
BSXROM,
|
||||
BSCLoROM,
|
||||
BSCHiROM,
|
||||
STROM,
|
||||
};
|
||||
|
||||
enum DSP1MemoryMapper {
|
||||
DSP1Unmapped,
|
||||
DSP1LoROM1MB,
|
||||
DSP1LoROM2MB,
|
||||
DSP1HiROM,
|
||||
};
|
||||
|
||||
struct {
|
||||
bool loaded;
|
||||
char fn[PATH_MAX];
|
||||
uint8 *rom, *ram, *rtc;
|
||||
uint rom_size, ram_size, rtc_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];
|
||||
bool patched;
|
||||
|
||||
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 spc7110rtc;
|
||||
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 rtcfn[PATH_MAX];
|
||||
char cheatfn[PATH_MAX];
|
||||
};
|
||||
|
||||
namespace memory {
|
||||
extern MappedRAM cartrom, cartram, cartrtc;
|
||||
extern MappedRAM bscram;
|
||||
extern MappedRAM stArom, stAram;
|
||||
extern MappedRAM stBrom, stBram;
|
||||
};
|
||||
|
||||
extern Cartridge cartridge;
|
||||
@@ -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,177 @@
|
||||
#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) {
|
||||
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,197 @@
|
||||
#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 rom_size = rom[index + ROM_SIZE];
|
||||
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)) {
|
||||
info.spc7110 = true;
|
||||
info.spc7110rtc = (rom_type == 0xf9);
|
||||
info.mapper = SPC7110ROM;
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && rom_type == 0xf3) {
|
||||
info.cx4 = true;
|
||||
}
|
||||
|
||||
if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x05 && company != 0xb2) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(info.dsp1 == true) {
|
||||
if((mapper & 0x2f) == 0x20 && 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 && rom_size >= 10) {
|
||||
info.st010 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0xf6 && rom_size < 10) {
|
||||
info.st011 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0xf5) {
|
||||
info.st018 = true;
|
||||
}
|
||||
|
||||
if(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 += 12;
|
||||
}
|
||||
|
||||
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,64 @@
|
||||
#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.patched = true;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if(info.srtc || info.spc7110rtc) {
|
||||
cart.rtc = new(zeromemory) uint8_t[cart.rtc_size = 20];
|
||||
if(load_file(get_save_filename(cart.fn, "rtc"), data, size, CompressionNone) == true) {
|
||||
memcpy(cart.rtc, data, min(size, cart.rtc_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);
|
||||
if(cart.rtc) save_file(get_save_filename(cart.fn, "rtc"), cart.rtc, cart.rtc_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,11 @@
|
||||
#include "bsx/bsx.h"
|
||||
#include "srtc/srtc.h"
|
||||
#include "sdd1/sdd1.h"
|
||||
#include "spc7110/spc7110.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;
|
||||
@@ -0,0 +1,110 @@
|
||||
#include "../../base.h"
|
||||
#define SDD1_CPP
|
||||
|
||||
#include "sdd1emu.cpp"
|
||||
|
||||
void SDD1::init() {}
|
||||
|
||||
void SDD1::enable() {
|
||||
for(int i = 0x4800; i <= 0x4807; i++) memory::mmio.map(i, *this);
|
||||
}
|
||||
|
||||
void SDD1::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void SDD1::reset() {
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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(regs.r4800 & (1 << channel) && regs.r4801 & (1 << channel)) {
|
||||
regs.r4801 &= ~(1 << channel);
|
||||
sdd1.dma_active = true;
|
||||
sdd1.buffer_index = 0;
|
||||
sdd1.buffer_size = length;
|
||||
sdd1emu.decompress(addr, (length) ? length : 65536, sdd1.buffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool SDD1::dma_active() {
|
||||
return sdd1.dma_active;
|
||||
}
|
||||
|
||||
uint8 SDD1::dma_read() {
|
||||
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() {}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include "sdd1emu.h"
|
||||
|
||||
class SDD1 : public MMIO {
|
||||
public:
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 mmio_read (uint addr);
|
||||
void mmio_write(uint 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;
|
||||
@@ -0,0 +1,451 @@
|
||||
#ifdef SDD1_CPP
|
||||
|
||||
/************************************************************************
|
||||
|
||||
S-DD1'algorithm emulation code
|
||||
------------------------------
|
||||
|
||||
Author: Andreas Naive
|
||||
Date: August 2003
|
||||
Last update: October 2004
|
||||
|
||||
This code is Public Domain. There is no copyright holded by the author.
|
||||
Said this, the author wish to explicitly emphasize his inalienable moral rights
|
||||
over this piece of intelectual work and the previous research that made it
|
||||
possible, as recognized by most of the copyright laws around the world.
|
||||
|
||||
This code is provided 'as-is', with no warranty, expressed or implied.
|
||||
No responsability is assumed by the author in connection with it.
|
||||
|
||||
The author is greatly indebted with The Dumper, without whose help and
|
||||
patience providing him with real S-DD1 data the research would have never been
|
||||
possible. He also wish to note that in the very beggining of his research,
|
||||
Neviksti had done some steps in the right direction. By last, the author is
|
||||
indirectly indebted to all the people that worked and contributed in the
|
||||
S-DD1 issue in the past.
|
||||
|
||||
An algorithm's documentation is available as a separate document.
|
||||
The implementation is obvious when the algorithm is
|
||||
understood.
|
||||
|
||||
************************************************************************/
|
||||
|
||||
#define SDD1_read(__addr) (bus.read(__addr))
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void SDD1_IM::prepareDecomp(uint32 in_buf) {
|
||||
|
||||
byte_ptr=in_buf;
|
||||
bit_count=4;
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
|
||||
uint8 SDD1_IM::getCodeword(uint8 code_len) {
|
||||
|
||||
uint8 codeword;
|
||||
uint8 comp_count;
|
||||
|
||||
codeword = (SDD1_read(byte_ptr))<<bit_count;
|
||||
|
||||
++bit_count;
|
||||
|
||||
if (codeword & 0x80) {
|
||||
codeword |= SDD1_read(byte_ptr+1)>>(9-bit_count);
|
||||
bit_count+=code_len;
|
||||
}
|
||||
|
||||
if (bit_count & 0x08) {
|
||||
byte_ptr++;
|
||||
bit_count&=0x07;
|
||||
}
|
||||
|
||||
return codeword;
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
|
||||
SDD1_GCD::SDD1_GCD(SDD1_IM *associatedIM) :
|
||||
IM(associatedIM)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void SDD1_GCD::getRunCount(uint8 code_num, uint8 *MPScount, bool8 *LPSind) {
|
||||
|
||||
const uint8 run_count[] = {
|
||||
0x00, 0x00, 0x01, 0x00, 0x03, 0x01, 0x02, 0x00,
|
||||
0x07, 0x03, 0x05, 0x01, 0x06, 0x02, 0x04, 0x00,
|
||||
0x0f, 0x07, 0x0b, 0x03, 0x0d, 0x05, 0x09, 0x01,
|
||||
0x0e, 0x06, 0x0a, 0x02, 0x0c, 0x04, 0x08, 0x00,
|
||||
0x1f, 0x0f, 0x17, 0x07, 0x1b, 0x0b, 0x13, 0x03,
|
||||
0x1d, 0x0d, 0x15, 0x05, 0x19, 0x09, 0x11, 0x01,
|
||||
0x1e, 0x0e, 0x16, 0x06, 0x1a, 0x0a, 0x12, 0x02,
|
||||
0x1c, 0x0c, 0x14, 0x04, 0x18, 0x08, 0x10, 0x00,
|
||||
0x3f, 0x1f, 0x2f, 0x0f, 0x37, 0x17, 0x27, 0x07,
|
||||
0x3b, 0x1b, 0x2b, 0x0b, 0x33, 0x13, 0x23, 0x03,
|
||||
0x3d, 0x1d, 0x2d, 0x0d, 0x35, 0x15, 0x25, 0x05,
|
||||
0x39, 0x19, 0x29, 0x09, 0x31, 0x11, 0x21, 0x01,
|
||||
0x3e, 0x1e, 0x2e, 0x0e, 0x36, 0x16, 0x26, 0x06,
|
||||
0x3a, 0x1a, 0x2a, 0x0a, 0x32, 0x12, 0x22, 0x02,
|
||||
0x3c, 0x1c, 0x2c, 0x0c, 0x34, 0x14, 0x24, 0x04,
|
||||
0x38, 0x18, 0x28, 0x08, 0x30, 0x10, 0x20, 0x00,
|
||||
0x7f, 0x3f, 0x5f, 0x1f, 0x6f, 0x2f, 0x4f, 0x0f,
|
||||
0x77, 0x37, 0x57, 0x17, 0x67, 0x27, 0x47, 0x07,
|
||||
0x7b, 0x3b, 0x5b, 0x1b, 0x6b, 0x2b, 0x4b, 0x0b,
|
||||
0x73, 0x33, 0x53, 0x13, 0x63, 0x23, 0x43, 0x03,
|
||||
0x7d, 0x3d, 0x5d, 0x1d, 0x6d, 0x2d, 0x4d, 0x0d,
|
||||
0x75, 0x35, 0x55, 0x15, 0x65, 0x25, 0x45, 0x05,
|
||||
0x79, 0x39, 0x59, 0x19, 0x69, 0x29, 0x49, 0x09,
|
||||
0x71, 0x31, 0x51, 0x11, 0x61, 0x21, 0x41, 0x01,
|
||||
0x7e, 0x3e, 0x5e, 0x1e, 0x6e, 0x2e, 0x4e, 0x0e,
|
||||
0x76, 0x36, 0x56, 0x16, 0x66, 0x26, 0x46, 0x06,
|
||||
0x7a, 0x3a, 0x5a, 0x1a, 0x6a, 0x2a, 0x4a, 0x0a,
|
||||
0x72, 0x32, 0x52, 0x12, 0x62, 0x22, 0x42, 0x02,
|
||||
0x7c, 0x3c, 0x5c, 0x1c, 0x6c, 0x2c, 0x4c, 0x0c,
|
||||
0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04,
|
||||
0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
|
||||
0x70, 0x30, 0x50, 0x10, 0x60, 0x20, 0x40, 0x00,
|
||||
};
|
||||
|
||||
uint8 codeword=IM->getCodeword(code_num);
|
||||
|
||||
if (codeword & 0x80) {
|
||||
*LPSind=1;
|
||||
*MPScount=run_count[codeword>>(code_num^0x07)];
|
||||
}
|
||||
else {
|
||||
*MPScount=(1<<code_num);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
SDD1_BG::SDD1_BG(SDD1_GCD *associatedGCD, uint8 code) :
|
||||
GCD(associatedGCD), code_num(code)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////
|
||||
|
||||
|
||||
void SDD1_BG::prepareDecomp(void) {
|
||||
|
||||
MPScount=0;
|
||||
LPSind=0;
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
|
||||
|
||||
uint8 SDD1_BG::getBit(bool8 *endOfRun) {
|
||||
|
||||
uint8 bit;
|
||||
|
||||
if (!(MPScount || LPSind)) GCD->getRunCount(code_num, &MPScount, &LPSind);
|
||||
|
||||
if (MPScount) {
|
||||
bit=0;
|
||||
MPScount--;
|
||||
}
|
||||
else {
|
||||
bit=1;
|
||||
LPSind=0;
|
||||
}
|
||||
|
||||
if (MPScount || LPSind) (*endOfRun)=0;
|
||||
else (*endOfRun)=1;
|
||||
|
||||
return bit;
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
|
||||
SDD1_PEM::SDD1_PEM(SDD1_BG *associatedBG0, SDD1_BG *associatedBG1,
|
||||
SDD1_BG *associatedBG2, SDD1_BG *associatedBG3,
|
||||
SDD1_BG *associatedBG4, SDD1_BG *associatedBG5,
|
||||
SDD1_BG *associatedBG6, SDD1_BG *associatedBG7) {
|
||||
|
||||
BG[0]=associatedBG0;
|
||||
BG[1]=associatedBG1;
|
||||
BG[2]=associatedBG2;
|
||||
BG[3]=associatedBG3;
|
||||
BG[4]=associatedBG4;
|
||||
BG[5]=associatedBG5;
|
||||
BG[6]=associatedBG6;
|
||||
BG[7]=associatedBG7;
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
const SDD1_PEM::state SDD1_PEM::evolution_table[]={
|
||||
{ 0,25,25},
|
||||
{ 0, 2, 1},
|
||||
{ 0, 3, 1},
|
||||
{ 0, 4, 2},
|
||||
{ 0, 5, 3},
|
||||
{ 1, 6, 4},
|
||||
{ 1, 7, 5},
|
||||
{ 1, 8, 6},
|
||||
{ 1, 9, 7},
|
||||
{ 2,10, 8},
|
||||
{ 2,11, 9},
|
||||
{ 2,12,10},
|
||||
{ 2,13,11},
|
||||
{ 3,14,12},
|
||||
{ 3,15,13},
|
||||
{ 3,16,14},
|
||||
{ 3,17,15},
|
||||
{ 4,18,16},
|
||||
{ 4,19,17},
|
||||
{ 5,20,18},
|
||||
{ 5,21,19},
|
||||
{ 6,22,20},
|
||||
{ 6,23,21},
|
||||
{ 7,24,22},
|
||||
{ 7,24,23},
|
||||
{ 0,26, 1},
|
||||
{ 1,27, 2},
|
||||
{ 2,28, 4},
|
||||
{ 3,29, 8},
|
||||
{ 4,30,12},
|
||||
{ 5,31,16},
|
||||
{ 6,32,18},
|
||||
{ 7,24,22}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void SDD1_PEM::prepareDecomp(void) {
|
||||
|
||||
for (uint8 i=0; i<32; i++) {
|
||||
contextInfo[i].status=0;
|
||||
contextInfo[i].MPS=0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
uint8 SDD1_PEM::getBit(uint8 context) {
|
||||
|
||||
bool8 endOfRun;
|
||||
uint8 bit;
|
||||
|
||||
SDD1_ContextInfo *pContInfo=&contextInfo[context];
|
||||
uint8 currStatus = pContInfo->status;
|
||||
const state *pState=&SDD1_PEM::evolution_table[currStatus];
|
||||
uint8 currentMPS=pContInfo->MPS;
|
||||
|
||||
bit=(BG[pState->code_num])->getBit(&endOfRun);
|
||||
|
||||
if (endOfRun)
|
||||
if (bit) {
|
||||
if (!(currStatus & 0xfe)) (pContInfo->MPS)^=0x01;
|
||||
(pContInfo->status)=pState->nextIfLPS;
|
||||
}
|
||||
else
|
||||
(pContInfo->status)=pState->nextIfMPS;
|
||||
|
||||
return bit^currentMPS;
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
SDD1_CM::SDD1_CM(SDD1_PEM *associatedPEM) :
|
||||
PEM(associatedPEM)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void SDD1_CM::prepareDecomp(uint32 first_byte) {
|
||||
|
||||
bitplanesInfo = SDD1_read(first_byte) & 0xc0;
|
||||
contextBitsInfo = SDD1_read(first_byte) & 0x30;
|
||||
bit_number=0;
|
||||
for (int i=0; i<8; i++) prevBitplaneBits[i]=0;
|
||||
switch (bitplanesInfo) {
|
||||
case 0x00:
|
||||
currBitplane = 1;
|
||||
break;
|
||||
case 0x40:
|
||||
currBitplane = 7;
|
||||
break;
|
||||
case 0x80:
|
||||
currBitplane = 3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
uint8 SDD1_CM::getBit(void) {
|
||||
|
||||
uint8 currContext;
|
||||
uint16 *context_bits;
|
||||
|
||||
switch (bitplanesInfo) {
|
||||
case 0x00:
|
||||
currBitplane ^= 0x01;
|
||||
break;
|
||||
case 0x40:
|
||||
currBitplane ^= 0x01;
|
||||
if (!(bit_number & 0x7f)) currBitplane = ((currBitplane+2) & 0x07);
|
||||
break;
|
||||
case 0x80:
|
||||
currBitplane ^= 0x01;
|
||||
if (!(bit_number & 0x7f)) currBitplane ^= 0x02;
|
||||
break;
|
||||
case 0xc0:
|
||||
currBitplane = bit_number & 0x07;
|
||||
}
|
||||
|
||||
context_bits = &prevBitplaneBits[currBitplane];
|
||||
|
||||
currContext=(currBitplane & 0x01)<<4;
|
||||
switch (contextBitsInfo) {
|
||||
case 0x00:
|
||||
currContext|=((*context_bits & 0x01c0)>>5)|(*context_bits & 0x0001);
|
||||
break;
|
||||
case 0x10:
|
||||
currContext|=((*context_bits & 0x0180)>>5)|(*context_bits & 0x0001);
|
||||
break;
|
||||
case 0x20:
|
||||
currContext|=((*context_bits & 0x00c0)>>5)|(*context_bits & 0x0001);
|
||||
break;
|
||||
case 0x30:
|
||||
currContext|=((*context_bits & 0x0180)>>5)|(*context_bits & 0x0003);
|
||||
}
|
||||
|
||||
uint8 bit=PEM->getBit(currContext);
|
||||
|
||||
*context_bits <<= 1;
|
||||
*context_bits |= bit;
|
||||
|
||||
bit_number++;
|
||||
|
||||
return bit;
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
SDD1_OL::SDD1_OL(SDD1_CM *associatedCM) :
|
||||
CM(associatedCM)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
|
||||
void SDD1_OL::prepareDecomp(uint32 first_byte, uint16 out_len, uint8 *out_buf) {
|
||||
|
||||
bitplanesInfo = SDD1_read(first_byte) & 0xc0;
|
||||
length=out_len;
|
||||
buffer=out_buf;
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
|
||||
void SDD1_OL::launch(void) {
|
||||
|
||||
uint8 i;
|
||||
uint8 register1, register2;
|
||||
|
||||
switch (bitplanesInfo) {
|
||||
case 0x00:
|
||||
case 0x40:
|
||||
case 0x80:
|
||||
i=1;
|
||||
do { //if length==0, we output 2^16 bytes
|
||||
if (!i) {
|
||||
*(buffer++)=register2;
|
||||
i=~i;
|
||||
}
|
||||
else {
|
||||
for (register1=register2=0, i=0x80; i; i>>=1) {
|
||||
if (CM->getBit()) register1 |= i;
|
||||
if (CM->getBit()) register2 |= i;
|
||||
}
|
||||
*(buffer++)=register1;
|
||||
}
|
||||
} while (--length);
|
||||
break;
|
||||
case 0xc0:
|
||||
do {
|
||||
for (register1=0, i=0x01; i; i<<=1) {
|
||||
if (CM->getBit()) register1 |= i;
|
||||
}
|
||||
*(buffer++)=register1;
|
||||
} while (--length);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void SDD1emu::decompress(uint32 in_buf, uint16 out_len, uint8 *out_buf) {
|
||||
|
||||
IM.prepareDecomp(in_buf);
|
||||
BG0.prepareDecomp();
|
||||
BG1.prepareDecomp();
|
||||
BG2.prepareDecomp();
|
||||
BG3.prepareDecomp();
|
||||
BG4.prepareDecomp();
|
||||
BG5.prepareDecomp();
|
||||
BG6.prepareDecomp();
|
||||
BG7.prepareDecomp();
|
||||
PEM.prepareDecomp();
|
||||
CM.prepareDecomp(in_buf);
|
||||
OL.prepareDecomp(in_buf, out_len, out_buf);
|
||||
|
||||
OL.launch();
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
SDD1emu::SDD1emu() :
|
||||
GCD(&IM),
|
||||
BG0(&GCD, 0), BG1(&GCD, 1), BG2(&GCD, 2), BG3(&GCD, 3),
|
||||
BG4(&GCD, 4), BG5(&GCD, 5), BG6(&GCD, 6), BG7(&GCD, 7),
|
||||
PEM(&BG0, &BG1, &BG2, &BG3, &BG4, &BG5, &BG6, &BG7),
|
||||
CM(&PEM),
|
||||
OL(&CM)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
#endif //ifdef SDD1_CPP
|
||||
@@ -0,0 +1,162 @@
|
||||
/************************************************************************
|
||||
|
||||
S-DD1'algorithm emulation code
|
||||
------------------------------
|
||||
|
||||
Author: Andreas Naive
|
||||
Date: August 2003
|
||||
Last update: October 2004
|
||||
|
||||
This code is Public Domain. There is no copyright holded by the author.
|
||||
Said this, the author wish to explicitly emphasize his inalienable moral rights
|
||||
over this piece of intelectual work and the previous research that made it
|
||||
possible, as recognized by most of the copyright laws around the world.
|
||||
|
||||
This code is provided 'as-is', with no warranty, expressed or implied.
|
||||
No responsability is assumed by the author in connection with it.
|
||||
|
||||
The author is greatly indebted with The Dumper, without whose help and
|
||||
patience providing him with real S-DD1 data the research would have never been
|
||||
possible. He also wish to note that in the very beggining of his research,
|
||||
Neviksti had done some steps in the right direction. By last, the author is
|
||||
indirectly indebted to all the people that worked and contributed in the
|
||||
S-DD1 issue in the past.
|
||||
|
||||
An algorithm's documentation is available as a separate document.
|
||||
The implementation is obvious when the algorithm is
|
||||
understood.
|
||||
|
||||
************************************************************************/
|
||||
|
||||
typedef uint8_t bool8;
|
||||
|
||||
class SDD1_IM { //Input Manager
|
||||
|
||||
public:
|
||||
SDD1_IM(void) {}
|
||||
void prepareDecomp(uint32 in_buf);
|
||||
uint8 getCodeword(const uint8 code_len);
|
||||
|
||||
private:
|
||||
uint32 byte_ptr;
|
||||
uint8 bit_count;
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class SDD1_GCD { //Golomb-Code Decoder
|
||||
|
||||
public:
|
||||
SDD1_GCD(SDD1_IM *associatedIM);
|
||||
void getRunCount(uint8 code_num, uint8 *MPScount, bool8 *LPSind);
|
||||
|
||||
private:
|
||||
SDD1_IM *const IM;
|
||||
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class SDD1_BG { // Bits Generator
|
||||
|
||||
public:
|
||||
SDD1_BG(SDD1_GCD *associatedGCD, uint8 code);
|
||||
void prepareDecomp(void);
|
||||
uint8 getBit(bool8 *endOfRun);
|
||||
|
||||
private:
|
||||
const uint8 code_num;
|
||||
uint8 MPScount;
|
||||
bool8 LPSind;
|
||||
SDD1_GCD *const GCD;
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////
|
||||
|
||||
|
||||
class SDD1_PEM { //Probability Estimation Module
|
||||
|
||||
public:
|
||||
SDD1_PEM(SDD1_BG *associatedBG0, SDD1_BG *associatedBG1,
|
||||
SDD1_BG *associatedBG2, SDD1_BG *associatedBG3,
|
||||
SDD1_BG *associatedBG4, SDD1_BG *associatedBG5,
|
||||
SDD1_BG *associatedBG6, SDD1_BG *associatedBG7);
|
||||
void prepareDecomp(void);
|
||||
uint8 getBit(uint8 context);
|
||||
|
||||
private:
|
||||
struct state {
|
||||
uint8 code_num;
|
||||
uint8 nextIfMPS;
|
||||
uint8 nextIfLPS;
|
||||
};
|
||||
static const state evolution_table[];
|
||||
struct SDD1_ContextInfo {
|
||||
uint8 status;
|
||||
uint8 MPS;
|
||||
} contextInfo[32];
|
||||
SDD1_BG * BG[8];
|
||||
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
|
||||
class SDD1_CM { //Context Model
|
||||
|
||||
public:
|
||||
SDD1_CM(SDD1_PEM *associatedPEM);
|
||||
void prepareDecomp(uint32 first_byte);
|
||||
uint8 getBit(void);
|
||||
|
||||
private:
|
||||
uint8 bitplanesInfo;
|
||||
uint8 contextBitsInfo;
|
||||
uint8 bit_number;
|
||||
uint8 currBitplane;
|
||||
uint16 prevBitplaneBits[8];
|
||||
SDD1_PEM *const PEM;
|
||||
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
|
||||
class SDD1_OL { //Output Logic
|
||||
|
||||
public:
|
||||
SDD1_OL(SDD1_CM *associatedCM);
|
||||
void prepareDecomp(uint32 first_byte, uint16 out_len, uint8 *out_buf);
|
||||
void launch(void);
|
||||
|
||||
private:
|
||||
uint8 bitplanesInfo;
|
||||
uint16 length;
|
||||
uint8 *buffer;
|
||||
SDD1_CM *const CM;
|
||||
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class SDD1emu {
|
||||
|
||||
public:
|
||||
SDD1emu(void);
|
||||
void decompress(uint32 in_buf, uint16 out_len, uint8 *out_buf);
|
||||
|
||||
private:
|
||||
SDD1_IM IM;
|
||||
SDD1_GCD GCD;
|
||||
SDD1_BG BG0; SDD1_BG BG1; SDD1_BG BG2; SDD1_BG BG3;
|
||||
SDD1_BG BG4; SDD1_BG BG5; SDD1_BG BG6; SDD1_BG BG7;
|
||||
SDD1_PEM PEM;
|
||||
SDD1_CM CM;
|
||||
SDD1_OL OL;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,511 @@
|
||||
#ifdef SPC7110_CPP
|
||||
|
||||
uint8 SPC7110Decomp::read() {
|
||||
if(decomp_buffer_length == 0) {
|
||||
//decompress at least (decomp_buffer_size / 2) bytes to the buffer
|
||||
switch(decomp_mode) {
|
||||
case 0: mode0(false); break;
|
||||
case 1: mode1(false); break;
|
||||
case 2: mode2(false); break;
|
||||
default: return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 data = decomp_buffer[decomp_buffer_rdoffset++];
|
||||
decomp_buffer_rdoffset &= decomp_buffer_size - 1;
|
||||
decomp_buffer_length--;
|
||||
return data;
|
||||
}
|
||||
|
||||
void SPC7110Decomp::write(uint8 data) {
|
||||
decomp_buffer[decomp_buffer_wroffset++] = data;
|
||||
decomp_buffer_wroffset &= decomp_buffer_size - 1;
|
||||
decomp_buffer_length++;
|
||||
}
|
||||
|
||||
uint8 SPC7110Decomp::dataread() {
|
||||
unsigned size = memory::cartrom.size() - 0x100000;
|
||||
while(decomp_offset >= size) decomp_offset -= size;
|
||||
return memory::cartrom.read(0x100000 + decomp_offset++);
|
||||
}
|
||||
|
||||
void SPC7110Decomp::init(unsigned mode, unsigned offset, unsigned index) {
|
||||
decomp_mode = mode;
|
||||
decomp_offset = offset;
|
||||
|
||||
decomp_buffer_rdoffset = 0;
|
||||
decomp_buffer_wroffset = 0;
|
||||
decomp_buffer_length = 0;
|
||||
|
||||
//reset context states
|
||||
for(unsigned i = 0; i < 32; i++) {
|
||||
context[i].index = 0;
|
||||
context[i].invert = 0;
|
||||
}
|
||||
|
||||
switch(decomp_mode) {
|
||||
case 0: mode0(true); break;
|
||||
case 1: mode1(true); break;
|
||||
case 2: mode2(true); break;
|
||||
}
|
||||
|
||||
//decompress up to requested output data index
|
||||
while(index--) read();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void SPC7110Decomp::mode0(bool init) {
|
||||
static uint8 val, in, span;
|
||||
static int out, inverts, lps, in_count;
|
||||
|
||||
if(init == true) {
|
||||
out = inverts = lps = 0;
|
||||
span = 0xff;
|
||||
val = dataread();
|
||||
in = dataread();
|
||||
in_count = 8;
|
||||
return;
|
||||
}
|
||||
|
||||
while(decomp_buffer_length < (decomp_buffer_size >> 1)) {
|
||||
for(unsigned bit = 0; bit < 8; bit++) {
|
||||
//get context
|
||||
uint8 mask = (1 << (bit & 3)) - 1;
|
||||
uint8 con = mask + ((inverts & mask) ^ (lps & mask));
|
||||
if(bit > 3) con += 15;
|
||||
|
||||
//get prob and mps
|
||||
unsigned prob = probability(con);
|
||||
unsigned mps = (((out >> 15) & 1) ^ context[con].invert);
|
||||
|
||||
//get bit
|
||||
unsigned flag_lps;
|
||||
if(val <= span - prob) { //mps
|
||||
span = span - prob;
|
||||
out = (out << 1) + mps;
|
||||
flag_lps = 0;
|
||||
} else { //lps
|
||||
val = val - (span - (prob - 1));
|
||||
span = prob - 1;
|
||||
out = (out << 1) + 1 - mps;
|
||||
flag_lps = 1;
|
||||
}
|
||||
|
||||
//renormalize
|
||||
unsigned shift = 0;
|
||||
while(span < 0x7f) {
|
||||
shift++;
|
||||
|
||||
span = (span << 1) + 1;
|
||||
val = (val << 1) + (in >> 7);
|
||||
|
||||
in <<= 1;
|
||||
if(--in_count == 0) {
|
||||
in = dataread();
|
||||
in_count = 8;
|
||||
}
|
||||
}
|
||||
|
||||
//update processing info
|
||||
lps = (lps << 1) + flag_lps;
|
||||
inverts = (inverts << 1) + context[con].invert;
|
||||
|
||||
//update context state
|
||||
if(flag_lps & toggle_invert(con)) context[con].invert ^= 1;
|
||||
if(flag_lps) context[con].index = next_lps(con);
|
||||
else if(shift) context[con].index = next_mps(con);
|
||||
}
|
||||
|
||||
//save byte
|
||||
write(out);
|
||||
}
|
||||
}
|
||||
|
||||
void SPC7110Decomp::mode1(bool init) {
|
||||
static int pixelorder[4], realorder[4];
|
||||
static uint8 in, val, span;
|
||||
static int out, inverts, lps, in_count;
|
||||
|
||||
if(init == true) {
|
||||
for(unsigned i = 0; i < 4; i++) pixelorder[i] = i;
|
||||
out = inverts = lps = 0;
|
||||
span = 0xff;
|
||||
val = dataread();
|
||||
in = dataread();
|
||||
in_count = 8;
|
||||
return;
|
||||
}
|
||||
|
||||
while(decomp_buffer_length < (decomp_buffer_size >> 1)) {
|
||||
for(unsigned pixel = 0; pixel < 8; pixel++) {
|
||||
//get first symbol context
|
||||
unsigned a = ((out >> (1 * 2)) & 3);
|
||||
unsigned b = ((out >> (7 * 2)) & 3);
|
||||
unsigned c = ((out >> (8 * 2)) & 3);
|
||||
unsigned con = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c);
|
||||
|
||||
//update pixel order
|
||||
unsigned m, n;
|
||||
for(m = 0; m < 4; m++) if(pixelorder[m] == a) break;
|
||||
for(n = m; n > 0; n--) pixelorder[n] = pixelorder[n - 1];
|
||||
pixelorder[0] = a;
|
||||
|
||||
//calculate the real pixel order
|
||||
for(m = 0; m < 4; m++) realorder[m] = pixelorder[m];
|
||||
|
||||
//rotate reference pixel c value to top
|
||||
for(m = 0; m < 4; m++) if(realorder[m] == c) break;
|
||||
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
||||
realorder[0] = c;
|
||||
|
||||
//rotate reference pixel b value to top
|
||||
for(m = 0; m < 4; m++) if(realorder[m] == b) break;
|
||||
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
||||
realorder[0] = b;
|
||||
|
||||
//rotate reference pixel a value to top
|
||||
for(m = 0; m < 4; m++) if(realorder[m] == a) break;
|
||||
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
||||
realorder[0] = a;
|
||||
|
||||
//get 2 symbols
|
||||
for(unsigned bit = 0; bit < 2; bit++) {
|
||||
//get prob
|
||||
unsigned prob = probability(con);
|
||||
|
||||
//get symbol
|
||||
unsigned flag_lps;
|
||||
if(val <= span - prob) { //mps
|
||||
span = span - prob;
|
||||
flag_lps = 0;
|
||||
} else { //lps
|
||||
val = val - (span - (prob - 1));
|
||||
span = prob - 1;
|
||||
flag_lps = 1;
|
||||
}
|
||||
|
||||
//renormalize
|
||||
unsigned shift = 0;
|
||||
while(span < 0x7f) {
|
||||
shift++;
|
||||
|
||||
span = (span << 1) + 1;
|
||||
val = (val << 1) + (in >> 7);
|
||||
|
||||
in <<= 1;
|
||||
if(--in_count == 0) {
|
||||
in = dataread();
|
||||
in_count = 8;
|
||||
}
|
||||
}
|
||||
|
||||
//update processing info
|
||||
lps = (lps << 1) + flag_lps;
|
||||
inverts = (inverts << 1) + context[con].invert;
|
||||
|
||||
//update context state
|
||||
if(flag_lps & toggle_invert(con)) context[con].invert ^= 1;
|
||||
if(flag_lps) context[con].index = next_lps(con);
|
||||
else if(shift) context[con].index = next_mps(con);
|
||||
|
||||
//get next context
|
||||
con = 5 + (con << 1) + ((lps ^ inverts) & 1);
|
||||
}
|
||||
|
||||
//get pixel
|
||||
b = realorder[(lps ^ inverts) & 3];
|
||||
out = (out << 2) + b;
|
||||
}
|
||||
|
||||
//turn pixel data into bitplanes
|
||||
unsigned data = morton_2x8(out);
|
||||
write(data >> 8);
|
||||
write(data >> 0);
|
||||
}
|
||||
}
|
||||
|
||||
void SPC7110Decomp::mode2(bool init) {
|
||||
static int pixelorder[16], realorder[16];
|
||||
static uint8 bitplanebuffer[16], buffer_index;
|
||||
static uint8 in, val, span;
|
||||
static int out0, out1, inverts, lps, in_count;
|
||||
|
||||
if(init == true) {
|
||||
for(unsigned i = 0; i < 16; i++) pixelorder[i] = i;
|
||||
buffer_index = 0;
|
||||
out0 = out1 = inverts = lps = 0;
|
||||
span = 0xff;
|
||||
val = dataread();
|
||||
in = dataread();
|
||||
in_count = 8;
|
||||
return;
|
||||
}
|
||||
|
||||
while(decomp_buffer_length < (decomp_buffer_size >> 1)) {
|
||||
for(unsigned pixel = 0; pixel < 8; pixel++) {
|
||||
//get first symbol context
|
||||
unsigned a = ((out0 >> (0 * 4)) & 15);
|
||||
unsigned b = ((out0 >> (7 * 4)) & 15);
|
||||
unsigned c = ((out1 >> (0 * 4)) & 15);
|
||||
unsigned con = 0;
|
||||
unsigned refcon = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c);
|
||||
|
||||
//update pixel order
|
||||
unsigned m, n;
|
||||
for(m = 0; m < 16; m++) if(pixelorder[m] == a) break;
|
||||
for(n = m; n > 0; n--) pixelorder[n] = pixelorder[n - 1];
|
||||
pixelorder[0] = a;
|
||||
|
||||
//calculate the real pixel order
|
||||
for(m = 0; m < 16; m++) realorder[m] = pixelorder[m];
|
||||
|
||||
//rotate reference pixel c value to top
|
||||
for(m = 0; m < 16; m++) if(realorder[m] == c) break;
|
||||
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
||||
realorder[0] = c;
|
||||
|
||||
//rotate reference pixel b value to top
|
||||
for(m = 0; m < 16; m++) if(realorder[m] == b) break;
|
||||
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
||||
realorder[0] = b;
|
||||
|
||||
//rotate reference pixel a value to top
|
||||
for(m = 0; m < 16; m++) if(realorder[m] == a) break;
|
||||
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
||||
realorder[0] = a;
|
||||
|
||||
//get 4 symbols
|
||||
for(unsigned bit = 0; bit < 4; bit++) {
|
||||
//get prob
|
||||
unsigned prob = probability(con);
|
||||
|
||||
//get symbol
|
||||
unsigned flag_lps;
|
||||
if(val <= span - prob) { //mps
|
||||
span = span - prob;
|
||||
flag_lps = 0;
|
||||
} else { //lps
|
||||
val = val - (span - (prob - 1));
|
||||
span = prob - 1;
|
||||
flag_lps = 1;
|
||||
}
|
||||
|
||||
//renormalize
|
||||
unsigned shift = 0;
|
||||
while(span < 0x7f) {
|
||||
shift++;
|
||||
|
||||
span = (span << 1) + 1;
|
||||
val = (val << 1) + (in >> 7);
|
||||
|
||||
in <<= 1;
|
||||
if(--in_count == 0) {
|
||||
in = dataread();
|
||||
in_count = 8;
|
||||
}
|
||||
}
|
||||
|
||||
//update processing info
|
||||
lps = (lps << 1) + flag_lps;
|
||||
unsigned invertbit = context[con].invert;
|
||||
inverts = (inverts << 1) + invertbit;
|
||||
|
||||
//update context state
|
||||
if(flag_lps & toggle_invert(con)) context[con].invert ^= 1;
|
||||
if(flag_lps) context[con].index = next_lps(con);
|
||||
else if(shift) context[con].index = next_mps(con);
|
||||
|
||||
//get next context
|
||||
con = mode2_context_table[con][flag_lps ^ invertbit] + (con == 1 ? refcon : 0);
|
||||
}
|
||||
|
||||
//get pixel
|
||||
b = realorder[(lps ^ inverts) & 0x0f];
|
||||
out1 = (out1 << 4) + ((out0 >> 28) & 0x0f);
|
||||
out0 = (out0 << 4) + b;
|
||||
}
|
||||
|
||||
//convert pixel data into bitplanes
|
||||
unsigned data = morton_4x8(out0);
|
||||
write(data >> 24);
|
||||
write(data >> 16);
|
||||
bitplanebuffer[buffer_index++] = data >> 8;
|
||||
bitplanebuffer[buffer_index++] = data >> 0;
|
||||
|
||||
if(buffer_index == 16) {
|
||||
for(unsigned i = 0; i < 16; i++) write(bitplanebuffer[i]);
|
||||
buffer_index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
const uint8 SPC7110Decomp::evolution_table[53][4] = {
|
||||
//{ prob, nextlps, nextmps, toggle invert },
|
||||
|
||||
{ 0x5a, 1, 1, 1 },
|
||||
{ 0x25, 6, 2, 0 },
|
||||
{ 0x11, 8, 3, 0 },
|
||||
{ 0x08, 10, 4, 0 },
|
||||
{ 0x03, 12, 5, 0 },
|
||||
{ 0x01, 15, 5, 0 },
|
||||
|
||||
{ 0x5a, 7, 7, 1 },
|
||||
{ 0x3f, 19, 8, 0 },
|
||||
{ 0x2c, 21, 9, 0 },
|
||||
{ 0x20, 22, 10, 0 },
|
||||
{ 0x17, 23, 11, 0 },
|
||||
{ 0x11, 25, 12, 0 },
|
||||
{ 0x0c, 26, 13, 0 },
|
||||
{ 0x09, 28, 14, 0 },
|
||||
{ 0x07, 29, 15, 0 },
|
||||
{ 0x05, 31, 16, 0 },
|
||||
{ 0x04, 32, 17, 0 },
|
||||
{ 0x03, 34, 18, 0 },
|
||||
{ 0x02, 35, 5, 0 },
|
||||
|
||||
{ 0x5a, 20, 20, 1 },
|
||||
{ 0x48, 39, 21, 0 },
|
||||
{ 0x3a, 40, 22, 0 },
|
||||
{ 0x2e, 42, 23, 0 },
|
||||
{ 0x26, 44, 24, 0 },
|
||||
{ 0x1f, 45, 25, 0 },
|
||||
{ 0x19, 46, 26, 0 },
|
||||
{ 0x15, 25, 27, 0 },
|
||||
{ 0x11, 26, 28, 0 },
|
||||
{ 0x0e, 26, 29, 0 },
|
||||
{ 0x0b, 27, 30, 0 },
|
||||
{ 0x09, 28, 31, 0 },
|
||||
{ 0x08, 29, 32, 0 },
|
||||
{ 0x07, 30, 33, 0 },
|
||||
{ 0x05, 31, 34, 0 },
|
||||
{ 0x04, 33, 35, 0 },
|
||||
{ 0x04, 33, 36, 0 },
|
||||
{ 0x03, 34, 37, 0 },
|
||||
{ 0x02, 35, 38, 0 },
|
||||
{ 0x02, 36, 5, 0 },
|
||||
|
||||
{ 0x58, 39, 40, 1 },
|
||||
{ 0x4d, 47, 41, 0 },
|
||||
{ 0x43, 48, 42, 0 },
|
||||
{ 0x3b, 49, 43, 0 },
|
||||
{ 0x34, 50, 44, 0 },
|
||||
{ 0x2e, 51, 45, 0 },
|
||||
{ 0x29, 44, 46, 0 },
|
||||
{ 0x25, 45, 24, 0 },
|
||||
|
||||
{ 0x56, 47, 48, 1 },
|
||||
{ 0x4f, 47, 49, 0 },
|
||||
{ 0x47, 48, 50, 0 },
|
||||
{ 0x41, 49, 51, 0 },
|
||||
{ 0x3c, 50, 52, 0 },
|
||||
{ 0x37, 51, 43, 0 },
|
||||
};
|
||||
|
||||
const uint8 SPC7110Decomp::mode2_context_table[32][2] = {
|
||||
//{ next 0, next 1 },
|
||||
|
||||
{ 1, 2 },
|
||||
|
||||
{ 3, 8 },
|
||||
{ 13, 14 },
|
||||
|
||||
{ 15, 16 },
|
||||
{ 17, 18 },
|
||||
{ 19, 20 },
|
||||
{ 21, 22 },
|
||||
{ 23, 24 },
|
||||
{ 25, 26 },
|
||||
{ 25, 26 },
|
||||
{ 25, 26 },
|
||||
{ 25, 26 },
|
||||
{ 25, 26 },
|
||||
{ 27, 28 },
|
||||
{ 29, 30 },
|
||||
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
|
||||
{ 31, 31 },
|
||||
};
|
||||
|
||||
uint8 SPC7110Decomp::probability (unsigned n) { return evolution_table[context[n].index][0]; }
|
||||
uint8 SPC7110Decomp::next_lps (unsigned n) { return evolution_table[context[n].index][1]; }
|
||||
uint8 SPC7110Decomp::next_mps (unsigned n) { return evolution_table[context[n].index][2]; }
|
||||
bool SPC7110Decomp::toggle_invert(unsigned n) { return evolution_table[context[n].index][3]; }
|
||||
|
||||
unsigned SPC7110Decomp::morton_2x8(unsigned data) {
|
||||
//reverse morton lookup: de-interleave two 8-bit values
|
||||
//15, 13, 11, 9, 7, 5, 3, 1 -> 15- 8
|
||||
//14, 12, 10, 8, 6, 4, 2, 0 -> 7- 0
|
||||
return morton16[0][(data >> 0) & 255] + morton16[1][(data >> 8) & 255];
|
||||
}
|
||||
|
||||
unsigned SPC7110Decomp::morton_4x8(unsigned data) {
|
||||
//reverse morton lookup: de-interleave four 8-bit values
|
||||
//31, 27, 23, 19, 15, 11, 7, 3 -> 31-24
|
||||
//30, 26, 22, 18, 14, 10, 6, 2 -> 23-16
|
||||
//29, 25, 21, 17, 13, 9, 5, 1 -> 15- 8
|
||||
//28, 24, 20, 16, 12, 8, 4, 0 -> 7- 0
|
||||
return morton32[0][(data >> 0) & 255] + morton32[1][(data >> 8) & 255]
|
||||
+ morton32[2][(data >> 16) & 255] + morton32[3][(data >> 24) & 255];
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void SPC7110Decomp::reset() {
|
||||
//mode 3 is invalid; this is treated as a special case to always return 0x00
|
||||
//set to mode 3 so that reading decomp port before starting first decomp will return 0x00
|
||||
decomp_mode = 3;
|
||||
|
||||
decomp_buffer_rdoffset = 0;
|
||||
decomp_buffer_wroffset = 0;
|
||||
decomp_buffer_length = 0;
|
||||
}
|
||||
|
||||
SPC7110Decomp::SPC7110Decomp() {
|
||||
decomp_buffer = new uint8_t[decomp_buffer_size];
|
||||
reset();
|
||||
|
||||
//initialize reverse morton lookup tables
|
||||
for(unsigned i = 0; i < 256; i++) {
|
||||
#define map(x, y) (((i >> x) & 1) << y)
|
||||
//2x8-bit
|
||||
morton16[1][i] = map(7, 15) + map(6, 7) + map(5, 14) + map(4, 6)
|
||||
+ map(3, 13) + map(2, 5) + map(1, 12) + map(0, 4);
|
||||
morton16[0][i] = map(7, 11) + map(6, 3) + map(5, 10) + map(4, 2)
|
||||
+ map(3, 9) + map(2, 1) + map(1, 8) + map(0, 0);
|
||||
//4x8-bit
|
||||
morton32[3][i] = map(7, 31) + map(6, 23) + map(5, 15) + map(4, 7)
|
||||
+ map(3, 30) + map(2, 22) + map(1, 14) + map(0, 6);
|
||||
morton32[2][i] = map(7, 29) + map(6, 21) + map(5, 13) + map(4, 5)
|
||||
+ map(3, 28) + map(2, 20) + map(1, 12) + map(0, 4);
|
||||
morton32[1][i] = map(7, 27) + map(6, 19) + map(5, 11) + map(4, 3)
|
||||
+ map(3, 26) + map(2, 18) + map(1, 10) + map(0, 2);
|
||||
morton32[0][i] = map(7, 25) + map(6, 17) + map(5, 9) + map(4, 1)
|
||||
+ map(3, 24) + map(2, 16) + map(1, 8) + map(0, 0);
|
||||
#undef map
|
||||
}
|
||||
}
|
||||
|
||||
SPC7110Decomp::~SPC7110Decomp() {
|
||||
delete[] decomp_buffer;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
class SPC7110Decomp {
|
||||
public:
|
||||
uint8 read();
|
||||
void init(unsigned mode, unsigned offset, unsigned index);
|
||||
void reset();
|
||||
|
||||
SPC7110Decomp();
|
||||
~SPC7110Decomp();
|
||||
|
||||
private:
|
||||
unsigned decomp_mode;
|
||||
unsigned decomp_offset;
|
||||
|
||||
//read() will spool chunks half the size of decomp_buffer_size
|
||||
enum { decomp_buffer_size = 64 }; //must be >= 64, and must be a power of two
|
||||
uint8 *decomp_buffer;
|
||||
unsigned decomp_buffer_rdoffset;
|
||||
unsigned decomp_buffer_wroffset;
|
||||
unsigned decomp_buffer_length;
|
||||
|
||||
void write(uint8 data);
|
||||
uint8 dataread();
|
||||
|
||||
void mode0(bool init);
|
||||
void mode1(bool init);
|
||||
void mode2(bool init);
|
||||
|
||||
static const uint8 evolution_table[53][4];
|
||||
static const uint8 mode2_context_table[32][2];
|
||||
|
||||
struct ContextState {
|
||||
uint8 index;
|
||||
uint8 invert;
|
||||
} context[32];
|
||||
|
||||
uint8 probability(unsigned n);
|
||||
uint8 next_lps(unsigned n);
|
||||
uint8 next_mps(unsigned n);
|
||||
bool toggle_invert(unsigned n);
|
||||
|
||||
unsigned morton16[2][256];
|
||||
unsigned morton32[4][256];
|
||||
unsigned morton_2x8(unsigned data);
|
||||
unsigned morton_4x8(unsigned data);
|
||||
};
|
||||
@@ -0,0 +1,658 @@
|
||||
#include "../../base.h"
|
||||
#define SPC7110_CPP
|
||||
|
||||
#include "decomp.cpp"
|
||||
|
||||
const unsigned SPC7110::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
void SPC7110::init() {}
|
||||
|
||||
void SPC7110::enable() {
|
||||
uint16_t limit = (cartridge.info.spc7110rtc ? 0x4842 : 0x483f);
|
||||
for(uint16_t i = 0x4800; i <= limit; i++) memory::mmio.map(i, *this);
|
||||
}
|
||||
|
||||
void SPC7110::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void SPC7110::reset() {
|
||||
r4801 = 0x00;
|
||||
r4802 = 0x00;
|
||||
r4803 = 0x00;
|
||||
r4804 = 0x00;
|
||||
r4805 = 0x00;
|
||||
r4806 = 0x00;
|
||||
r4807 = 0x00;
|
||||
r4808 = 0x00;
|
||||
r4809 = 0x00;
|
||||
r480a = 0x00;
|
||||
r480b = 0x00;
|
||||
r480c = 0x00;
|
||||
|
||||
decomp.reset();
|
||||
|
||||
r4811 = 0x00;
|
||||
r4812 = 0x00;
|
||||
r4813 = 0x00;
|
||||
r4814 = 0x00;
|
||||
r4815 = 0x00;
|
||||
r4816 = 0x00;
|
||||
r4817 = 0x00;
|
||||
r4818 = 0x00;
|
||||
|
||||
r481x = 0x00;
|
||||
r4814_latch = false;
|
||||
r4815_latch = false;
|
||||
|
||||
r4820 = 0x00;
|
||||
r4821 = 0x00;
|
||||
r4822 = 0x00;
|
||||
r4823 = 0x00;
|
||||
r4824 = 0x00;
|
||||
r4825 = 0x00;
|
||||
r4826 = 0x00;
|
||||
r4827 = 0x00;
|
||||
r4828 = 0x00;
|
||||
r4829 = 0x00;
|
||||
r482a = 0x00;
|
||||
r482b = 0x00;
|
||||
r482c = 0x00;
|
||||
r482d = 0x00;
|
||||
r482e = 0x00;
|
||||
r482f = 0x00;
|
||||
|
||||
r4830 = 0x00;
|
||||
mmio_write(0x4831, 0);
|
||||
mmio_write(0x4832, 1);
|
||||
mmio_write(0x4833, 2);
|
||||
r4834 = 0x00;
|
||||
|
||||
r4840 = 0x00;
|
||||
r4841 = 0x00;
|
||||
r4842 = 0x00;
|
||||
|
||||
if(cartridge.info.spc7110rtc) {
|
||||
rtc_state = RTCS_Inactive;
|
||||
rtc_mode = RTCM_Linear;
|
||||
rtc_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned SPC7110::datarom_addr(unsigned addr) {
|
||||
unsigned size = memory::cartrom.size() - 0x100000;
|
||||
while(addr >= size) addr -= size;
|
||||
return addr + 0x100000;
|
||||
}
|
||||
|
||||
unsigned SPC7110::data_pointer() { return r4811 + (r4812 << 8) + (r4813 << 16); }
|
||||
unsigned SPC7110::data_adjust() { return r4814 + (r4815 << 8); }
|
||||
unsigned SPC7110::data_increment() { return r4816 + (r4817 << 8); }
|
||||
void SPC7110::set_data_pointer(unsigned addr) { r4811 = addr; r4812 = addr >> 8; r4813 = addr >> 16; }
|
||||
void SPC7110::set_data_adjust(unsigned addr) { r4814 = addr; r4815 = addr >> 8; }
|
||||
|
||||
void SPC7110::update_time(int offset) {
|
||||
time_t rtc_time;
|
||||
rtc_time = memory::cartrtc.read(16);
|
||||
rtc_time |= memory::cartrtc.read(17) << 8;
|
||||
rtc_time |= memory::cartrtc.read(18) << 16;
|
||||
rtc_time |= memory::cartrtc.read(19) << 24;
|
||||
|
||||
bool update = true;
|
||||
if(memory::cartrtc.read(13) & 1) update = false; //do not update if CR0 timer disable flag is set
|
||||
if(memory::cartrtc.read(15) & 3) update = false; //do not update if CR2 timer disable flags are set
|
||||
|
||||
time_t current_time = time(0) - offset;
|
||||
if(update && current_time > rtc_time) {
|
||||
unsigned second = memory::cartrtc.read( 0) + memory::cartrtc.read( 1) * 10;
|
||||
unsigned minute = memory::cartrtc.read( 2) + memory::cartrtc.read( 3) * 10;
|
||||
unsigned hour = memory::cartrtc.read( 4) + memory::cartrtc.read( 5) * 10;
|
||||
unsigned day = memory::cartrtc.read( 6) + memory::cartrtc.read( 7) * 10;
|
||||
unsigned month = memory::cartrtc.read( 8) + memory::cartrtc.read( 9) * 10;
|
||||
unsigned year = memory::cartrtc.read(10) + memory::cartrtc.read(11) * 10;
|
||||
unsigned weekday = memory::cartrtc.read(12);
|
||||
|
||||
day--;
|
||||
month--;
|
||||
year += (year >= 90) ? 1900 : 2000; //range = 1990-2089
|
||||
|
||||
second += (unsigned)(current_time - rtc_time);
|
||||
while(second >= 60) {
|
||||
second -= 60;
|
||||
|
||||
minute++;
|
||||
if(minute < 60) continue;
|
||||
minute = 0;
|
||||
|
||||
hour++;
|
||||
if(hour < 24) continue;
|
||||
hour = 0;
|
||||
|
||||
day++;
|
||||
weekday = (weekday + 1) % 7;
|
||||
unsigned days = months[month % 12];
|
||||
if(days == 28) {
|
||||
bool leapyear = false;
|
||||
if((year % 4) == 0) {
|
||||
leapyear = true;
|
||||
if((year % 100) == 0 && (year % 400) != 0) leapyear = false;
|
||||
}
|
||||
if(leapyear) days++;
|
||||
}
|
||||
if(day < days) continue;
|
||||
day = 0;
|
||||
|
||||
month++;
|
||||
if(month < 12) continue;
|
||||
month = 0;
|
||||
|
||||
year++;
|
||||
}
|
||||
|
||||
day++;
|
||||
month++;
|
||||
year %= 100;
|
||||
|
||||
memory::cartrtc.write( 0, second % 10);
|
||||
memory::cartrtc.write( 1, second / 10);
|
||||
memory::cartrtc.write( 2, minute % 10);
|
||||
memory::cartrtc.write( 3, minute / 10);
|
||||
memory::cartrtc.write( 4, hour % 10);
|
||||
memory::cartrtc.write( 5, hour / 10);
|
||||
memory::cartrtc.write( 6, day % 10);
|
||||
memory::cartrtc.write( 7, day / 10);
|
||||
memory::cartrtc.write( 8, month % 10);
|
||||
memory::cartrtc.write( 9, month / 10);
|
||||
memory::cartrtc.write(10, year % 10);
|
||||
memory::cartrtc.write(11, (year / 10) % 10);
|
||||
memory::cartrtc.write(12, weekday % 7);
|
||||
}
|
||||
|
||||
memory::cartrtc.write(16, current_time);
|
||||
memory::cartrtc.write(17, current_time >> 8);
|
||||
memory::cartrtc.write(18, current_time >> 16);
|
||||
memory::cartrtc.write(19, current_time >> 24);
|
||||
}
|
||||
|
||||
uint8 SPC7110::mmio_read(uint addr) {
|
||||
addr &= 0xffff;
|
||||
|
||||
switch(addr) {
|
||||
//==================
|
||||
//decompression unit
|
||||
//==================
|
||||
|
||||
case 0x4800: {
|
||||
uint16 counter = (r4809 + (r480a << 8));
|
||||
counter--;
|
||||
r4809 = counter;
|
||||
r480a = counter >> 8;
|
||||
return decomp.read();
|
||||
}
|
||||
case 0x4801: return r4801;
|
||||
case 0x4802: return r4802;
|
||||
case 0x4803: return r4803;
|
||||
case 0x4804: return r4804;
|
||||
case 0x4805: return r4805;
|
||||
case 0x4806: return r4806;
|
||||
case 0x4807: return r4807;
|
||||
case 0x4808: return r4808;
|
||||
case 0x4809: return r4809;
|
||||
case 0x480a: return r480a;
|
||||
case 0x480b: return r480b;
|
||||
case 0x480c: {
|
||||
uint8 status = r480c;
|
||||
r480c &= 0x7f;
|
||||
return status;
|
||||
}
|
||||
|
||||
//==============
|
||||
//data port unit
|
||||
//==============
|
||||
|
||||
case 0x4810: {
|
||||
if(r481x != 0x07) return 0x00;
|
||||
|
||||
unsigned addr = data_pointer();
|
||||
unsigned adjust = data_adjust();
|
||||
if(r4818 & 8) adjust = (int16)adjust; //16-bit sign extend
|
||||
|
||||
unsigned adjustaddr = addr;
|
||||
if(r4818 & 2) {
|
||||
adjustaddr += adjust;
|
||||
set_data_adjust(adjust + 1);
|
||||
}
|
||||
|
||||
uint8 data = memory::cartrom.read(datarom_addr(adjustaddr));
|
||||
if(!(r4818 & 2)) {
|
||||
unsigned increment = (r4818 & 1) ? data_increment() : 1;
|
||||
if(r4818 & 4) increment = (int16)increment; //16-bit sign extend
|
||||
|
||||
if((r4818 & 16) == 0) {
|
||||
set_data_pointer(addr + increment);
|
||||
} else {
|
||||
set_data_adjust(adjust + increment);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
case 0x4811: return r4811;
|
||||
case 0x4812: return r4812;
|
||||
case 0x4813: return r4813;
|
||||
case 0x4814: return r4814;
|
||||
case 0x4815: return r4815;
|
||||
case 0x4816: return r4816;
|
||||
case 0x4817: return r4817;
|
||||
case 0x4818: return r4818;
|
||||
case 0x481a: {
|
||||
if(r481x != 0x07) return 0x00;
|
||||
|
||||
unsigned addr = data_pointer();
|
||||
unsigned adjust = data_adjust();
|
||||
if(r4818 & 8) adjust = (int16)adjust; //16-bit sign extend
|
||||
|
||||
uint8 data = memory::cartrom.read(datarom_addr(addr + adjust));
|
||||
if((r4818 & 0x60) == 0x60) {
|
||||
if((r4818 & 16) == 0) {
|
||||
set_data_pointer(addr + adjust);
|
||||
} else {
|
||||
set_data_adjust(adjust + adjust);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//=========
|
||||
//math unit
|
||||
//=========
|
||||
|
||||
case 0x4820: return r4820;
|
||||
case 0x4821: return r4821;
|
||||
case 0x4822: return r4822;
|
||||
case 0x4823: return r4823;
|
||||
case 0x4824: return r4824;
|
||||
case 0x4825: return r4825;
|
||||
case 0x4826: return r4826;
|
||||
case 0x4827: return r4827;
|
||||
case 0x4828: return r4828;
|
||||
case 0x4829: return r4829;
|
||||
case 0x482a: return r482a;
|
||||
case 0x482b: return r482b;
|
||||
case 0x482c: return r482c;
|
||||
case 0x482d: return r482d;
|
||||
case 0x482e: return r482e;
|
||||
case 0x482f: {
|
||||
uint8 status = r482f;
|
||||
r482f &= 0x7f;
|
||||
return status;
|
||||
}
|
||||
|
||||
//===================
|
||||
//memory mapping unit
|
||||
//===================
|
||||
|
||||
case 0x4830: return r4830;
|
||||
case 0x4831: return r4831;
|
||||
case 0x4832: return r4832;
|
||||
case 0x4833: return r4833;
|
||||
case 0x4834: return r4834;
|
||||
|
||||
//====================
|
||||
//real-time clock unit
|
||||
//====================
|
||||
|
||||
case 0x4840: return r4840;
|
||||
case 0x4841: {
|
||||
if(rtc_state == RTCS_Inactive || rtc_state == RTCS_ModeSelect) return 0x00;
|
||||
|
||||
r4842 = 0x80;
|
||||
uint8 data = memory::cartrtc.read(rtc_index);
|
||||
rtc_index = (rtc_index + 1) & 15;
|
||||
return data;
|
||||
}
|
||||
case 0x4842: {
|
||||
uint8 status = r4842;
|
||||
r4842 &= 0x7f;
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return cpu.regs.mdr;
|
||||
}
|
||||
|
||||
void SPC7110::mmio_write(uint addr, uint8 data) {
|
||||
addr &= 0xffff;
|
||||
|
||||
switch(addr) {
|
||||
//==================
|
||||
//decompression unit
|
||||
//==================
|
||||
|
||||
case 0x4801: r4801 = data; break;
|
||||
case 0x4802: r4802 = data; break;
|
||||
case 0x4803: r4803 = data; break;
|
||||
case 0x4804: r4804 = data; break;
|
||||
case 0x4805: r4805 = data; break;
|
||||
case 0x4806: {
|
||||
r4806 = data;
|
||||
|
||||
unsigned table = (r4801 + (r4802 << 8) + (r4803 << 16));
|
||||
unsigned index = (r4804 << 2);
|
||||
unsigned length = (r4809 + (r480a << 8));
|
||||
unsigned addr = datarom_addr(table + index);
|
||||
unsigned mode = (memory::cartrom.read(addr + 0));
|
||||
unsigned offset = (memory::cartrom.read(addr + 1) << 16)
|
||||
+ (memory::cartrom.read(addr + 2) << 8)
|
||||
+ (memory::cartrom.read(addr + 3) << 0);
|
||||
|
||||
decomp.init(mode, offset, (r4805 + (r4806 << 8)) << mode);
|
||||
r480c = 0x80;
|
||||
} break;
|
||||
|
||||
case 0x4807: r4807 = data; break;
|
||||
case 0x4808: r4808 = data; break;
|
||||
case 0x4809: r4809 = data; break;
|
||||
case 0x480a: r480a = data; break;
|
||||
case 0x480b: r480b = data; break;
|
||||
|
||||
//==============
|
||||
//data port unit
|
||||
//==============
|
||||
|
||||
case 0x4811: r4811 = data; r481x |= 0x01; break;
|
||||
case 0x4812: r4812 = data; r481x |= 0x02; break;
|
||||
case 0x4813: r4813 = data; r481x |= 0x04; break;
|
||||
case 0x4814: {
|
||||
r4814 = data;
|
||||
r4814_latch = true;
|
||||
if(!r4815_latch) break;
|
||||
if(!(r4818 & 2)) break;
|
||||
if(r4818 & 0x10) break;
|
||||
|
||||
if((r4818 & 0x60) == 0x20) {
|
||||
unsigned increment = data_adjust() & 0xff;
|
||||
if(r4818 & 8) increment = (int8)increment; //8-bit sign extend
|
||||
set_data_pointer(data_pointer() + increment);
|
||||
} else if((r4818 & 0x60) == 0x40) {
|
||||
unsigned increment = data_adjust();
|
||||
if(r4818 & 8) increment = (int16)increment; //16-bit sign extend
|
||||
set_data_pointer(data_pointer() + increment);
|
||||
}
|
||||
} break;
|
||||
case 0x4815: {
|
||||
r4815 = data;
|
||||
r4815_latch = true;
|
||||
if(!r4814_latch) break;
|
||||
if(!(r4818 & 2)) break;
|
||||
if(r4818 & 0x10) break;
|
||||
|
||||
if((r4818 & 0x60) == 0x20) {
|
||||
unsigned increment = data_adjust() & 0xff;
|
||||
if(r4818 & 8) increment = (int8)increment; //8-bit sign extend
|
||||
set_data_pointer(data_pointer() + increment);
|
||||
} else if((r4818 & 0x60) == 0x40) {
|
||||
unsigned increment = data_adjust();
|
||||
if(r4818 & 8) increment = (int16)increment; //16-bit sign extend
|
||||
set_data_pointer(data_pointer() + increment);
|
||||
}
|
||||
} break;
|
||||
case 0x4816: r4816 = data; break;
|
||||
case 0x4817: r4817 = data; break;
|
||||
case 0x4818: {
|
||||
if(r481x != 0x07) break;
|
||||
|
||||
r4818 = data;
|
||||
r4814_latch = r4815_latch = false;
|
||||
} break;
|
||||
|
||||
//=========
|
||||
//math unit
|
||||
//=========
|
||||
|
||||
case 0x4820: r4820 = data; break;
|
||||
case 0x4821: r4821 = data; break;
|
||||
case 0x4822: r4822 = data; break;
|
||||
case 0x4823: r4823 = data; break;
|
||||
case 0x4824: r4824 = data; break;
|
||||
case 0x4825: {
|
||||
r4825 = data;
|
||||
|
||||
if(r482e & 1) {
|
||||
//signed 16-bit x 16-bit multiplication
|
||||
int16 r0 = (int16)(r4824 + (r4825 << 8));
|
||||
int16 r1 = (int16)(r4820 + (r4821 << 8));
|
||||
|
||||
signed result = r0 * r1;
|
||||
r4828 = result;
|
||||
r4829 = result >> 8;
|
||||
r482a = result >> 16;
|
||||
r482b = result >> 24;
|
||||
} else {
|
||||
//unsigned 16-bit x 16-bit multiplication
|
||||
uint16 r0 = (uint16)(r4824 + (r4825 << 8));
|
||||
uint16 r1 = (uint16)(r4820 + (r4821 << 8));
|
||||
|
||||
unsigned result = r0 * r1;
|
||||
r4828 = result;
|
||||
r4829 = result >> 8;
|
||||
r482a = result >> 16;
|
||||
r482b = result >> 24;
|
||||
}
|
||||
|
||||
r482f = 0x80;
|
||||
} break;
|
||||
case 0x4826: r4826 = data; break;
|
||||
case 0x4827: {
|
||||
r4827 = data;
|
||||
|
||||
if(r482e & 1) {
|
||||
//signed 32-bit x 16-bit division
|
||||
int32 dividend = (int32)(r4820 + (r4821 << 8) + (r4822 << 16) + (r4823 << 24));
|
||||
int16 divisor = (int16)(r4826 + (r4827 << 8));
|
||||
|
||||
int32 quotient;
|
||||
int16 remainder;
|
||||
|
||||
if(divisor) {
|
||||
quotient = (int32)(dividend / divisor);
|
||||
remainder = (int32)(dividend % divisor);
|
||||
} else {
|
||||
//illegal division by zero
|
||||
quotient = 0;
|
||||
remainder = dividend & 0xffff;
|
||||
}
|
||||
|
||||
r4828 = quotient;
|
||||
r4829 = quotient >> 8;
|
||||
r482a = quotient >> 16;
|
||||
r482b = quotient >> 24;
|
||||
|
||||
r482c = remainder;
|
||||
r482d = remainder >> 8;
|
||||
} else {
|
||||
//unsigned 32-bit x 16-bit division
|
||||
uint32 dividend = (uint32)(r4820 + (r4821 << 8) + (r4822 << 16) + (r4823 << 24));
|
||||
uint16 divisor = (uint16)(r4826 + (r4827 << 8));
|
||||
|
||||
uint32 quotient;
|
||||
uint16 remainder;
|
||||
|
||||
if(divisor) {
|
||||
quotient = (uint32)(dividend / divisor);
|
||||
remainder = (uint16)(dividend % divisor);
|
||||
} else {
|
||||
//illegal division by zero
|
||||
quotient = 0;
|
||||
remainder = dividend & 0xffff;
|
||||
}
|
||||
|
||||
r4828 = quotient;
|
||||
r4829 = quotient >> 8;
|
||||
r482a = quotient >> 16;
|
||||
r482b = quotient >> 24;
|
||||
|
||||
r482c = remainder;
|
||||
r482d = remainder >> 8;
|
||||
}
|
||||
|
||||
r482f = 0x80;
|
||||
} break;
|
||||
|
||||
case 0x482e: {
|
||||
//reset math unit
|
||||
r4820 = r4821 = r4822 = r4823 = 0;
|
||||
r4824 = r4825 = r4826 = r4827 = 0;
|
||||
r4828 = r4829 = r482a = r482b = 0;
|
||||
r482c = r482d = 0;
|
||||
|
||||
r482e = data;
|
||||
} break;
|
||||
|
||||
//===================
|
||||
//memory mapping unit
|
||||
//===================
|
||||
|
||||
case 0x4830: r4830 = data; break;
|
||||
|
||||
case 0x4831: {
|
||||
r4831 = data;
|
||||
dx_offset = datarom_addr((data & 7) * 0x100000);
|
||||
} break;
|
||||
|
||||
case 0x4832: {
|
||||
r4832 = data;
|
||||
ex_offset = datarom_addr((data & 7) * 0x100000);
|
||||
} break;
|
||||
|
||||
case 0x4833: {
|
||||
r4833 = data;
|
||||
fx_offset = datarom_addr((data & 7) * 0x100000);
|
||||
} break;
|
||||
|
||||
case 0x4834: r4834 = data; break;
|
||||
|
||||
//====================
|
||||
//real-time clock unit
|
||||
//====================
|
||||
|
||||
case 0x4840: {
|
||||
r4840 = data;
|
||||
if(!(r4840 & 1)) {
|
||||
//disable RTC
|
||||
rtc_state = RTCS_Inactive;
|
||||
update_time();
|
||||
} else {
|
||||
//enable RTC
|
||||
r4842 = 0x80;
|
||||
rtc_state = RTCS_ModeSelect;
|
||||
}
|
||||
} break;
|
||||
|
||||
case 0x4841: {
|
||||
r4841 = data;
|
||||
|
||||
switch(rtc_state) {
|
||||
case RTCS_ModeSelect: {
|
||||
if(data == RTCM_Linear || data == RTCM_Indexed) {
|
||||
r4842 = 0x80;
|
||||
rtc_state = RTCS_IndexSelect;
|
||||
rtc_mode = (RTC_Mode)data;
|
||||
rtc_index = 0;
|
||||
}
|
||||
} break;
|
||||
|
||||
case RTCS_IndexSelect: {
|
||||
r4842 = 0x80;
|
||||
rtc_index = data & 15;
|
||||
if(rtc_mode == RTCM_Linear) rtc_state = RTCS_Write;
|
||||
} break;
|
||||
|
||||
case RTCS_Write: {
|
||||
r4842 = 0x80;
|
||||
|
||||
//control register 0
|
||||
if(rtc_index == 13) {
|
||||
//increment second counter
|
||||
if(data & 2) update_time(+1);
|
||||
|
||||
//round minute counter
|
||||
if(data & 8) {
|
||||
update_time();
|
||||
|
||||
unsigned second = memory::cartrtc.read( 0) + memory::cartrtc.read( 1) * 10;
|
||||
//clear seconds
|
||||
memory::cartrtc.write(0, 0);
|
||||
memory::cartrtc.write(1, 0);
|
||||
|
||||
if(second >= 30) update_time(+60);
|
||||
}
|
||||
}
|
||||
|
||||
//control register 2
|
||||
if(rtc_index == 15) {
|
||||
//disable timer and clear second counter
|
||||
if((data & 1) && !(memory::cartrtc.read(15) & 1)) {
|
||||
update_time();
|
||||
|
||||
//clear seconds
|
||||
memory::cartrtc.write(0, 0);
|
||||
memory::cartrtc.write(1, 0);
|
||||
}
|
||||
|
||||
//disable timer
|
||||
if((data & 2) && !(memory::cartrtc.read(15) & 2)) {
|
||||
update_time();
|
||||
}
|
||||
}
|
||||
|
||||
memory::cartrtc.write(rtc_index, data & 15);
|
||||
rtc_index = (rtc_index + 1) & 15;
|
||||
} break;
|
||||
} //switch(rtc_state)
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 SPC7110::read(uint addr) {
|
||||
//$[00-0f|80-8f]:[8000-ffff], $[c0-cf]:[0000-ffff] mapped directly to memory::cartrom
|
||||
|
||||
if((addr & 0xffe000) == 0x006000 || (addr & 0xffe000) == 0x306000) {
|
||||
//$[00|30]:[6000-7fff]
|
||||
return memory::cartram.read(addr & 0x1fff);
|
||||
}
|
||||
|
||||
if((addr & 0xff0000) == 0x500000) {
|
||||
//$[50]:[0000-ffff]
|
||||
return mmio_read(0x4800);
|
||||
}
|
||||
|
||||
if((addr & 0xf00000) == 0xd00000) {
|
||||
//$[d0-df]:[0000-ffff]
|
||||
return memory::cartrom.read(dx_offset + (addr & 0x0fffff));
|
||||
}
|
||||
|
||||
if((addr & 0xf00000) == 0xe00000) {
|
||||
//$[e0-ef]:[0000-ffff]
|
||||
return memory::cartrom.read(ex_offset + (addr & 0x0fffff));
|
||||
}
|
||||
|
||||
if((addr & 0xf00000) == 0xf00000) {
|
||||
//$[f0-ff]:[0000-ffff]
|
||||
return memory::cartrom.read(fx_offset + (addr & 0x0fffff));
|
||||
}
|
||||
|
||||
return cpu.regs.mdr;
|
||||
}
|
||||
|
||||
void SPC7110::write(uint addr, uint8 data) {
|
||||
if((addr & 0xffe000) == 0x006000 || (addr & 0xffe000) == 0x306000) {
|
||||
//$[00|30]:[6000-7fff]
|
||||
if(r4830 & 0x80) memory::cartram.write(addr & 0x1fff, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SPC7110::SPC7110() {
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*****
|
||||
* SPC7110 emulator - version 0.03 (2008-08-10)
|
||||
* Copyright (c) 2008, byuu and neviksti
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* The software is provided "as is" and the author disclaims all warranties
|
||||
* with regard to this software including all implied warranties of
|
||||
* merchantibility and fitness, in no event shall the author be liable for
|
||||
* any special, direct, indirect, or consequential damages or any damages
|
||||
* whatsoever resulting from loss of use, data or profits, whether in an
|
||||
* action of contract, negligence or other tortious action, arising out of
|
||||
* or in connection with the use or performance of this software.
|
||||
*****/
|
||||
|
||||
#include "decomp.h"
|
||||
|
||||
class SPC7110 : public MMIO, public Memory {
|
||||
public:
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
unsigned datarom_addr(unsigned addr);
|
||||
|
||||
unsigned data_pointer();
|
||||
unsigned data_adjust();
|
||||
unsigned data_increment();
|
||||
void set_data_pointer(unsigned addr);
|
||||
void set_data_adjust(unsigned addr);
|
||||
|
||||
void update_time(int offset = 0);
|
||||
time_t create_time();
|
||||
|
||||
uint8 mmio_read (uint addr);
|
||||
void mmio_write(uint addr, uint8 data);
|
||||
|
||||
uint8 read (uint addr);
|
||||
void write(uint addr, uint8 data);
|
||||
|
||||
//spc7110decomp
|
||||
void decomp_init();
|
||||
uint8 decomp_read();
|
||||
|
||||
SPC7110();
|
||||
|
||||
private:
|
||||
//==================
|
||||
//decompression unit
|
||||
//==================
|
||||
uint8 r4801; //compression table low
|
||||
uint8 r4802; //compression table high
|
||||
uint8 r4803; //compression table bank
|
||||
uint8 r4804; //compression table index
|
||||
uint8 r4805; //decompression buffer index low
|
||||
uint8 r4806; //decompression buffer index high
|
||||
uint8 r4807; //???
|
||||
uint8 r4808; //???
|
||||
uint8 r4809; //compression length low
|
||||
uint8 r480a; //compression length high
|
||||
uint8 r480b; //decompression control register
|
||||
uint8 r480c; //decompression status
|
||||
|
||||
SPC7110Decomp decomp;
|
||||
|
||||
//==============
|
||||
//data port unit
|
||||
//==============
|
||||
uint8 r4811; //data pointer low
|
||||
uint8 r4812; //data pointer high
|
||||
uint8 r4813; //data pointer bank
|
||||
uint8 r4814; //data adjust low
|
||||
uint8 r4815; //data adjust high
|
||||
uint8 r4816; //data increment low
|
||||
uint8 r4817; //data increment high
|
||||
uint8 r4818; //data port control register
|
||||
|
||||
uint8 r481x;
|
||||
|
||||
bool r4814_latch;
|
||||
bool r4815_latch;
|
||||
|
||||
//=========
|
||||
//math unit
|
||||
//=========
|
||||
uint8 r4820; //16-bit multiplicand B0, 32-bit dividend B0
|
||||
uint8 r4821; //16-bit multiplicand B1, 32-bit dividend B1
|
||||
uint8 r4822; //32-bit dividend B2
|
||||
uint8 r4823; //32-bit dividend B3
|
||||
uint8 r4824; //16-bit multiplier B0
|
||||
uint8 r4825; //16-bit multiplier B1
|
||||
uint8 r4826; //16-bit divisor B0
|
||||
uint8 r4827; //16-bit divisor B1
|
||||
uint8 r4828; //32-bit product B0, 32-bit quotient B0
|
||||
uint8 r4829; //32-bit product B1, 32-bit quotient B1
|
||||
uint8 r482a; //32-bit product B2, 32-bit quotient B2
|
||||
uint8 r482b; //32-bit product B3, 32-bit quotient B3
|
||||
uint8 r482c; //16-bit remainder B0
|
||||
uint8 r482d; //16-bit remainder B1
|
||||
uint8 r482e; //math control register
|
||||
uint8 r482f; //math status
|
||||
|
||||
//===================
|
||||
//memory mapping unit
|
||||
//===================
|
||||
uint8 r4830; //SRAM write enable
|
||||
uint8 r4831; //$[d0-df]:[0000-ffff] mapping
|
||||
uint8 r4832; //$[e0-ef]:[0000-ffff] mapping
|
||||
uint8 r4833; //$[f0-ff]:[0000-ffff] mapping
|
||||
uint8 r4834; //???
|
||||
|
||||
unsigned dx_offset;
|
||||
unsigned ex_offset;
|
||||
unsigned fx_offset;
|
||||
|
||||
//====================
|
||||
//real-time clock unit
|
||||
//====================
|
||||
uint8 r4840; //RTC latch
|
||||
uint8 r4841; //RTC index/data port
|
||||
uint8 r4842; //RTC status
|
||||
|
||||
enum RTC_State { RTCS_Inactive, RTCS_ModeSelect, RTCS_IndexSelect, RTCS_Write } rtc_state;
|
||||
enum RTC_Mode { RTCM_Linear = 0x03, RTCM_Indexed = 0x0c } rtc_mode;
|
||||
unsigned rtc_index;
|
||||
|
||||
static const unsigned months[12];
|
||||
};
|
||||
|
||||
extern SPC7110 spc7110;
|
||||
@@ -0,0 +1,213 @@
|
||||
#include "../../base.h"
|
||||
|
||||
const unsigned SRTC::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
void SRTC::init() {
|
||||
}
|
||||
|
||||
void SRTC::enable() {
|
||||
memory::mmio.map(0x2800, *this);
|
||||
memory::mmio.map(0x2801, *this);
|
||||
}
|
||||
|
||||
void SRTC::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void SRTC::reset() {
|
||||
rtc_mode = RTCM_Read;
|
||||
rtc_index = -1;
|
||||
update_time();
|
||||
}
|
||||
|
||||
void SRTC::update_time() {
|
||||
time_t rtc_time;
|
||||
rtc_time = memory::cartrtc.read(16);
|
||||
rtc_time |= memory::cartrtc.read(17) << 8;
|
||||
rtc_time |= memory::cartrtc.read(18) << 16;
|
||||
rtc_time |= memory::cartrtc.read(19) << 24;
|
||||
|
||||
time_t current_time = time(0);
|
||||
if(current_time > rtc_time) {
|
||||
unsigned second = memory::cartrtc.read( 0) + memory::cartrtc.read( 1) * 10;
|
||||
unsigned minute = memory::cartrtc.read( 2) + memory::cartrtc.read( 3) * 10;
|
||||
unsigned hour = memory::cartrtc.read( 4) + memory::cartrtc.read( 5) * 10;
|
||||
unsigned day = memory::cartrtc.read( 6) + memory::cartrtc.read( 7) * 10;
|
||||
unsigned month = memory::cartrtc.read( 8);
|
||||
unsigned year = memory::cartrtc.read( 9) + memory::cartrtc.read(10) * 10 + memory::cartrtc.read(11) * 100;
|
||||
unsigned weekday = memory::cartrtc.read(12);
|
||||
|
||||
day--;
|
||||
month--;
|
||||
year += 1000;
|
||||
|
||||
second += (unsigned)(current_time - rtc_time);
|
||||
|
||||
while(second >= 60) {
|
||||
second -= 60;
|
||||
|
||||
minute++;
|
||||
if(minute < 60) continue;
|
||||
minute = 0;
|
||||
|
||||
hour++;
|
||||
if(hour < 24) continue;
|
||||
hour = 0;
|
||||
|
||||
day++;
|
||||
weekday = (weekday + 1) % 7;
|
||||
unsigned days = months[month % 12];
|
||||
if(days == 28) {
|
||||
bool leapyear = false;
|
||||
if((year % 4) == 0) {
|
||||
leapyear = true;
|
||||
if((year % 100) == 0 && (year % 400) != 0) leapyear = false;
|
||||
}
|
||||
if(leapyear) days++;
|
||||
}
|
||||
if(day < days) continue;
|
||||
day = 0;
|
||||
|
||||
month++;
|
||||
if(month < 12) continue;
|
||||
month = 0;
|
||||
|
||||
year++;
|
||||
}
|
||||
|
||||
day++;
|
||||
month++;
|
||||
year -= 1000;
|
||||
|
||||
memory::cartrtc.write( 0, second % 10);
|
||||
memory::cartrtc.write( 1, second / 10);
|
||||
memory::cartrtc.write( 2, minute % 10);
|
||||
memory::cartrtc.write( 3, minute / 10);
|
||||
memory::cartrtc.write( 4, hour % 10);
|
||||
memory::cartrtc.write( 5, hour / 10);
|
||||
memory::cartrtc.write( 6, day % 10);
|
||||
memory::cartrtc.write( 7, day / 10);
|
||||
memory::cartrtc.write( 8, month);
|
||||
memory::cartrtc.write( 9, year % 10);
|
||||
memory::cartrtc.write(10, (year / 10) % 10);
|
||||
memory::cartrtc.write(11, year / 100);
|
||||
memory::cartrtc.write(12, weekday % 7);
|
||||
}
|
||||
|
||||
memory::cartrtc.write(16, current_time);
|
||||
memory::cartrtc.write(17, current_time >> 8);
|
||||
memory::cartrtc.write(18, current_time >> 16);
|
||||
memory::cartrtc.write(19, current_time >> 24);
|
||||
}
|
||||
|
||||
//returns day of week for specified date
|
||||
//eg 0 = Sunday, 1 = Monday, ... 6 = Saturday
|
||||
//usage: weekday(2008, 1, 1) returns weekday of January 1st, 2008
|
||||
unsigned SRTC::weekday(unsigned year, unsigned month, unsigned day) {
|
||||
unsigned y = 1900, m = 1; //epoch is 1900-01-01
|
||||
unsigned sum = 0; //number of days passed since epoch
|
||||
|
||||
year = max(1900, year);
|
||||
month = max(1, min(12, month));
|
||||
day = max(1, min(31, day));
|
||||
|
||||
while(y < year) {
|
||||
bool leapyear = false;
|
||||
if((y % 4) == 0) {
|
||||
leapyear = true;
|
||||
if((y % 100) == 0 && (y % 400) != 0) leapyear = false;
|
||||
}
|
||||
sum += leapyear ? 366 : 365;
|
||||
y++;
|
||||
}
|
||||
|
||||
while(m < month) {
|
||||
unsigned days = months[m - 1];
|
||||
if(days == 28) {
|
||||
bool leapyear = false;
|
||||
if((y % 4) == 0) {
|
||||
leapyear = true;
|
||||
if((y % 100) == 0 && (y % 400) != 0) leapyear = false;
|
||||
}
|
||||
if(leapyear) days++;
|
||||
}
|
||||
sum += days;
|
||||
m++;
|
||||
}
|
||||
|
||||
sum += day - 1;
|
||||
return (sum + 1) % 7; //1900-01-01 was a Monday
|
||||
}
|
||||
|
||||
uint8 SRTC::mmio_read(uint addr) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr == 0x2800) {
|
||||
if(rtc_mode != RTCM_Read) return 0x00;
|
||||
|
||||
if(rtc_index < 0) {
|
||||
update_time();
|
||||
rtc_index++;
|
||||
return 0x0f;
|
||||
} else if(rtc_index > 12) {
|
||||
rtc_index = -1;
|
||||
return 0x0f;
|
||||
} else {
|
||||
return memory::cartrtc.read(rtc_index++);
|
||||
}
|
||||
}
|
||||
|
||||
return cpu.regs.mdr;
|
||||
}
|
||||
|
||||
void SRTC::mmio_write(uint addr, uint8 data) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr == 0x2801) {
|
||||
data &= 0x0f; //only the low four bits are used
|
||||
|
||||
if(data == 0x0d) {
|
||||
rtc_mode = RTCM_Read;
|
||||
rtc_index = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
if(data == 0x0e) {
|
||||
rtc_mode = RTCM_Command;
|
||||
return;
|
||||
}
|
||||
|
||||
if(data == 0x0f) return; //unknown behavior
|
||||
|
||||
if(rtc_mode == RTCM_Write) {
|
||||
if(rtc_index >= 0 && rtc_index < 12) {
|
||||
memory::cartrtc.write(rtc_index++, data);
|
||||
|
||||
if(rtc_index == 12) {
|
||||
//day of week is automatically calculated and written
|
||||
unsigned day = memory::cartrtc.read( 6) + memory::cartrtc.read( 7) * 10;
|
||||
unsigned month = memory::cartrtc.read( 8);
|
||||
unsigned year = memory::cartrtc.read( 9) + memory::cartrtc.read(10) * 10 + memory::cartrtc.read(11) * 100;
|
||||
year += 1000;
|
||||
|
||||
memory::cartrtc.write(rtc_index++, weekday(year, month, day));
|
||||
}
|
||||
}
|
||||
} else if(rtc_mode == RTCM_Command) {
|
||||
if(data == 0) {
|
||||
rtc_mode = RTCM_Write;
|
||||
rtc_index = 0;
|
||||
} else if(data == 4) {
|
||||
rtc_mode = RTCM_Ready;
|
||||
rtc_index = -1;
|
||||
for(unsigned i = 0; i < 13; i++) memory::cartrtc.write(i, 0);
|
||||
} else {
|
||||
//unknown behavior
|
||||
rtc_mode = RTCM_Ready;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SRTC::SRTC() {
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
class SRTC : public MMIO {
|
||||
public:
|
||||
void update_time();
|
||||
unsigned weekday(unsigned year, unsigned month, unsigned day);
|
||||
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 mmio_read (uint addr);
|
||||
void mmio_write(uint addr, uint8 data);
|
||||
|
||||
SRTC();
|
||||
|
||||
private:
|
||||
static const unsigned months[12];
|
||||
enum RTC_Mode { RTCM_Ready, RTCM_Command, RTCM_Read, RTCM_Write } rtc_mode;
|
||||
signed rtc_index;
|
||||
};
|
||||
|
||||
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
|
||||
@@ -1,205 +0,0 @@
|
||||
#include "../../base.h"
|
||||
|
||||
void bClock::frameskip_update_status() {
|
||||
if(frameskip.changed == true) {
|
||||
frameskip.changed = false;
|
||||
frameskip.count = frameskip.new_count;
|
||||
frameskip.pos = 0;
|
||||
} else {
|
||||
frameskip.pos++;
|
||||
frameskip.pos %= (frameskip.count + 1);
|
||||
}
|
||||
|
||||
frameskip.notify_ppu = (frameskip.pos == 0)?true:false;
|
||||
}
|
||||
|
||||
void bClock::dram_refresh_test() {
|
||||
if(cc1.dram_refreshed == false && status.hcycles >= cc1.dram_refresh_pos) {
|
||||
cc1.dram_refreshed = true;
|
||||
|
||||
if(status.interlace != false || status.interlace_field != 1 || status.vcounter != 240) {
|
||||
if(cc1.dram_refresh_pos == 534) {
|
||||
cc1.dram_refresh_pos = 538;
|
||||
} else { //cc1.dram_refresh_pos == 538
|
||||
cc1.dram_refresh_pos = 534;
|
||||
}
|
||||
}
|
||||
|
||||
cc1.pos += 40;
|
||||
cc1.frame_pos += 40;
|
||||
status.hcycles += 40;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
all scanlines are 1364 cycles long, except scanline 240
|
||||
on non-interlace odd-frames, which is 1360 cycles long.
|
||||
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.
|
||||
|
||||
cycles per frame:
|
||||
263 * 1364 = 358732
|
||||
262 * 1364 = 357368
|
||||
262 * 1364 - 4 = 357364
|
||||
*/
|
||||
void bClock::inc_vcounter() {
|
||||
status.hcycles -= cc1.line_cycles;
|
||||
|
||||
status.vcounter++;
|
||||
if(status.vcounter >= cc1.frame_lines) {
|
||||
frameskip_update_status();
|
||||
|
||||
cc1.frame_pos -= cc1.frame_cycles;
|
||||
status.vcounter = 0;
|
||||
status.interlace_field ^= 1;
|
||||
if(status.interlace == true) {
|
||||
if(status.interlace_field == 0) {
|
||||
cc1.frame_cycles = 263 * 1364;
|
||||
cc1.frame_lines = 263;
|
||||
} else {
|
||||
cc1.frame_cycles = 262 * 1364;
|
||||
cc1.frame_lines = 262;
|
||||
}
|
||||
} else {
|
||||
if(status.interlace_field == 0) {
|
||||
cc1.frame_cycles = 262 * 1364;
|
||||
cc1.frame_lines = 262;
|
||||
} else {
|
||||
cc1.frame_cycles = (262 * 1364) - 4;
|
||||
cc1.frame_lines = 262;
|
||||
}
|
||||
}
|
||||
cc1.render_frame = true;
|
||||
cpu->frame();
|
||||
if(frameskip.notify_ppu == true)ppu->frame();
|
||||
}
|
||||
|
||||
if(status.interlace == false && status.interlace_field == 1 && status.vcounter == 240) {
|
||||
cc1.line_cycles = 1360;
|
||||
} else {
|
||||
cc1.line_cycles = 1364;
|
||||
}
|
||||
|
||||
cc1.dram_refreshed = false;
|
||||
|
||||
cpu->scanline();
|
||||
if(frameskip.notify_ppu == true)ppu->scanline();
|
||||
|
||||
//if(status.vcounter == visible_scanlines()) {
|
||||
// cc1.render_frame = true;
|
||||
//}
|
||||
}
|
||||
|
||||
/*
|
||||
all dots are 4 cycles long, except dots 322 and 326. dots 322 and 326
|
||||
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 322 range = { 1288, 1290, 1292 }
|
||||
dot 326 range = { 1306, 1308, 1310 }
|
||||
*/
|
||||
void bClock::sync() {
|
||||
uint32 new_cycles, cycles;
|
||||
new_cycles = cc1.pos - cc1.last_pos;
|
||||
while(new_cycles) {
|
||||
if(new_cycles > 40) {
|
||||
cycles = 40;
|
||||
new_cycles -= 40;
|
||||
} else {
|
||||
cycles = new_cycles;
|
||||
new_cycles = 0;
|
||||
}
|
||||
|
||||
status.hcycles += cycles;
|
||||
cc1.frame_pos += cycles;
|
||||
dram_refresh_test();
|
||||
if(status.hcycles >= cc1.line_cycles) {
|
||||
inc_vcounter();
|
||||
}
|
||||
}
|
||||
cc1.last_pos = cc1.pos;
|
||||
|
||||
if(cc1.pos > cc1.frequency) {
|
||||
cc1.pos -= cc1.frequency;
|
||||
cc1.last_pos -= cc1.frequency;
|
||||
}
|
||||
|
||||
if(status.interlace == false && status.interlace_field == 1 && status.vcounter == 240) {
|
||||
status.hcounter = status.hcycles >> 2;
|
||||
} else {
|
||||
//1288 = 322 * 4, 1306 = 326 * 4 + 2
|
||||
status.hcounter = (status.hcycles - ((status.hcycles > 1288) << 1) - ((status.hcycles > 1306) << 1)) >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
void bClock::set_frameskip(uint8 fs) {
|
||||
frameskip.changed = true;
|
||||
frameskip.new_count = fs;
|
||||
}
|
||||
|
||||
bool bClock::update_frame() {
|
||||
if(cc1.render_frame == true) {
|
||||
cc1.render_frame = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void bClock::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void bClock::reset() {
|
||||
cc1.render_frame = false;
|
||||
|
||||
//upon SNES reset, start at scanline 0 non-interlace
|
||||
cc1.frame_cycles = 262 * 1364;
|
||||
cc1.frame_lines = 262;
|
||||
cc1.line_cycles = 1364;
|
||||
|
||||
/*
|
||||
Initial latch values for $213c/$213d
|
||||
0035:0000 (53.0 -> 212) [lda $2137]
|
||||
0038:0000 (56.5 -> 226) [nop : lda $2137]
|
||||
*/
|
||||
cc1.pos = 188;
|
||||
cc1.last_pos = 0;
|
||||
cc1.frame_pos = 0;
|
||||
status.vcounter = 0;
|
||||
status.hcounter = 0;
|
||||
status.hcycles = 0;
|
||||
|
||||
cc1.dram_refresh_pos = 538;
|
||||
cc1.dram_refreshed = false;
|
||||
|
||||
cc2.pos = 0;
|
||||
|
||||
sync();
|
||||
}
|
||||
|
||||
void bClock::run() {
|
||||
cpu->run();
|
||||
if(frameskip.notify_ppu == true)ppu->run();
|
||||
sync();
|
||||
}
|
||||
|
||||
void bClock::add_cc1_cycles(uint32 cycles) {
|
||||
cc1.pos += cycles;
|
||||
}
|
||||
|
||||
void bClock::add_cc2_cycles(uint32 cycles) {
|
||||
cc2.pos += cycles;
|
||||
}
|
||||
|
||||
bClock::bClock() {
|
||||
cc1.frequency = 21477272;
|
||||
cc2.frequency = 24576000;
|
||||
|
||||
frameskip.changed = false;
|
||||
frameskip.count = 0;
|
||||
frameskip.pos = 0;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
class bClock : public Clock {
|
||||
private:
|
||||
struct {
|
||||
bool changed, notify_ppu;
|
||||
uint8 count, new_count, pos;
|
||||
}frameskip;
|
||||
void frameskip_update_status();
|
||||
void inc_vcounter();
|
||||
void dram_refresh_test();
|
||||
|
||||
public:
|
||||
struct {
|
||||
uint32 frequency;
|
||||
uint32 pos, last_pos;
|
||||
uint32 frame_cycles, frame_lines, frame_pos;
|
||||
uint16 line_cycles;
|
||||
bool dram_refreshed; //whether or not dram has been refreshed on this line
|
||||
uint16 dram_refresh_pos;
|
||||
|
||||
bool render_frame;
|
||||
}cc1;
|
||||
struct {
|
||||
uint32 frequency;
|
||||
uint32 pos, last_pos;
|
||||
}cc2;
|
||||
|
||||
void set_frameskip(uint8 fs);
|
||||
bool update_frame();
|
||||
|
||||
void add_cc1_cycles(uint32 cycles);
|
||||
void add_cc2_cycles(uint32 cycles);
|
||||
void sync();
|
||||
void run();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
bClock();
|
||||
~bClock();
|
||||
};
|
||||
@@ -1,49 +0,0 @@
|
||||
#include "../base.h"
|
||||
|
||||
void Clock::enable_overscan(bool n) {
|
||||
status.overscan = n;
|
||||
}
|
||||
|
||||
void Clock::enable_interlace(bool n) {
|
||||
status.interlace = n;
|
||||
}
|
||||
|
||||
bool Clock::overscan() {
|
||||
return status.overscan;
|
||||
}
|
||||
|
||||
bool Clock::interlace() {
|
||||
return status.interlace;
|
||||
}
|
||||
|
||||
bool Clock::interlace_field() {
|
||||
return status.interlace_field;
|
||||
}
|
||||
|
||||
uint16 Clock::vcounter() {
|
||||
return status.vcounter;
|
||||
}
|
||||
|
||||
uint16 Clock::hcounter() {
|
||||
return status.hcounter;
|
||||
}
|
||||
|
||||
uint16 Clock::hcycles() {
|
||||
return status.hcycles;
|
||||
}
|
||||
|
||||
uint16 Clock::visible_scanlines() {
|
||||
return (status.overscan)?239:224;
|
||||
}
|
||||
|
||||
void Clock::set_frameskip(uint8 fs) {}
|
||||
|
||||
Clock::Clock() {
|
||||
status.overscan = false;
|
||||
status.interlace = false;
|
||||
status.interlace_field = 0;
|
||||
|
||||
status.vcounter = 0;
|
||||
status.hcounter = 0;
|
||||
status.hcycles = 0;
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
class Clock {
|
||||
private:
|
||||
struct {
|
||||
bool overscan;
|
||||
bool interlace;
|
||||
bool interlace_field;
|
||||
|
||||
uint16 vcounter;
|
||||
uint16 hcounter;
|
||||
uint16 hcycles;
|
||||
}status;
|
||||
|
||||
public:
|
||||
virtual void enable_overscan(bool n);
|
||||
virtual void enable_interlace(bool n);
|
||||
virtual bool overscan();
|
||||
virtual bool interlace();
|
||||
virtual bool interlace_field();
|
||||
virtual uint16 vcounter();
|
||||
virtual uint16 hcounter();
|
||||
virtual uint16 hcycles();
|
||||
virtual uint16 visible_scanlines();
|
||||
|
||||
virtual void set_frameskip(uint8 fs);
|
||||
virtual bool update_frame() = 0;
|
||||
|
||||
virtual void add_cc1_cycles(uint32 cycles) = 0;
|
||||
virtual void add_cc2_cycles(uint32 cycles) = 0;
|
||||
virtual void sync() = 0;
|
||||
virtual void run() = 0;
|
||||
virtual void power() = 0;
|
||||
virtual void reset() = 0;
|
||||
|
||||
Clock();
|
||||
|
||||
friend class bClock;
|
||||
};
|
||||
@@ -0,0 +1,127 @@
|
||||
namespace config {
|
||||
|
||||
configuration& config() {
|
||||
static configuration config;
|
||||
return config;
|
||||
}
|
||||
|
||||
integral_setting File::autodetect_type(config(), "file.autodetect_type",
|
||||
"Auto-detect file type by inspecting file header, rather than by file extension.\n"
|
||||
"In other words, if a .zip file is renamed to .smc, it will still be correctly\n"
|
||||
"identified as a .zip file. However, there is an infinitesimal (1:~500,000,000)\n"
|
||||
"chance of a false detection when loading an uncompressed image file, if this\n"
|
||||
"option is enabled.",
|
||||
integral_setting::boolean, false);
|
||||
|
||||
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);
|
||||
|
||||
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; }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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_port1(config(), "snes.controller_port1",
|
||||
"Controller attached to SNES port 1", integral_setting::decimal, ::SNES::Input::DeviceJoypad);
|
||||
integral_setting SNES::controller_port2(config(), "snes.controller_port2",
|
||||
"Controller attached to SNES port 2", integral_setting::decimal, ::SNES::Input::DeviceJoypad);
|
||||
|
||||
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 SMP::ntsc_clock_rate(config(), "smp.ntsc_clock_rate",
|
||||
"NTSC S-SMP clock rate (in hz)", integral_setting::decimal, 32040 * 768);
|
||||
integral_setting SMP::pal_clock_rate(config(), "smp.pal_clock_rate",
|
||||
"PAL S-SMP clock rate (in hz)", integral_setting::decimal, 32040 * 768);
|
||||
|
||||
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
|
||||
@@ -0,0 +1,48 @@
|
||||
namespace config {
|
||||
|
||||
extern configuration& config();
|
||||
|
||||
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_port1;
|
||||
static integral_setting controller_port2;
|
||||
} snes;
|
||||
|
||||
extern struct CPU {
|
||||
static integral_setting ntsc_clock_rate, pal_clock_rate;
|
||||
static integral_setting wram_init_value;
|
||||
} 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,298 +0,0 @@
|
||||
#include "../../base.h"
|
||||
|
||||
#include "bcpu_op_adc.cpp"
|
||||
#include "bcpu_op_and.cpp"
|
||||
#include "bcpu_op_cmp.cpp"
|
||||
#include "bcpu_op_eor.cpp"
|
||||
#include "bcpu_op_incdec.cpp"
|
||||
#include "bcpu_op_lda.cpp"
|
||||
#include "bcpu_op_misc.cpp"
|
||||
#include "bcpu_op_ora.cpp"
|
||||
#include "bcpu_op_pc.cpp"
|
||||
#include "bcpu_op_sbc.cpp"
|
||||
#include "bcpu_op_shift.cpp"
|
||||
#include "bcpu_op_sta.cpp"
|
||||
#include "bcpu_op_stack.cpp"
|
||||
#include "bcpu_exec.cpp"
|
||||
#include "bcpu_mmio.cpp"
|
||||
|
||||
uint8 bCPU::pio_status() {
|
||||
return status.pio;
|
||||
}
|
||||
|
||||
/***********
|
||||
*** IRQ ***
|
||||
***********
|
||||
cycles:
|
||||
[1] pbr,pc ; io
|
||||
[2] pbr,pc ; io
|
||||
[3] 0,s ; pbr
|
||||
[4] 0,s-1 ; pch
|
||||
[5] 0,s-2 ; pcl
|
||||
[6] 0,s-3 ; p
|
||||
[7] 0,va ; aavl
|
||||
[8] 0,va+1 ; aavh
|
||||
*/
|
||||
void bCPU::irq(uint16 addr) {
|
||||
if(cpustate == CPUSTATE_WAI) {
|
||||
regs.pc.w++;
|
||||
cpustate = CPUSTATE_RUN;
|
||||
}
|
||||
|
||||
clock->add_cc1_cycles(mem_bus->speed(regs.pc)); //1
|
||||
clock->add_cc1_cycles(6); //2
|
||||
stack_write(regs.pc.b); //3
|
||||
stack_write(regs.pc.h); //4
|
||||
stack_write(regs.pc.l); //5
|
||||
stack_write(regs.p); //6
|
||||
rd.l = op_read(OPMODE_ADDR, addr); //7
|
||||
rd.h = op_read(OPMODE_ADDR, addr + 1); //8
|
||||
regs.pc.b = 0x00;
|
||||
regs.pc.w = rd.w;
|
||||
|
||||
regs.p.d = 0;
|
||||
regs.p.i = 1;
|
||||
|
||||
snes->notify(SNES::CPU_EXEC_OPCODE);
|
||||
}
|
||||
|
||||
void bCPU::run() {
|
||||
uint16 v, h, hc, vs;
|
||||
switch(cpustate) {
|
||||
case CPUSTATE_RUN:
|
||||
case CPUSTATE_WAI:
|
||||
v = clock->vcounter();
|
||||
h = clock->hcounter();
|
||||
hc = clock->hcycles();
|
||||
vs = clock->visible_scanlines();
|
||||
|
||||
//NMI test
|
||||
if(v >= (vs + 1) && status.nmi_triggered == false) {
|
||||
if((v == (vs + 1) && hc >= 12) || (v >= (vs + 1))) {
|
||||
status.nmi_triggered = true;
|
||||
status.nmi_pin = 0;
|
||||
if(status.nmi_enabled == true) {
|
||||
irq(0xffea);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//IRQ test
|
||||
if(!regs.p.i) {
|
||||
if(status.virq_enabled == true && status.virq_enabled == true) {
|
||||
if(v == status.virq_pos && h >= status.hirq_pos && status.irq_pin == 1) {
|
||||
status.irq_triggered = true;
|
||||
status.irq_pin = 0;
|
||||
irq(0xffee);
|
||||
return;
|
||||
}
|
||||
} else if(status.virq_enabled == true) {
|
||||
if(v == status.virq_pos && status.irq_pin == 1) {
|
||||
status.irq_triggered = true;
|
||||
status.irq_pin = 0;
|
||||
irq(0xffee);
|
||||
return;
|
||||
}
|
||||
} else if(status.hirq_enabled == true) {
|
||||
if(h >= status.hirq_pos && status.irq_pin == 1) {
|
||||
status.irq_triggered = true;
|
||||
status.irq_pin = 0;
|
||||
irq(0xffee);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//HDMA test
|
||||
if(v < vs && h >= 278 && dma->hdma_triggered == false) {
|
||||
dma->hdma_run();
|
||||
dma->hdma_triggered = true;
|
||||
}
|
||||
|
||||
exec_opcode();
|
||||
break;
|
||||
case CPUSTATE_DMA:
|
||||
dma->run();
|
||||
break;
|
||||
case CPUSTATE_STP:
|
||||
exec_opcode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::scanline() {
|
||||
uint16 v = clock->vcounter();
|
||||
if(v == 225 && status.auto_joypad_poll == true) {
|
||||
snes->poll_input();
|
||||
}
|
||||
if(status.virq_enabled == false) {
|
||||
status.irq_pin = 1;
|
||||
}
|
||||
dma->hdma_triggered = false;
|
||||
}
|
||||
|
||||
void bCPU::frame() {
|
||||
status.nmi_triggered = false;
|
||||
status.r4210_read = false;
|
||||
|
||||
status.irq_pin = 1;
|
||||
|
||||
dma->hdma_initialize();
|
||||
}
|
||||
|
||||
void bCPU::power() {
|
||||
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;
|
||||
|
||||
cpustate = CPUSTATE_RUN;
|
||||
|
||||
dma->reset();
|
||||
mmio_reset();
|
||||
|
||||
status.nmi_triggered = false;
|
||||
status.nmi_pin = 1;
|
||||
status.r4210_read = false;
|
||||
|
||||
status.irq_triggered = false;
|
||||
status.irq_pin = 1;
|
||||
}
|
||||
|
||||
void bCPU::cpu_c2() {
|
||||
if(regs.d.l != 0x00) {
|
||||
clock->add_cc1_cycles(6);
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::cpu_c4(uint16 a, uint16 b) {
|
||||
if(((a & 0xff00) != (b & 0xff00)) || !regs.p.x) {
|
||||
clock->add_cc1_cycles(6);
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::cpu_c6(uint16 a) {
|
||||
if(regs.e) {
|
||||
if((regs.pc.w & 0xff00) != (a & 0xff00)) {
|
||||
clock->add_cc1_cycles(6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::cpu_io() {
|
||||
clock->add_cc1_cycles(6);
|
||||
}
|
||||
|
||||
uint8 bCPU::op_read() {
|
||||
uint8 r;
|
||||
r = mem_bus->read(regs.pc);
|
||||
clock->add_cc1_cycles(mem_bus->speed(regs.pc));
|
||||
regs.pc.w++;
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8 bCPU::op_read(uint8 mode, uint32 addr) {
|
||||
uint8 r;
|
||||
switch(mode) {
|
||||
case OPMODE_ADDR:
|
||||
addr &= 0xffff;
|
||||
break;
|
||||
case OPMODE_LONG:
|
||||
addr &= 0xffffff;
|
||||
break;
|
||||
case OPMODE_DBR:
|
||||
addr &= 0xffffff;
|
||||
addr = (regs.db << 16) + addr;
|
||||
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;
|
||||
}
|
||||
r = mem_bus->read(addr);
|
||||
clock->add_cc1_cycles(mem_bus->speed(addr));
|
||||
return r;
|
||||
}
|
||||
|
||||
void bCPU::op_write(uint8 mode, uint32 addr, uint8 value) {
|
||||
switch(mode) {
|
||||
case OPMODE_ADDR:
|
||||
addr &= 0xffff;
|
||||
break;
|
||||
case OPMODE_LONG:
|
||||
addr &= 0xffffff;
|
||||
break;
|
||||
case OPMODE_DBR:
|
||||
addr &= 0xffffff;
|
||||
addr = (regs.db << 16) + addr;
|
||||
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;
|
||||
}
|
||||
mem_bus->write(addr, value);
|
||||
clock->add_cc1_cycles(mem_bus->speed(addr));
|
||||
}
|
||||
|
||||
uint8 bCPU::stack_read() {
|
||||
byte r;
|
||||
if(regs.e) {
|
||||
regs.s.l++;
|
||||
} else {
|
||||
regs.s.w++;
|
||||
}
|
||||
r = mem_bus->read(regs.s);
|
||||
clock->add_cc1_cycles(mem_bus->speed(regs.s));
|
||||
return r;
|
||||
}
|
||||
|
||||
void bCPU::stack_write(uint8 value) {
|
||||
mem_bus->write(regs.s, value);
|
||||
clock->add_cc1_cycles(mem_bus->speed(regs.s));
|
||||
if(regs.e) {
|
||||
regs.s.l--;
|
||||
} else {
|
||||
regs.s.w--;
|
||||
}
|
||||
}
|
||||
|
||||
bCPU::bCPU() {
|
||||
dma = new bDMA(this);
|
||||
mmio = new bCPUMMIO(this);
|
||||
}
|
||||
|
||||
bCPU::~bCPU() {
|
||||
delete(mmio);
|
||||
delete(dma);
|
||||
}
|
||||
@@ -1,880 +0,0 @@
|
||||
class bCPU;
|
||||
|
||||
class bDMA {
|
||||
public:
|
||||
bCPU *cpu;
|
||||
struct {
|
||||
//$420b
|
||||
bool active;
|
||||
//$420c
|
||||
bool hdma_active;
|
||||
//$43x0
|
||||
bool direction;
|
||||
bool hdma_indirect;
|
||||
int8 incmode;
|
||||
bool fixedxfer;
|
||||
uint8 xfermode;
|
||||
//$43x1
|
||||
uint8 destaddr;
|
||||
//$43x2-$43x4
|
||||
uint32 srcaddr;
|
||||
//$43x5-$43x6
|
||||
uint16 xfersize;
|
||||
//$43x7
|
||||
uint8 hdma_indirect_bank;
|
||||
|
||||
//hdma-specific
|
||||
bool hdma_first_line;
|
||||
bool hdma_repeat;
|
||||
uint16 hdma_line_counter;
|
||||
uint32 hdma_address, hdma_iaddress;
|
||||
bool hdma_completed;
|
||||
}channel[8];
|
||||
bool hdma_triggered;
|
||||
|
||||
void hdma_write(uint8 i, uint8 l, uint8 x);
|
||||
void hdma_run();
|
||||
void hdma_initialize();
|
||||
void run();
|
||||
void reset();
|
||||
uint16 dma_cputommio(uint8 i, uint8 index);
|
||||
uint16 dma_mmiotocpu(uint8 i, uint8 index);
|
||||
void dma_xfer_type0(uint8 i);
|
||||
void dma_xfer_type1(uint8 i);
|
||||
void dma_xfer_type2(uint8 i);
|
||||
void dma_xfer_type3(uint8 i);
|
||||
void dma_xfer_type4(uint8 i);
|
||||
void dma_xfer_type5(uint8 i);
|
||||
|
||||
bDMA(bCPU *_cpu);
|
||||
};
|
||||
|
||||
class bCPUMMIO : public MMIO {
|
||||
public:
|
||||
bCPU *cpu;
|
||||
uint8 read (uint32 addr);
|
||||
void write(uint32 addr, uint8 value);
|
||||
bCPUMMIO(bCPU *_cpu);
|
||||
};
|
||||
|
||||
class bCPU : public CPU {
|
||||
public:
|
||||
enum { CPUSTATE_RUN = 0, CPUSTATE_DMA, CPUSTATE_WAI, CPUSTATE_STP };
|
||||
uint8 cpustate;
|
||||
|
||||
bDMA *dma;
|
||||
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;
|
||||
|
||||
struct {
|
||||
bool nmi_triggered;
|
||||
bool nmi_pin;
|
||||
bool r4210_read;
|
||||
|
||||
bool irq_triggered;
|
||||
bool irq_pin;
|
||||
|
||||
//$2181-$2183
|
||||
uint32 wram_addr;
|
||||
|
||||
//$4016
|
||||
uint8 joypad1_strobe_value;
|
||||
uint8 joypad1_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;
|
||||
|
||||
uint8 pio_status();
|
||||
void irq(uint16 addr);
|
||||
void run();
|
||||
void scanline();
|
||||
void frame();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
//mmio commands
|
||||
void mmio_reset();
|
||||
uint8 mmio_r2180();
|
||||
uint8 mmio_r21c2();
|
||||
uint8 mmio_r21c3();
|
||||
uint8 mmio_r4016();
|
||||
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();
|
||||
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_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 exec_opcode();
|
||||
|
||||
uint8 op_read ();
|
||||
uint8 op_read (uint8 mode, uint32 addr);
|
||||
void op_write(uint8 mode, uint32 addr, uint8 value);
|
||||
uint8 stack_read ();
|
||||
void stack_write(uint8 value);
|
||||
|
||||
//cpu extra-cycle conditions
|
||||
void cpu_c2();
|
||||
void cpu_c4(uint16 a, uint16 b);
|
||||
void cpu_c6(uint16 a);
|
||||
void cpu_io();
|
||||
|
||||
//op_adc
|
||||
void flags_adc_b();
|
||||
void flags_adc_w();
|
||||
void op_adc_constb();
|
||||
void op_adc_constw();
|
||||
void op_adc_const();
|
||||
void op_adc_addrb();
|
||||
void op_adc_addrw();
|
||||
void op_adc_addr();
|
||||
void op_adc_addrxb();
|
||||
void op_adc_addrxw();
|
||||
void op_adc_addrx();
|
||||
void op_adc_dpb();
|
||||
void op_adc_dpw();
|
||||
void op_adc_dp();
|
||||
void op_adc_idpb();
|
||||
void op_adc_idpw();
|
||||
void op_adc_idp();
|
||||
void op_adc_ildpb();
|
||||
void op_adc_ildpw();
|
||||
void op_adc_ildp();
|
||||
void op_adc_longb();
|
||||
void op_adc_longw();
|
||||
void op_adc_long();
|
||||
void op_adc_longxb();
|
||||
void op_adc_longxw();
|
||||
void op_adc_longx();
|
||||
void op_adc_addryb();
|
||||
void op_adc_addryw();
|
||||
void op_adc_addry();
|
||||
void op_adc_dpxb();
|
||||
void op_adc_dpxw();
|
||||
void op_adc_dpx();
|
||||
void op_adc_idpxb();
|
||||
void op_adc_idpxw();
|
||||
void op_adc_idpx();
|
||||
void op_adc_idpyb();
|
||||
void op_adc_idpyw();
|
||||
void op_adc_idpy();
|
||||
void op_adc_ildpyb();
|
||||
void op_adc_ildpyw();
|
||||
void op_adc_ildpy();
|
||||
void op_adc_srb();
|
||||
void op_adc_srw();
|
||||
void op_adc_sr();
|
||||
void op_adc_isryb();
|
||||
void op_adc_isryw();
|
||||
void op_adc_isry();
|
||||
//op_and
|
||||
void flags_and_b();
|
||||
void flags_and_w();
|
||||
void op_and_constb();
|
||||
void op_and_constw();
|
||||
void op_and_const();
|
||||
void op_and_addrb();
|
||||
void op_and_addrw();
|
||||
void op_and_addr();
|
||||
void op_and_addrxb();
|
||||
void op_and_addrxw();
|
||||
void op_and_addrx();
|
||||
void op_and_dpb();
|
||||
void op_and_dpw();
|
||||
void op_and_dp();
|
||||
void op_and_idpb();
|
||||
void op_and_idpw();
|
||||
void op_and_idp();
|
||||
void op_and_ildpb();
|
||||
void op_and_ildpw();
|
||||
void op_and_ildp();
|
||||
void op_and_longb();
|
||||
void op_and_longw();
|
||||
void op_and_long();
|
||||
void op_and_longxb();
|
||||
void op_and_longxw();
|
||||
void op_and_longx();
|
||||
void op_and_addryb();
|
||||
void op_and_addryw();
|
||||
void op_and_addry();
|
||||
void op_and_dpxb();
|
||||
void op_and_dpxw();
|
||||
void op_and_dpx();
|
||||
void op_and_idpxb();
|
||||
void op_and_idpxw();
|
||||
void op_and_idpx();
|
||||
void op_and_idpyb();
|
||||
void op_and_idpyw();
|
||||
void op_and_idpy();
|
||||
void op_and_ildpyb();
|
||||
void op_and_ildpyw();
|
||||
void op_and_ildpy();
|
||||
void op_and_srb();
|
||||
void op_and_srw();
|
||||
void op_and_sr();
|
||||
void op_and_isryb();
|
||||
void op_and_isryw();
|
||||
void op_and_isry();
|
||||
//op_cmp
|
||||
void flags_cmp_b();
|
||||
void flags_cmp_w();
|
||||
void op_cmp_constb();
|
||||
void op_cmp_constw();
|
||||
void op_cmp_const();
|
||||
void op_cmp_addrb();
|
||||
void op_cmp_addrw();
|
||||
void op_cmp_addr();
|
||||
void op_cmp_addrxb();
|
||||
void op_cmp_addrxw();
|
||||
void op_cmp_addrx();
|
||||
void op_cmp_dpb();
|
||||
void op_cmp_dpw();
|
||||
void op_cmp_dp();
|
||||
void op_cmp_idpb();
|
||||
void op_cmp_idpw();
|
||||
void op_cmp_idp();
|
||||
void op_cmp_ildpb();
|
||||
void op_cmp_ildpw();
|
||||
void op_cmp_ildp();
|
||||
void op_cmp_longb();
|
||||
void op_cmp_longw();
|
||||
void op_cmp_long();
|
||||
void op_cmp_longxb();
|
||||
void op_cmp_longxw();
|
||||
void op_cmp_longx();
|
||||
void op_cmp_addryb();
|
||||
void op_cmp_addryw();
|
||||
void op_cmp_addry();
|
||||
void op_cmp_dpxb();
|
||||
void op_cmp_dpxw();
|
||||
void op_cmp_dpx();
|
||||
void op_cmp_idpxb();
|
||||
void op_cmp_idpxw();
|
||||
void op_cmp_idpx();
|
||||
void op_cmp_idpyb();
|
||||
void op_cmp_idpyw();
|
||||
void op_cmp_idpy();
|
||||
void op_cmp_ildpyb();
|
||||
void op_cmp_ildpyw();
|
||||
void op_cmp_ildpy();
|
||||
void op_cmp_srb();
|
||||
void op_cmp_srw();
|
||||
void op_cmp_sr();
|
||||
void op_cmp_isryb();
|
||||
void op_cmp_isryw();
|
||||
void op_cmp_isry();
|
||||
//op_eor
|
||||
void flags_eor_b();
|
||||
void flags_eor_w();
|
||||
void op_eor_constb();
|
||||
void op_eor_constw();
|
||||
void op_eor_const();
|
||||
void op_eor_addrb();
|
||||
void op_eor_addrw();
|
||||
void op_eor_addr();
|
||||
void op_eor_addrxb();
|
||||
void op_eor_addrxw();
|
||||
void op_eor_addrx();
|
||||
void op_eor_dpb();
|
||||
void op_eor_dpw();
|
||||
void op_eor_dp();
|
||||
void op_eor_idpb();
|
||||
void op_eor_idpw();
|
||||
void op_eor_idp();
|
||||
void op_eor_ildpb();
|
||||
void op_eor_ildpw();
|
||||
void op_eor_ildp();
|
||||
void op_eor_longb();
|
||||
void op_eor_longw();
|
||||
void op_eor_long();
|
||||
void op_eor_longxb();
|
||||
void op_eor_longxw();
|
||||
void op_eor_longx();
|
||||
void op_eor_addryb();
|
||||
void op_eor_addryw();
|
||||
void op_eor_addry();
|
||||
void op_eor_dpxb();
|
||||
void op_eor_dpxw();
|
||||
void op_eor_dpx();
|
||||
void op_eor_idpxb();
|
||||
void op_eor_idpxw();
|
||||
void op_eor_idpx();
|
||||
void op_eor_idpyb();
|
||||
void op_eor_idpyw();
|
||||
void op_eor_idpy();
|
||||
void op_eor_ildpyb();
|
||||
void op_eor_ildpyw();
|
||||
void op_eor_ildpy();
|
||||
void op_eor_srb();
|
||||
void op_eor_srw();
|
||||
void op_eor_sr();
|
||||
void op_eor_isryb();
|
||||
void op_eor_isryw();
|
||||
void op_eor_isry();
|
||||
//op_incdec
|
||||
void op_incb();
|
||||
void op_incw();
|
||||
void op_inc();
|
||||
void op_inc_addrb();
|
||||
void op_inc_addrw();
|
||||
void op_inc_addr();
|
||||
void op_inc_addrxb();
|
||||
void op_inc_addrxw();
|
||||
void op_inc_addrx();
|
||||
void op_inc_dpb();
|
||||
void op_inc_dpw();
|
||||
void op_inc_dp();
|
||||
void op_inc_dpxb();
|
||||
void op_inc_dpxw();
|
||||
void op_inc_dpx();
|
||||
void op_inxb();
|
||||
void op_inxw();
|
||||
void op_inx();
|
||||
void op_inyb();
|
||||
void op_inyw();
|
||||
void op_iny();
|
||||
void op_decb();
|
||||
void op_decw();
|
||||
void op_dec();
|
||||
void op_dec_addrb();
|
||||
void op_dec_addrw();
|
||||
void op_dec_addr();
|
||||
void op_dec_addrxb();
|
||||
void op_dec_addrxw();
|
||||
void op_dec_addrx();
|
||||
void op_dec_dpb();
|
||||
void op_dec_dpw();
|
||||
void op_dec_dp();
|
||||
void op_dec_dpxb();
|
||||
void op_dec_dpxw();
|
||||
void op_dec_dpx();
|
||||
void op_dexb();
|
||||
void op_dexw();
|
||||
void op_dex();
|
||||
void op_deyb();
|
||||
void op_deyw();
|
||||
void op_dey();
|
||||
//op_lda
|
||||
void flags_lda_b();
|
||||
void flags_lda_w();
|
||||
void op_lda_constb();
|
||||
void op_lda_constw();
|
||||
void op_lda_const();
|
||||
void op_lda_addrb();
|
||||
void op_lda_addrw();
|
||||
void op_lda_addr();
|
||||
void op_lda_addrxb();
|
||||
void op_lda_addrxw();
|
||||
void op_lda_addrx();
|
||||
void op_lda_dpb();
|
||||
void op_lda_dpw();
|
||||
void op_lda_dp();
|
||||
void op_lda_idpb();
|
||||
void op_lda_idpw();
|
||||
void op_lda_idp();
|
||||
void op_lda_ildpb();
|
||||
void op_lda_ildpw();
|
||||
void op_lda_ildp();
|
||||
void op_lda_longb();
|
||||
void op_lda_longw();
|
||||
void op_lda_long();
|
||||
void op_lda_longxb();
|
||||
void op_lda_longxw();
|
||||
void op_lda_longx();
|
||||
void op_lda_addryb();
|
||||
void op_lda_addryw();
|
||||
void op_lda_addry();
|
||||
void op_lda_dpxb();
|
||||
void op_lda_dpxw();
|
||||
void op_lda_dpx();
|
||||
void op_lda_idpxb();
|
||||
void op_lda_idpxw();
|
||||
void op_lda_idpx();
|
||||
void op_lda_idpyb();
|
||||
void op_lda_idpyw();
|
||||
void op_lda_idpy();
|
||||
void op_lda_ildpyb();
|
||||
void op_lda_ildpyw();
|
||||
void op_lda_ildpy();
|
||||
void op_lda_srb();
|
||||
void op_lda_srw();
|
||||
void op_lda_sr();
|
||||
void op_lda_isryb();
|
||||
void op_lda_isryw();
|
||||
void op_lda_isry();
|
||||
//op_misc
|
||||
void flags_bit_b();
|
||||
void flags_bit_w();
|
||||
void op_bit_constb();
|
||||
void op_bit_constw();
|
||||
void op_bit_const();
|
||||
void op_bit_addrb();
|
||||
void op_bit_addrw();
|
||||
void op_bit_addr();
|
||||
void op_bit_addrxb();
|
||||
void op_bit_addrxw();
|
||||
void op_bit_addrx();
|
||||
void op_bit_dpb();
|
||||
void op_bit_dpw();
|
||||
void op_bit_dp();
|
||||
void op_bit_dpxb();
|
||||
void op_bit_dpxw();
|
||||
void op_bit_dpx();
|
||||
void flags_cpx_b();
|
||||
void flags_cpx_w();
|
||||
void op_cpx_constb();
|
||||
void op_cpx_constw();
|
||||
void op_cpx_const();
|
||||
void op_cpx_addrb();
|
||||
void op_cpx_addrw();
|
||||
void op_cpx_addr();
|
||||
void op_cpx_dpb();
|
||||
void op_cpx_dpw();
|
||||
void op_cpx_dp();
|
||||
void flags_cpy_b();
|
||||
void flags_cpy_w();
|
||||
void op_cpy_constb();
|
||||
void op_cpy_constw();
|
||||
void op_cpy_const();
|
||||
void op_cpy_addrb();
|
||||
void op_cpy_addrw();
|
||||
void op_cpy_addr();
|
||||
void op_cpy_dpb();
|
||||
void op_cpy_dpw();
|
||||
void op_cpy_dp();
|
||||
void flags_ldx_b();
|
||||
void flags_ldx_w();
|
||||
void op_ldx_constb();
|
||||
void op_ldx_constw();
|
||||
void op_ldx_const();
|
||||
void op_ldx_addrb();
|
||||
void op_ldx_addrw();
|
||||
void op_ldx_addr();
|
||||
void op_ldx_addryb();
|
||||
void op_ldx_addryw();
|
||||
void op_ldx_addry();
|
||||
void op_ldx_dpb();
|
||||
void op_ldx_dpw();
|
||||
void op_ldx_dp();
|
||||
void op_ldx_dpyb();
|
||||
void op_ldx_dpyw();
|
||||
void op_ldx_dpy();
|
||||
void flags_ldy_b();
|
||||
void flags_ldy_w();
|
||||
void op_ldy_constb();
|
||||
void op_ldy_constw();
|
||||
void op_ldy_const();
|
||||
void op_ldy_addrb();
|
||||
void op_ldy_addrw();
|
||||
void op_ldy_addr();
|
||||
void op_ldy_addrxb();
|
||||
void op_ldy_addrxw();
|
||||
void op_ldy_addrx();
|
||||
void op_ldy_dpb();
|
||||
void op_ldy_dpw();
|
||||
void op_ldy_dp();
|
||||
void op_ldy_dpxb();
|
||||
void op_ldy_dpxw();
|
||||
void op_ldy_dpx();
|
||||
void op_stx_addrb();
|
||||
void op_stx_addrw();
|
||||
void op_stx_addr();
|
||||
void op_stx_dpb();
|
||||
void op_stx_dpw();
|
||||
void op_stx_dp();
|
||||
void op_stx_dpyb();
|
||||
void op_stx_dpyw();
|
||||
void op_stx_dpy();
|
||||
void op_sty_addrb();
|
||||
void op_sty_addrw();
|
||||
void op_sty_addr();
|
||||
void op_sty_dpb();
|
||||
void op_sty_dpw();
|
||||
void op_sty_dp();
|
||||
void op_sty_dpxb();
|
||||
void op_sty_dpxw();
|
||||
void op_sty_dpx();
|
||||
void op_stz_addrb();
|
||||
void op_stz_addrw();
|
||||
void op_stz_addr();
|
||||
void op_stz_addrxb();
|
||||
void op_stz_addrxw();
|
||||
void op_stz_addrx();
|
||||
void op_stz_dpb();
|
||||
void op_stz_dpw();
|
||||
void op_stz_dp();
|
||||
void op_stz_dpxb();
|
||||
void op_stz_dpxw();
|
||||
void op_stz_dpx();
|
||||
void op_xba();
|
||||
void op_trb_addrb();
|
||||
void op_trb_addrw();
|
||||
void op_trb_addr();
|
||||
void op_trb_dpb();
|
||||
void op_trb_dpw();
|
||||
void op_trb_dp();
|
||||
void op_tsb_addrb();
|
||||
void op_tsb_addrw();
|
||||
void op_tsb_addr();
|
||||
void op_tsb_dpb();
|
||||
void op_tsb_dpw();
|
||||
void op_tsb_dp();
|
||||
void op_mvn();
|
||||
void op_mvp();
|
||||
void op_brk();
|
||||
void op_cop();
|
||||
void op_stp();
|
||||
void op_wai();
|
||||
void op_xce();
|
||||
void op_nop();
|
||||
void op_wdm();
|
||||
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_taxb();
|
||||
void op_taxw();
|
||||
void op_tax();
|
||||
void op_tayb();
|
||||
void op_tayw();
|
||||
void op_tay();
|
||||
void op_tcd();
|
||||
void op_tcs();
|
||||
void op_tdc();
|
||||
void op_tsc();
|
||||
void op_tsxb();
|
||||
void op_tsxw();
|
||||
void op_tsx();
|
||||
void op_txab();
|
||||
void op_txaw();
|
||||
void op_txa();
|
||||
void op_txsb();
|
||||
void op_txsw();
|
||||
void op_txs();
|
||||
void op_txyb();
|
||||
void op_txyw();
|
||||
void op_txy();
|
||||
void op_tyab();
|
||||
void op_tyaw();
|
||||
void op_tya();
|
||||
void op_tyxb();
|
||||
void op_tyxw();
|
||||
void op_tyx();
|
||||
//op_ora
|
||||
void flags_ora_b();
|
||||
void flags_ora_w();
|
||||
void op_ora_constb();
|
||||
void op_ora_constw();
|
||||
void op_ora_const();
|
||||
void op_ora_addrb();
|
||||
void op_ora_addrw();
|
||||
void op_ora_addr();
|
||||
void op_ora_addrxb();
|
||||
void op_ora_addrxw();
|
||||
void op_ora_addrx();
|
||||
void op_ora_dpb();
|
||||
void op_ora_dpw();
|
||||
void op_ora_dp();
|
||||
void op_ora_idpb();
|
||||
void op_ora_idpw();
|
||||
void op_ora_idp();
|
||||
void op_ora_ildpb();
|
||||
void op_ora_ildpw();
|
||||
void op_ora_ildp();
|
||||
void op_ora_longb();
|
||||
void op_ora_longw();
|
||||
void op_ora_long();
|
||||
void op_ora_longxb();
|
||||
void op_ora_longxw();
|
||||
void op_ora_longx();
|
||||
void op_ora_addryb();
|
||||
void op_ora_addryw();
|
||||
void op_ora_addry();
|
||||
void op_ora_dpxb();
|
||||
void op_ora_dpxw();
|
||||
void op_ora_dpx();
|
||||
void op_ora_idpxb();
|
||||
void op_ora_idpxw();
|
||||
void op_ora_idpx();
|
||||
void op_ora_idpyb();
|
||||
void op_ora_idpyw();
|
||||
void op_ora_idpy();
|
||||
void op_ora_ildpyb();
|
||||
void op_ora_ildpyw();
|
||||
void op_ora_ildpy();
|
||||
void op_ora_srb();
|
||||
void op_ora_srw();
|
||||
void op_ora_sr();
|
||||
void op_ora_isryb();
|
||||
void op_ora_isryw();
|
||||
void op_ora_isry();
|
||||
//op_pc
|
||||
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_rtie();
|
||||
void op_rtin();
|
||||
void op_rti();
|
||||
void op_rts();
|
||||
void op_rtl();
|
||||
void op_bra();
|
||||
void op_brl();
|
||||
void op_bcc();
|
||||
void op_bcs();
|
||||
void op_bne();
|
||||
void op_beq();
|
||||
void op_bpl();
|
||||
void op_bmi();
|
||||
void op_bvc();
|
||||
void op_bvs();
|
||||
//op_sbc
|
||||
void flags_sbc_b();
|
||||
void flags_sbc_w();
|
||||
void op_sbc_constb();
|
||||
void op_sbc_constw();
|
||||
void op_sbc_const();
|
||||
void op_sbc_addrb();
|
||||
void op_sbc_addrw();
|
||||
void op_sbc_addr();
|
||||
void op_sbc_addrxb();
|
||||
void op_sbc_addrxw();
|
||||
void op_sbc_addrx();
|
||||
void op_sbc_dpb();
|
||||
void op_sbc_dpw();
|
||||
void op_sbc_dp();
|
||||
void op_sbc_idpb();
|
||||
void op_sbc_idpw();
|
||||
void op_sbc_idp();
|
||||
void op_sbc_ildpb();
|
||||
void op_sbc_ildpw();
|
||||
void op_sbc_ildp();
|
||||
void op_sbc_longb();
|
||||
void op_sbc_longw();
|
||||
void op_sbc_long();
|
||||
void op_sbc_longxb();
|
||||
void op_sbc_longxw();
|
||||
void op_sbc_longx();
|
||||
void op_sbc_addryb();
|
||||
void op_sbc_addryw();
|
||||
void op_sbc_addry();
|
||||
void op_sbc_dpxb();
|
||||
void op_sbc_dpxw();
|
||||
void op_sbc_dpx();
|
||||
void op_sbc_idpxb();
|
||||
void op_sbc_idpxw();
|
||||
void op_sbc_idpx();
|
||||
void op_sbc_idpyb();
|
||||
void op_sbc_idpyw();
|
||||
void op_sbc_idpy();
|
||||
void op_sbc_ildpyb();
|
||||
void op_sbc_ildpyw();
|
||||
void op_sbc_ildpy();
|
||||
void op_sbc_srb();
|
||||
void op_sbc_srw();
|
||||
void op_sbc_sr();
|
||||
void op_sbc_isryb();
|
||||
void op_sbc_isryw();
|
||||
void op_sbc_isry();
|
||||
//op_shift
|
||||
void op_aslb();
|
||||
void op_aslw();
|
||||
void op_asl();
|
||||
void op_asl_addrb();
|
||||
void op_asl_addrw();
|
||||
void op_asl_addr();
|
||||
void op_asl_addrxb();
|
||||
void op_asl_addrxw();
|
||||
void op_asl_addrx();
|
||||
void op_asl_dpb();
|
||||
void op_asl_dpw();
|
||||
void op_asl_dp();
|
||||
void op_asl_dpxb();
|
||||
void op_asl_dpxw();
|
||||
void op_asl_dpx();
|
||||
void op_lsrb();
|
||||
void op_lsrw();
|
||||
void op_lsr();
|
||||
void op_lsr_addrb();
|
||||
void op_lsr_addrw();
|
||||
void op_lsr_addr();
|
||||
void op_lsr_addrxb();
|
||||
void op_lsr_addrxw();
|
||||
void op_lsr_addrx();
|
||||
void op_lsr_dpb();
|
||||
void op_lsr_dpw();
|
||||
void op_lsr_dp();
|
||||
void op_lsr_dpxb();
|
||||
void op_lsr_dpxw();
|
||||
void op_lsr_dpx();
|
||||
void op_rolb();
|
||||
void op_rolw();
|
||||
void op_rol();
|
||||
void op_rol_addrb();
|
||||
void op_rol_addrw();
|
||||
void op_rol_addr();
|
||||
void op_rol_addrxb();
|
||||
void op_rol_addrxw();
|
||||
void op_rol_addrx();
|
||||
void op_rol_dpb();
|
||||
void op_rol_dpw();
|
||||
void op_rol_dp();
|
||||
void op_rol_dpxb();
|
||||
void op_rol_dpxw();
|
||||
void op_rol_dpx();
|
||||
void op_rorb();
|
||||
void op_rorw();
|
||||
void op_ror();
|
||||
void op_ror_addrb();
|
||||
void op_ror_addrw();
|
||||
void op_ror_addr();
|
||||
void op_ror_addrxb();
|
||||
void op_ror_addrxw();
|
||||
void op_ror_addrx();
|
||||
void op_ror_dpb();
|
||||
void op_ror_dpw();
|
||||
void op_ror_dp();
|
||||
void op_ror_dpxb();
|
||||
void op_ror_dpxw();
|
||||
void op_ror_dpx();
|
||||
//op_sta
|
||||
void op_sta_addrb();
|
||||
void op_sta_addrw();
|
||||
void op_sta_addr();
|
||||
void op_sta_addrxb();
|
||||
void op_sta_addrxw();
|
||||
void op_sta_addrx();
|
||||
void op_sta_dpb();
|
||||
void op_sta_dpw();
|
||||
void op_sta_dp();
|
||||
void op_sta_idpb();
|
||||
void op_sta_idpw();
|
||||
void op_sta_idp();
|
||||
void op_sta_ildpb();
|
||||
void op_sta_ildpw();
|
||||
void op_sta_ildp();
|
||||
void op_sta_longb();
|
||||
void op_sta_longw();
|
||||
void op_sta_long();
|
||||
void op_sta_longxb();
|
||||
void op_sta_longxw();
|
||||
void op_sta_longx();
|
||||
void op_sta_addryb();
|
||||
void op_sta_addryw();
|
||||
void op_sta_addry();
|
||||
void op_sta_dpxb();
|
||||
void op_sta_dpxw();
|
||||
void op_sta_dpx();
|
||||
void op_sta_idpxb();
|
||||
void op_sta_idpxw();
|
||||
void op_sta_idpx();
|
||||
void op_sta_idpyb();
|
||||
void op_sta_idpyw();
|
||||
void op_sta_idpy();
|
||||
void op_sta_ildpyb();
|
||||
void op_sta_ildpyw();
|
||||
void op_sta_ildpy();
|
||||
void op_sta_srb();
|
||||
void op_sta_srw();
|
||||
void op_sta_sr();
|
||||
void op_sta_isryb();
|
||||
void op_sta_isryw();
|
||||
void op_sta_isry();
|
||||
//op_stack
|
||||
void op_phab();
|
||||
void op_phaw();
|
||||
void op_pha();
|
||||
void op_phb();
|
||||
void op_phd();
|
||||
void op_phk();
|
||||
void op_php();
|
||||
void op_phxb();
|
||||
void op_phxw();
|
||||
void op_phx();
|
||||
void op_phyb();
|
||||
void op_phyw();
|
||||
void op_phy();
|
||||
void op_plab();
|
||||
void op_plaw();
|
||||
void op_pla();
|
||||
void op_plb();
|
||||
void op_pld();
|
||||
void op_plp();
|
||||
void op_plxb();
|
||||
void op_plxw();
|
||||
void op_plx();
|
||||
void op_plyb();
|
||||
void op_plyw();
|
||||
void op_ply();
|
||||
void op_pea();
|
||||
void op_pei();
|
||||
void op_per();
|
||||
|
||||
bCPU();
|
||||
~bCPU();
|
||||
};
|
||||
@@ -1,280 +0,0 @@
|
||||
void bCPU::exec_opcode() {
|
||||
byte op;
|
||||
op = op_read();
|
||||
switch(op) {
|
||||
/* 0x */
|
||||
case 0x00:op_brk(); break;
|
||||
case 0x01:op_ora_idpx(); break;
|
||||
case 0x02:op_cop(); break;
|
||||
case 0x03:op_ora_sr(); break;
|
||||
case 0x04:op_tsb_dp(); break;
|
||||
case 0x05:op_ora_dp(); break;
|
||||
case 0x06:op_asl_dp(); break;
|
||||
case 0x07:op_ora_ildp(); break;
|
||||
case 0x08:op_php(); break;
|
||||
case 0x09:op_ora_const();break;
|
||||
case 0x0a:op_asl(); break;
|
||||
case 0x0b:op_phd(); break;
|
||||
case 0x0c:op_tsb_addr(); break;
|
||||
case 0x0d:op_ora_addr(); break;
|
||||
case 0x0e:op_asl_addr(); break;
|
||||
case 0x0f:op_ora_long(); break;
|
||||
/* 1x */
|
||||
case 0x10:op_bpl(); break;
|
||||
case 0x11:op_ora_idpy(); break;
|
||||
case 0x12:op_ora_idp(); break;
|
||||
case 0x13:op_ora_isry(); break;
|
||||
case 0x14:op_trb_dp(); break;
|
||||
case 0x15:op_ora_dpx(); break;
|
||||
case 0x16:op_asl_dpx(); break;
|
||||
case 0x17:op_ora_ildpy();break;
|
||||
case 0x18:op_clc(); break;
|
||||
case 0x19:op_ora_addry();break;
|
||||
case 0x1a:op_inc(); break;
|
||||
case 0x1b:op_tcs(); break;
|
||||
case 0x1c:op_trb_addr(); break;
|
||||
case 0x1d:op_ora_addrx();break;
|
||||
case 0x1e:op_asl_addrx();break;
|
||||
case 0x1f:op_ora_longx();break;
|
||||
/* 2x */
|
||||
case 0x20:op_jsr_addr(); break;
|
||||
case 0x21:op_and_idpx(); break;
|
||||
case 0x22:op_jsr_long(); break;
|
||||
case 0x23:op_and_sr(); break;
|
||||
case 0x24:op_bit_dp(); break;
|
||||
case 0x25:op_and_dp(); break;
|
||||
case 0x26:op_rol_dp(); break;
|
||||
case 0x27:op_and_ildp(); break;
|
||||
case 0x28:op_plp(); break;
|
||||
case 0x29:op_and_const();break;
|
||||
case 0x2a:op_rol(); break;
|
||||
case 0x2b:op_pld(); break;
|
||||
case 0x2c:op_bit_addr(); break;
|
||||
case 0x2d:op_and_addr(); break;
|
||||
case 0x2e:op_rol_addr(); break;
|
||||
case 0x2f:op_and_long(); break;
|
||||
/* 3x */
|
||||
case 0x30:op_bmi(); break;
|
||||
case 0x31:op_and_idpy(); break;
|
||||
case 0x32:op_and_idp(); break;
|
||||
case 0x33:op_and_isry(); break;
|
||||
case 0x34:op_bit_dpx(); break;
|
||||
case 0x35:op_and_dpx(); break;
|
||||
case 0x36:op_rol_dpx(); break;
|
||||
case 0x37:op_and_ildpy();break;
|
||||
case 0x38:op_sec(); break;
|
||||
case 0x39:op_and_addry();break;
|
||||
case 0x3a:op_dec(); break;
|
||||
case 0x3b:op_tsc(); break;
|
||||
case 0x3c:op_bit_addrx();break;
|
||||
case 0x3d:op_and_addrx();break;
|
||||
case 0x3e:op_rol_addrx();break;
|
||||
case 0x3f:op_and_longx();break;
|
||||
/* 4x */
|
||||
case 0x40:op_rti(); break;
|
||||
case 0x41:op_eor_idpx(); break;
|
||||
case 0x42:op_wdm(); break;
|
||||
case 0x43:op_eor_sr(); break;
|
||||
case 0x44:op_mvp(); break;
|
||||
case 0x45:op_eor_dp(); break;
|
||||
case 0x46:op_lsr_dp(); break;
|
||||
case 0x47:op_eor_ildp(); break;
|
||||
case 0x48:op_pha(); break;
|
||||
case 0x49:op_eor_const();break;
|
||||
case 0x4a:op_lsr(); break;
|
||||
case 0x4b:op_phk(); break;
|
||||
case 0x4c:op_jmp_addr(); break;
|
||||
case 0x4d:op_eor_addr(); break;
|
||||
case 0x4e:op_lsr_addr(); break;
|
||||
case 0x4f:op_eor_long(); break;
|
||||
/* 5x */
|
||||
case 0x50:op_bvc(); break;
|
||||
case 0x51:op_eor_idpy(); break;
|
||||
case 0x52:op_eor_idp(); break;
|
||||
case 0x53:op_eor_isry(); break;
|
||||
case 0x54:op_mvn(); break;
|
||||
case 0x55:op_eor_dpx(); break;
|
||||
case 0x56:op_lsr_dpx(); break;
|
||||
case 0x57:op_eor_ildpy();break;
|
||||
case 0x58:op_cli(); break;
|
||||
case 0x59:op_eor_addry();break;
|
||||
case 0x5a:op_phy(); break;
|
||||
case 0x5b:op_tcd(); break;
|
||||
case 0x5c:op_jmp_long(); break;
|
||||
case 0x5d:op_eor_addrx();break;
|
||||
case 0x5e:op_lsr_addrx();break;
|
||||
case 0x5f:op_eor_longx();break;
|
||||
/* 6x */
|
||||
case 0x60:op_rts(); break;
|
||||
case 0x61:op_adc_idpx(); break;
|
||||
case 0x62:op_per(); break;
|
||||
case 0x63:op_adc_sr(); break;
|
||||
case 0x64:op_stz_dp(); break;
|
||||
case 0x65:op_adc_dp(); break;
|
||||
case 0x66:op_ror_dp(); break;
|
||||
case 0x67:op_adc_ildp(); break;
|
||||
case 0x68:op_pla(); break;
|
||||
case 0x69:op_adc_const();break;
|
||||
case 0x6a:op_ror(); break;
|
||||
case 0x6b:op_rtl(); break;
|
||||
case 0x6c:op_jmp_iaddr();break;
|
||||
case 0x6d:op_adc_addr(); break;
|
||||
case 0x6e:op_ror_addr(); break;
|
||||
case 0x6f:op_adc_long(); break;
|
||||
/* 7x */
|
||||
case 0x70:op_bvs(); break;
|
||||
case 0x71:op_adc_idpy(); break;
|
||||
case 0x72:op_adc_idp(); break;
|
||||
case 0x73:op_adc_isry(); break;
|
||||
case 0x74:op_stz_dpx(); break;
|
||||
case 0x75:op_adc_dpx(); break;
|
||||
case 0x76:op_ror_dpx(); break;
|
||||
case 0x77:op_adc_ildpy(); break;
|
||||
case 0x78:op_sei(); break;
|
||||
case 0x79:op_adc_addry(); break;
|
||||
case 0x7a:op_ply(); break;
|
||||
case 0x7b:op_tdc(); break;
|
||||
case 0x7c:op_jmp_iaddrx();break;
|
||||
case 0x7d:op_adc_addrx(); break;
|
||||
case 0x7e:op_ror_addrx(); break;
|
||||
case 0x7f:op_adc_longx(); break;
|
||||
/* 8x */
|
||||
case 0x80:op_bra(); break;
|
||||
case 0x81:op_sta_idpx(); break;
|
||||
case 0x82:op_brl(); break;
|
||||
case 0x83:op_sta_sr(); break;
|
||||
case 0x84:op_sty_dp(); break;
|
||||
case 0x85:op_sta_dp(); break;
|
||||
case 0x86:op_stx_dp(); break;
|
||||
case 0x87:op_sta_ildp(); break;
|
||||
case 0x88:op_dey(); break;
|
||||
case 0x89:op_bit_const();break;
|
||||
case 0x8a:op_txa(); break;
|
||||
case 0x8b:op_phb(); break;
|
||||
case 0x8c:op_sty_addr(); break;
|
||||
case 0x8d:op_sta_addr(); break;
|
||||
case 0x8e:op_stx_addr(); break;
|
||||
case 0x8f:op_sta_long(); break;
|
||||
/* 9x */
|
||||
case 0x90:op_bcc(); break;
|
||||
case 0x91:op_sta_idpy(); break;
|
||||
case 0x92:op_sta_idp(); break;
|
||||
case 0x93:op_sta_isry(); break;
|
||||
case 0x94:op_sty_dpx(); break;
|
||||
case 0x95:op_sta_dpx(); break;
|
||||
case 0x96:op_stx_dpy(); break;
|
||||
case 0x97:op_sta_ildpy();break;
|
||||
case 0x98:op_tya(); break;
|
||||
case 0x99:op_sta_addry();break;
|
||||
case 0x9a:op_txs(); break;
|
||||
case 0x9b:op_txy(); break;
|
||||
case 0x9c:op_stz_addr(); break;
|
||||
case 0x9d:op_sta_addrx();break;
|
||||
case 0x9e:op_stz_addrx();break;
|
||||
case 0x9f:op_sta_longx();break;
|
||||
/* ax */
|
||||
case 0xa0:op_ldy_const();break;
|
||||
case 0xa1:op_lda_idpx(); break;
|
||||
case 0xa2:op_ldx_const();break;
|
||||
case 0xa3:op_lda_sr(); break;
|
||||
case 0xa4:op_ldy_dp(); break;
|
||||
case 0xa5:op_lda_dp(); break;
|
||||
case 0xa6:op_ldx_dp(); break;
|
||||
case 0xa7:op_lda_ildp(); break;
|
||||
case 0xa8:op_tay(); break;
|
||||
case 0xa9:op_lda_const();break;
|
||||
case 0xaa:op_tax(); break;
|
||||
case 0xab:op_plb(); break;
|
||||
case 0xac:op_ldy_addr(); break;
|
||||
case 0xad:op_lda_addr(); break;
|
||||
case 0xae:op_ldx_addr(); break;
|
||||
case 0xaf:op_lda_long(); break;
|
||||
/* bx */
|
||||
case 0xb0:op_bcs(); break;
|
||||
case 0xb1:op_lda_idpy(); break;
|
||||
case 0xb2:op_lda_idp(); break;
|
||||
case 0xb3:op_lda_isry(); break;
|
||||
case 0xb4:op_ldy_dpx(); break;
|
||||
case 0xb5:op_lda_dpx(); break;
|
||||
case 0xb6:op_ldx_dpy(); break;
|
||||
case 0xb7:op_lda_ildpy();break;
|
||||
case 0xb8:op_clv(); break;
|
||||
case 0xb9:op_lda_addry();break;
|
||||
case 0xba:op_tsx(); break;
|
||||
case 0xbb:op_tyx(); break;
|
||||
case 0xbc:op_ldy_addrx();break;
|
||||
case 0xbd:op_lda_addrx();break;
|
||||
case 0xbe:op_ldx_addry();break;
|
||||
case 0xbf:op_lda_longx();break;
|
||||
/* cx */
|
||||
case 0xc0:op_cpy_const();break;
|
||||
case 0xc1:op_cmp_idpx(); break;
|
||||
case 0xc2:op_rep(); break;
|
||||
case 0xc3:op_cmp_sr(); break;
|
||||
case 0xc4:op_cpy_dp(); break;
|
||||
case 0xc5:op_cmp_dp(); break;
|
||||
case 0xc6:op_dec_dp(); break;
|
||||
case 0xc7:op_cmp_ildp(); break;
|
||||
case 0xc8:op_iny(); break;
|
||||
case 0xc9:op_cmp_const();break;
|
||||
case 0xca:op_dex(); break;
|
||||
case 0xcb:op_wai(); break;
|
||||
case 0xcc:op_cpy_addr(); break;
|
||||
case 0xcd:op_cmp_addr(); break;
|
||||
case 0xce:op_dec_addr(); break;
|
||||
case 0xcf:op_cmp_long(); break;
|
||||
/* dx */
|
||||
case 0xd0:op_bne(); break;
|
||||
case 0xd1:op_cmp_idpy(); break;
|
||||
case 0xd2:op_cmp_idp(); break;
|
||||
case 0xd3:op_cmp_isry(); break;
|
||||
case 0xd4:op_pei(); break;
|
||||
case 0xd5:op_cmp_dpx(); break;
|
||||
case 0xd6:op_dec_dpx(); break;
|
||||
case 0xd7:op_cmp_ildpy(); break;
|
||||
case 0xd8:op_cld(); break;
|
||||
case 0xd9:op_cmp_addry(); break;
|
||||
case 0xda:op_phx(); break;
|
||||
case 0xdb:op_stp(); break;
|
||||
case 0xdc:op_jmp_iladdr();break;
|
||||
case 0xdd:op_cmp_addrx(); break;
|
||||
case 0xde:op_dec_addrx(); break;
|
||||
case 0xdf:op_cmp_longx(); break;
|
||||
/* ex */
|
||||
case 0xe0:op_cpx_const();break;
|
||||
case 0xe1:op_sbc_idpx(); break;
|
||||
case 0xe2:op_sep(); break;
|
||||
case 0xe3:op_sbc_sr(); break;
|
||||
case 0xe4:op_cpx_dp(); break;
|
||||
case 0xe5:op_sbc_dp(); break;
|
||||
case 0xe6:op_inc_dp(); break;
|
||||
case 0xe7:op_sbc_ildp(); break;
|
||||
case 0xe8:op_inx(); break;
|
||||
case 0xe9:op_sbc_const();break;
|
||||
case 0xea:op_nop(); break;
|
||||
case 0xeb:op_xba(); break;
|
||||
case 0xec:op_cpx_addr(); break;
|
||||
case 0xed:op_sbc_addr(); break;
|
||||
case 0xee:op_inc_addr(); break;
|
||||
case 0xef:op_sbc_long(); break;
|
||||
/* fx */
|
||||
case 0xf0:op_beq(); break;
|
||||
case 0xf1:op_sbc_idpy(); break;
|
||||
case 0xf2:op_sbc_idp(); break;
|
||||
case 0xf3:op_sbc_isry(); break;
|
||||
case 0xf4:op_pea(); break;
|
||||
case 0xf5:op_sbc_dpx(); break;
|
||||
case 0xf6:op_inc_dpx(); break;
|
||||
case 0xf7:op_sbc_ildpy(); break;
|
||||
case 0xf8:op_sed(); break;
|
||||
case 0xf9:op_sbc_addry(); break;
|
||||
case 0xfa:op_plx(); break;
|
||||
case 0xfb:op_xce(); break;
|
||||
case 0xfc:op_jsr_iaddrx();break;
|
||||
case 0xfd:op_sbc_addrx(); break;
|
||||
case 0xfe:op_inc_addrx(); break;
|
||||
case 0xff:op_sbc_longx(); break;
|
||||
}
|
||||
|
||||
snes->notify(SNES::CPU_EXEC_OPCODE);
|
||||
}
|
||||
@@ -1,698 +0,0 @@
|
||||
void bCPU::mmio_reset() {
|
||||
//$2181-$2183
|
||||
status.wram_addr = 0x000000;
|
||||
|
||||
//$4016
|
||||
status.joypad1_strobe_value = 0x00;
|
||||
status.joypad1_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;
|
||||
}
|
||||
|
||||
//???
|
||||
uint8 bCPU::mmio_r21c2() {
|
||||
return 0x20;
|
||||
}
|
||||
|
||||
//???
|
||||
uint8 bCPU::mmio_r21c3() {
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
//JOYSER0
|
||||
uint8 bCPU::mmio_r4016() {
|
||||
uint8 r = 0x00;
|
||||
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;
|
||||
}
|
||||
|
||||
//RDNMI
|
||||
uint8 bCPU::mmio_r4210() {
|
||||
uint8 r = 0x00;
|
||||
uint16 v, h, hcycles, visible_scanlines;
|
||||
v = clock->vcounter();
|
||||
h = clock->hcounter();
|
||||
hcycles = clock->hcycles();
|
||||
visible_scanlines = clock->visible_scanlines();
|
||||
if(status.r4210_read == false) {
|
||||
if(v == 0 && hcycles < 2) {
|
||||
r |= 0x80;
|
||||
status.r4210_read = true;
|
||||
} else if(v == (visible_scanlines + 1) && hcycles >= 2) {
|
||||
r |= 0x80;
|
||||
status.r4210_read = true;
|
||||
} else if(v >= (visible_scanlines + 1)) {
|
||||
r |= 0x80;
|
||||
status.r4210_read = true;
|
||||
}
|
||||
}
|
||||
r |= 0x40;
|
||||
r |= 0x02; //cpu version number
|
||||
status.nmi_pin = 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
//TIMEUP
|
||||
uint8 bCPU::mmio_r4211() {
|
||||
uint8 r = 0x00;
|
||||
r |= 0x40;
|
||||
if(status.irq_triggered == true)r |= 0x80;
|
||||
status.irq_triggered = false;
|
||||
return r;
|
||||
}
|
||||
|
||||
//HVBJOY
|
||||
uint8 bCPU::mmio_r4212() {
|
||||
uint8 r;
|
||||
uint16 v, h, hcycles, visible_scanlines;
|
||||
r = 0x00;
|
||||
|
||||
v = clock->vcounter();
|
||||
h = clock->hcounter();
|
||||
hcycles = clock->hcycles();
|
||||
visible_scanlines = clock->visible_scanlines();
|
||||
|
||||
//auto joypad polling
|
||||
if(v >= (visible_scanlines + 1) && v <= (visible_scanlines + 3))r |= 0x01;
|
||||
|
||||
//hblank
|
||||
if(hcycles <= 4 || hcycles >= 1098)r |= 0x40;
|
||||
|
||||
//vblank
|
||||
if(v == 0 && hcycles < 2)r |= 0x80;
|
||||
if(v == (visible_scanlines + 1) && hcycles >= 2)r |= 0x80;
|
||||
if(v > (visible_scanlines + 1))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 = clock->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 = clock->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;
|
||||
}
|
||||
|
||||
uint8 bCPUMMIO::read(uint32 addr) {
|
||||
clock->sync();
|
||||
switch(addr) {
|
||||
case 0x2180:return cpu->mmio_r2180(); //WMDATA
|
||||
case 0x21c2:return cpu->mmio_r21c2(); //???
|
||||
case 0x21c3:return cpu->mmio_r21c3(); //???
|
||||
case 0x4016:return cpu->mmio_r4016(); //JOYSER0
|
||||
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
|
||||
}
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
//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;
|
||||
if(value == 1)snes->poll_input();
|
||||
if(value == 0)status.joypad1_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);
|
||||
}
|
||||
|
||||
//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:0;
|
||||
status.r4216 = (status.div_b)?status.div_a % status.div_b:0;
|
||||
}
|
||||
|
||||
//HTIMEL
|
||||
void bCPU::mmio_w4207(uint8 value) {
|
||||
status.hirq_pos = (status.hirq_pos & 0xff00) | value;
|
||||
}
|
||||
|
||||
//HTIMEH
|
||||
void bCPU::mmio_w4208(uint8 value) {
|
||||
status.hirq_pos = (status.hirq_pos & 0x00ff) | (value << 8);
|
||||
}
|
||||
|
||||
//VTIMEL
|
||||
void bCPU::mmio_w4209(uint8 value) {
|
||||
status.virq_pos = (status.virq_pos & 0xff00) | value;
|
||||
}
|
||||
|
||||
//VTIMEH
|
||||
void bCPU::mmio_w420a(uint8 value) {
|
||||
status.virq_pos = (status.virq_pos & 0x00ff) | (value << 8);
|
||||
}
|
||||
|
||||
//DMAEN
|
||||
void bCPU::mmio_w420b(uint8 value) {
|
||||
for(int i=0;i<8;i++) {
|
||||
dma->channel[i].active = !!(value & (1 << i));
|
||||
if(dma->channel[i].active == true) {
|
||||
dma->channel[i].hdma_active = false;
|
||||
}
|
||||
}
|
||||
cpustate = CPUSTATE_DMA;
|
||||
}
|
||||
|
||||
//HDMAEN
|
||||
void bCPU::mmio_w420c(uint8 value) {
|
||||
for(int i=0;i<8;i++) {
|
||||
dma->channel[i].hdma_active = !!(value & (1 << i));
|
||||
if(dma->channel[i].hdma_active == true) {
|
||||
dma->channel[i].active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//MEMSEL
|
||||
void bCPU::mmio_w420d(uint8 value) {
|
||||
mem_bus->fastROM = value & 1;
|
||||
}
|
||||
|
||||
//DMAPx
|
||||
void bCPU::mmio_w43x0(uint8 value, uint8 i) {
|
||||
dma->channel[i].direction = !!(value & 0x80);
|
||||
dma->channel[i].hdma_indirect = !!(value & 0x40);
|
||||
dma->channel[i].incmode = (value & 0x10)?-1:1;
|
||||
dma->channel[i].fixedxfer = !!(value & 0x08);
|
||||
dma->channel[i].xfermode = value & 7;
|
||||
}
|
||||
|
||||
//BBADx
|
||||
void bCPU::mmio_w43x1(uint8 value, uint8 i) {
|
||||
dma->channel[i].destaddr = value;
|
||||
}
|
||||
|
||||
//A1TxL
|
||||
void bCPU::mmio_w43x2(uint8 value, uint8 i) {
|
||||
dma->channel[i].srcaddr = (dma->channel[i].srcaddr & 0xffff00) | value;
|
||||
}
|
||||
|
||||
//A1TxH
|
||||
void bCPU::mmio_w43x3(uint8 value, uint8 i) {
|
||||
dma->channel[i].srcaddr = (dma->channel[i].srcaddr & 0xff00ff) | (value << 8);
|
||||
}
|
||||
|
||||
//A1Bx
|
||||
void bCPU::mmio_w43x4(uint8 value, uint8 i) {
|
||||
dma->channel[i].srcaddr = (dma->channel[i].srcaddr & 0x00ffff) | (value << 16);
|
||||
}
|
||||
|
||||
//DASxL
|
||||
void bCPU::mmio_w43x5(uint8 value, uint8 i) {
|
||||
dma->channel[i].xfersize = (dma->channel[i].xfersize & 0xff00) | value;
|
||||
}
|
||||
|
||||
//DASxH
|
||||
void bCPU::mmio_w43x6(uint8 value, uint8 i) {
|
||||
dma->channel[i].xfersize = (dma->channel[i].xfersize & 0x00ff) | (value << 8);
|
||||
}
|
||||
|
||||
//DASBx
|
||||
void bCPU::mmio_w43x7(uint8 value, uint8 i) {
|
||||
dma->channel[i].hdma_indirect_bank = value;
|
||||
}
|
||||
|
||||
void bCPUMMIO::write(uint32 addr, uint8 value) {
|
||||
int i;
|
||||
clock->sync();
|
||||
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 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
|
||||
//DMAPx
|
||||
case 0x4300:case 0x4310:case 0x4320:case 0x4330:
|
||||
case 0x4340:case 0x4350:case 0x4360:case 0x4370:
|
||||
cpu->mmio_w43x0(value, (addr >> 4) & 7);
|
||||
return;
|
||||
//BBADx
|
||||
case 0x4301:case 0x4311:case 0x4321:case 0x4331:
|
||||
case 0x4341:case 0x4351:case 0x4361:case 0x4371:
|
||||
cpu->mmio_w43x1(value, (addr >> 4) & 7);
|
||||
return;
|
||||
//A1TxL
|
||||
case 0x4302:case 0x4312:case 0x4322:case 0x4332:
|
||||
case 0x4342:case 0x4352:case 0x4362:case 0x4372:
|
||||
cpu->mmio_w43x2(value, (addr >> 4) & 7);
|
||||
return;
|
||||
//A1TxH
|
||||
case 0x4303:case 0x4313:case 0x4323:case 0x4333:
|
||||
case 0x4343:case 0x4353:case 0x4363:case 0x4373:
|
||||
cpu->mmio_w43x3(value, (addr >> 4) & 7);
|
||||
return;
|
||||
//A1Bx
|
||||
case 0x4304:case 0x4314:case 0x4324:case 0x4334:
|
||||
case 0x4344:case 0x4354:case 0x4364:case 0x4374:
|
||||
cpu->mmio_w43x4(value, (addr >> 4) & 7);
|
||||
return;
|
||||
//DASxL
|
||||
case 0x4305:case 0x4315:case 0x4325:case 0x4335:
|
||||
case 0x4345:case 0x4355:case 0x4365:case 0x4375:
|
||||
cpu->mmio_w43x5(value, (addr >> 4) & 7);
|
||||
return;
|
||||
//DASxH
|
||||
case 0x4306:case 0x4316:case 0x4326:case 0x4336:
|
||||
case 0x4346:case 0x4356:case 0x4366:case 0x4376:
|
||||
cpu->mmio_w43x6(value, (addr >> 4) & 7);
|
||||
return;
|
||||
//DASBx
|
||||
case 0x4307:case 0x4317:case 0x4327:case 0x4337:
|
||||
case 0x4347:case 0x4357:case 0x4367:case 0x4377:
|
||||
cpu->mmio_w43x7(value, (addr >> 4) & 7);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bCPUMMIO::bCPUMMIO(bCPU *_cpu) {
|
||||
cpu = _cpu;
|
||||
}
|
||||
|
||||
uint16 bDMA::dma_cputommio(uint8 i, uint8 index) {
|
||||
uint8 x;
|
||||
x = mem_bus->read(channel[i].srcaddr);
|
||||
mem_bus->write(0x2100 | ((channel[i].destaddr + index) & 0xff), x);
|
||||
if(channel[i].fixedxfer == false) {
|
||||
channel[i].srcaddr = (channel[i].srcaddr & 0xff0000) + ((channel[i].srcaddr + channel[i].incmode) & 0xffff);
|
||||
}
|
||||
clock->add_cc1_cycles(8);
|
||||
return --channel[i].xfersize;
|
||||
}
|
||||
|
||||
uint16 bDMA::dma_mmiotocpu(uint8 i, uint8 index) {
|
||||
uint8 x;
|
||||
x = mem_bus->read(0x2100 | ((channel[i].destaddr + index) & 0xff));
|
||||
mem_bus->write(channel[i].srcaddr, x);
|
||||
if(channel[i].fixedxfer == false) {
|
||||
channel[i].srcaddr = (channel[i].srcaddr & 0xff0000) + ((channel[i].srcaddr + channel[i].incmode) & 0xffff);
|
||||
}
|
||||
clock->add_cc1_cycles(8);
|
||||
return --channel[i].xfersize;
|
||||
}
|
||||
|
||||
void bDMA::dma_xfer_type0(uint8 i) {
|
||||
if(channel[i].direction == 0) {
|
||||
if(dma_cputommio(i, 0) == 0)return;
|
||||
} else {
|
||||
if(dma_mmiotocpu(i, 0) == 0)return;
|
||||
}
|
||||
}
|
||||
|
||||
void bDMA::dma_xfer_type1(uint8 i) {
|
||||
if(channel[i].direction == 0) {
|
||||
if(dma_cputommio(i, 0) == 0)return;
|
||||
if(dma_cputommio(i, 1) == 0)return;
|
||||
} else {
|
||||
if(dma_mmiotocpu(i, 0) == 0)return;
|
||||
if(dma_mmiotocpu(i, 1) == 0)return;
|
||||
}
|
||||
}
|
||||
|
||||
void bDMA::dma_xfer_type2(uint8 i) {
|
||||
if(channel[i].direction == 0) {
|
||||
if(dma_cputommio(i, 0) == 0)return;
|
||||
if(dma_cputommio(i, 0) == 0)return;
|
||||
} else {
|
||||
if(dma_mmiotocpu(i, 0) == 0)return;
|
||||
if(dma_mmiotocpu(i, 0) == 0)return;
|
||||
}
|
||||
}
|
||||
|
||||
void bDMA::dma_xfer_type3(uint8 i) {
|
||||
if(channel[i].direction == 0) {
|
||||
if(dma_cputommio(i, 0) == 0)return;
|
||||
if(dma_cputommio(i, 0) == 0)return;
|
||||
if(dma_cputommio(i, 1) == 0)return;
|
||||
if(dma_cputommio(i, 1) == 0)return;
|
||||
} else {
|
||||
if(dma_mmiotocpu(i, 0) == 0)return;
|
||||
if(dma_mmiotocpu(i, 0) == 0)return;
|
||||
if(dma_mmiotocpu(i, 1) == 0)return;
|
||||
if(dma_mmiotocpu(i, 1) == 0)return;
|
||||
}
|
||||
}
|
||||
|
||||
void bDMA::dma_xfer_type4(uint8 i) {
|
||||
if(channel[i].direction == 0) {
|
||||
if(dma_cputommio(i, 0) == 0)return;
|
||||
if(dma_cputommio(i, 1) == 0)return;
|
||||
if(dma_cputommio(i, 2) == 0)return;
|
||||
if(dma_cputommio(i, 3) == 0)return;
|
||||
} else {
|
||||
if(dma_mmiotocpu(i, 0) == 0)return;
|
||||
if(dma_mmiotocpu(i, 1) == 0)return;
|
||||
if(dma_mmiotocpu(i, 2) == 0)return;
|
||||
if(dma_mmiotocpu(i, 3) == 0)return;
|
||||
}
|
||||
}
|
||||
|
||||
void bDMA::dma_xfer_type5(uint8 i) {
|
||||
if(channel[i].direction == 0) {
|
||||
if(dma_cputommio(i, 0) == 0)return;
|
||||
if(dma_cputommio(i, 1) == 0)return;
|
||||
if(dma_cputommio(i, 0) == 0)return;
|
||||
if(dma_cputommio(i, 1) == 0)return;
|
||||
} else {
|
||||
if(dma_mmiotocpu(i, 0) == 0)return;
|
||||
if(dma_mmiotocpu(i, 1) == 0)return;
|
||||
if(dma_mmiotocpu(i, 0) == 0)return;
|
||||
if(dma_mmiotocpu(i, 1) == 0)return;
|
||||
}
|
||||
}
|
||||
|
||||
void bDMA::run() {
|
||||
for(int i=0;i<8;i++) {
|
||||
if(channel[i].active == false)continue;
|
||||
switch(channel[i].xfermode) {
|
||||
case 0:dma_xfer_type0(i);break;
|
||||
case 1:dma_xfer_type1(i);break;
|
||||
case 2:dma_xfer_type2(i);break;
|
||||
case 3:dma_xfer_type3(i);break;
|
||||
case 4:dma_xfer_type4(i);break;
|
||||
case 5:dma_xfer_type5(i);break;
|
||||
case 6:dma_xfer_type2(i);break;
|
||||
case 7:dma_xfer_type3(i);break;
|
||||
}
|
||||
if(channel[i].xfersize == 0) {
|
||||
channel[i].active = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
cpu->cpustate = bCPU::CPUSTATE_RUN;
|
||||
}
|
||||
|
||||
void bDMA::hdma_write(uint8 i, uint8 l, uint8 x) {
|
||||
switch(channel[i].xfermode) {
|
||||
case 0:mem_bus->write(0x2100 | ((channel[i].destaddr) & 0xff), x);break;
|
||||
case 1:mem_bus->write(0x2100 | ((channel[i].destaddr + l) & 0xff), x);break;
|
||||
case 2:mem_bus->write(0x2100 | ((channel[i].destaddr) & 0xff), x);break;
|
||||
case 3:mem_bus->write(0x2100 | ((channel[i].destaddr + (l >> 1)) & 0xff), x);break;
|
||||
case 4:mem_bus->write(0x2100 | ((channel[i].destaddr + l) & 0xff), x);break;
|
||||
case 5:mem_bus->write(0x2100 | ((channel[i].destaddr + (l & 1)) & 0xff), x);break;
|
||||
case 6:mem_bus->write(0x2100 | ((channel[i].destaddr) & 0xff), x);break;
|
||||
case 7:mem_bus->write(0x2100 | ((channel[i].destaddr + (l >> 1)) & 0xff), x);break;
|
||||
}
|
||||
}
|
||||
|
||||
void bDMA::hdma_run() {
|
||||
int l, xferlen;
|
||||
uint8 x, active_channels = 0;
|
||||
for(int i=0;i<8;i++) {
|
||||
if(channel[i].hdma_completed == true)continue;
|
||||
clock->add_cc1_cycles(8);
|
||||
active_channels++;
|
||||
if(channel[i].hdma_line_counter == 0) {
|
||||
channel[i].hdma_line_counter = mem_bus->read(channel[i].hdma_address++);
|
||||
// channel[i].r43x8 = channel[i].hdma_address;
|
||||
if(channel[i].hdma_line_counter == 0) {
|
||||
channel[i].hdma_completed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(channel[i].hdma_line_counter > 0x80) {
|
||||
channel[i].hdma_repeat = true;
|
||||
channel[i].hdma_line_counter -= 0x80;
|
||||
} else {
|
||||
channel[i].hdma_repeat = false;
|
||||
}
|
||||
|
||||
channel[i].hdma_first_line = true;
|
||||
if(channel[i].hdma_indirect == false) {
|
||||
channel[i].hdma_iaddress = channel[i].hdma_address;
|
||||
} else {
|
||||
channel[i].hdma_iaddress = mem_bus->read(channel[i].hdma_address++);
|
||||
channel[i].hdma_iaddress |= mem_bus->read(channel[i].hdma_address++) << 8;
|
||||
channel[i].hdma_iaddress |= channel[i].hdma_indirect_bank << 16;
|
||||
clock->add_cc1_cycles(16);
|
||||
}
|
||||
}
|
||||
|
||||
channel[i].hdma_line_counter--;
|
||||
if(channel[i].hdma_first_line == false && channel[i].hdma_repeat == false)continue;
|
||||
channel[i].hdma_first_line = false;
|
||||
|
||||
if(channel[i].hdma_indirect == false) {
|
||||
channel[i].hdma_iaddress = channel[i].hdma_address;
|
||||
}
|
||||
|
||||
switch(channel[i].xfermode) {
|
||||
case 0: xferlen = 1;break;
|
||||
case 1:case 2:case 6: xferlen = 2;break;
|
||||
case 3:case 4:case 5:case 7:xferlen = 4;break;
|
||||
}
|
||||
|
||||
for(l=0;l<xferlen;l++) {
|
||||
x = mem_bus->read(channel[i].hdma_iaddress++);
|
||||
if(channel[i].hdma_indirect == false) {
|
||||
channel[i].hdma_address++;
|
||||
}
|
||||
hdma_write(i, l, x);
|
||||
clock->add_cc1_cycles(8);
|
||||
}
|
||||
}
|
||||
if(active_channels != 0) {
|
||||
clock->add_cc1_cycles(18);
|
||||
}
|
||||
}
|
||||
|
||||
void bDMA::hdma_initialize() {
|
||||
uint8 active_channels = 0;
|
||||
for(int i=0;i<8;i++) {
|
||||
if(!channel[i].hdma_active) {
|
||||
channel[i].hdma_completed = true;
|
||||
continue;
|
||||
}
|
||||
active_channels++;
|
||||
channel[i].hdma_first_line = true;
|
||||
channel[i].hdma_repeat = false;
|
||||
channel[i].hdma_line_counter = 0;
|
||||
channel[i].hdma_address = channel[i].srcaddr;
|
||||
channel[i].hdma_completed = false;
|
||||
if(channel[i].hdma_indirect == false) {
|
||||
clock->add_cc1_cycles(8);
|
||||
} else {
|
||||
clock->add_cc1_cycles(24);
|
||||
}
|
||||
}
|
||||
if(active_channels != 0) {
|
||||
clock->add_cc1_cycles(18);
|
||||
}
|
||||
}
|
||||
|
||||
void bDMA::reset() {
|
||||
for(int i=0;i<8;i++) {
|
||||
channel[i].active = false;
|
||||
channel[i].hdma_active = false;
|
||||
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 = 0;
|
||||
channel[i].hdma_indirect_bank = 0;
|
||||
channel[i].hdma_first_line = false;
|
||||
channel[i].hdma_repeat = false;
|
||||
channel[i].hdma_line_counter = 0;
|
||||
channel[i].hdma_address = 0;
|
||||
channel[i].hdma_iaddress = 0;
|
||||
channel[i].hdma_completed = false;
|
||||
}
|
||||
hdma_triggered = false;
|
||||
}
|
||||
|
||||
bDMA::bDMA(bCPU *_cpu) {
|
||||
cpu = _cpu;
|
||||
reset();
|
||||
}
|
||||
@@ -1,494 +0,0 @@
|
||||
void bCPU::flags_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 = ((byte)r == 0);
|
||||
regs.p.c = (r > 0xff);
|
||||
regs.a.l = r;
|
||||
}
|
||||
|
||||
void bCPU::flags_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 = ((word)r == 0);
|
||||
regs.p.c = (r > 0xffff);
|
||||
regs.a.w = r;
|
||||
}
|
||||
|
||||
/************************
|
||||
*** 0x69: adc #const ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; idl
|
||||
[2a] pbr,pc+2 ; idh [1]
|
||||
*/
|
||||
void bCPU::op_adc_constb() {
|
||||
rd.l = op_read(); //2
|
||||
flags_adc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_constw() {
|
||||
rd.l = op_read(); //2
|
||||
rd.h = op_read(); //2a
|
||||
flags_adc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_const() { (regs.p.m)?op_adc_constb():op_adc_constw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x6d: adc addr ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aa ; data low
|
||||
[4a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_adc_addrb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
flags_adc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_addrw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a
|
||||
flags_adc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_addr() { (regs.p.m)?op_adc_addrb():op_adc_addrw(); }
|
||||
|
||||
/************************
|
||||
*** 0x7d: adc addr,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; operadc
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[3a] dbr,aah,aal+xl ; io [4]
|
||||
[4 ] dbr,aa+x ; data low
|
||||
[4a] dbr,aa+x+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_adc_addrxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.x.w); //3a
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4
|
||||
flags_adc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_addrxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.x.w); //3a
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a
|
||||
flags_adc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_addrx() { (regs.p.m)?op_adc_addrxb():op_adc_addrxw(); }
|
||||
|
||||
/********************
|
||||
*** 0x65: adc dp ***
|
||||
********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; operadc
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; data low
|
||||
[3a] 0,d+dp+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_adc_dpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
rd.l = op_read(OPMODE_DP, dp); //3
|
||||
flags_adc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_dpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
rd.l = op_read(OPMODE_DP, dp); //3
|
||||
rd.h = op_read(OPMODE_DP, dp + 1); //3a
|
||||
flags_adc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_dp() { (regs.p.m)?op_adc_dpb():op_adc_dpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x72: adc (dp) ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] dbr,aa ; data low
|
||||
[5a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_adc_idpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //5
|
||||
flags_adc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_idpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //5
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + 1); //5
|
||||
flags_adc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_idp() { (regs.p.m)?op_adc_idpb():op_adc_idpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x67: adc [dp] ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] 0,d+dp+2 ; aab
|
||||
[6 ] aab,aa ; data low
|
||||
[6a] aab,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_adc_ildpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
rd.l = op_read(OPMODE_LONG, aa.d); //6
|
||||
flags_adc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_ildpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
rd.l = op_read(OPMODE_LONG, aa.d); //6
|
||||
rd.h = op_read(OPMODE_LONG, aa.d + 1); //6a
|
||||
flags_adc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_ildp() { (regs.p.m)?op_adc_ildpb():op_adc_ildpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x6f: adc long ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] pbr,pc+3 ; aab
|
||||
[5 ] aab,aa ; data low
|
||||
[5a] aab,aa+1 ; data high
|
||||
*/
|
||||
void bCPU::op_adc_longb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
rd.l = op_read(OPMODE_LONG, aa.d); //5
|
||||
flags_adc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_longw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
rd.l = op_read(OPMODE_LONG, aa.d); //5
|
||||
rd.h = op_read(OPMODE_LONG, aa.d + 1); //5a
|
||||
flags_adc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_long() { (regs.p.m)?op_adc_longb():op_adc_longw(); }
|
||||
|
||||
/************************
|
||||
*** 0x7f: adc long,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] pbr,pc+3 ; aab
|
||||
[5 ] aab,aa+x ; data low
|
||||
[5a] aab,aa+x+1 ; data high
|
||||
*/
|
||||
void bCPU::op_adc_longxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5
|
||||
flags_adc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_longxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5
|
||||
rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a
|
||||
flags_adc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_longx() { (regs.p.m)?op_adc_longxb():op_adc_longxw(); }
|
||||
|
||||
/************************
|
||||
*** 0x79: adc addr,y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; operadc
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[3a] dbr,aah,aal+yl ; io [4]
|
||||
[4 ] dbr,aa+y ; data low
|
||||
[4a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_adc_addryb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //3a
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4
|
||||
flags_adc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_addryw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //3a
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a
|
||||
flags_adc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_addry() { (regs.p.m)?op_adc_addryb():op_adc_addryw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x75: adc dp,x ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; data low
|
||||
[4a] 0,d+dp+x+1 ; data high
|
||||
*/
|
||||
void bCPU::op_adc_dpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
flags_adc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_dpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
|
||||
flags_adc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_dpx() { (regs.p.m)?op_adc_dpxb():op_adc_dpxw(); }
|
||||
|
||||
/************************
|
||||
*** 0x61: adc (dp,x) ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; aal
|
||||
[5 ] 0,d+dp+x+1 ; aah
|
||||
[6 ] dbr,aa ; data low
|
||||
[6a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_adc_idpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //6
|
||||
flags_adc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_idpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //6
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + 1); //6a
|
||||
flags_adc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_idpx() { (regs.p.m)?op_adc_idpxb():op_adc_idpxw(); }
|
||||
|
||||
/************************
|
||||
*** 0x71: adc (dp),y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[4a] dbr,aah,aal+yl ; io [4]
|
||||
[5 ] dbr,aa+y ; data low
|
||||
[5a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_adc_idpyb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //4a
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5
|
||||
flags_adc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_idpyw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //4a
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a
|
||||
flags_adc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_idpy() { (regs.p.m)?op_adc_idpyb():op_adc_idpyw(); }
|
||||
|
||||
/************************
|
||||
*** 0x77: adc [dp],y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] 0,d+dp+2 ; aab
|
||||
[6 ] aab,aa+y ; data low
|
||||
[6a] aab,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_adc_ildpyb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6
|
||||
flags_adc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_ildpyw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6
|
||||
rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a
|
||||
flags_adc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_ildpy() { (regs.p.m)?op_adc_ildpyb():op_adc_ildpyw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x63: adc sr,s ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; sp
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+sp ; data low
|
||||
[4a] 0,s+sp+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_adc_srb() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_SP, sp); //4
|
||||
flags_adc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_srw() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_SP, sp); //4
|
||||
rd.h = op_read(OPMODE_SP, sp + 1); //4a
|
||||
flags_adc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_sr() { (regs.p.m)?op_adc_srb():op_adc_srw(); }
|
||||
|
||||
/**************************
|
||||
*** 0x73: adc (sr,s),y ***
|
||||
**************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; sp
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+sp ; aal
|
||||
[5 ] 0,s+sp+1 ; aah
|
||||
[6 ] 0,s+sp+1 ; io
|
||||
[7 ] dbr,aa+y ; data low
|
||||
[7a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_adc_isryb() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_SP, sp); //4
|
||||
aa.h = op_read(OPMODE_SP, sp + 1); //5
|
||||
cpu_io(); //6
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7
|
||||
flags_adc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_isryw() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_SP, sp); //4
|
||||
aa.h = op_read(OPMODE_SP, sp + 1); //5
|
||||
cpu_io(); //6
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a
|
||||
flags_adc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_adc_isry() { (regs.p.m)?op_adc_isryb():op_adc_isryw(); }
|
||||
@@ -1,474 +0,0 @@
|
||||
void bCPU::flags_and_b() {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::flags_and_w() {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
/************************
|
||||
*** 0x29: and #const ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; idl
|
||||
[2a] pbr,pc+2 ; idh [1]
|
||||
*/
|
||||
void bCPU::op_and_constb() {
|
||||
regs.a.l &= op_read(); //2
|
||||
flags_and_b();
|
||||
}
|
||||
|
||||
void bCPU::op_and_constw() {
|
||||
regs.a.l &= op_read(); //2
|
||||
regs.a.h &= op_read(); //2a
|
||||
flags_and_w();
|
||||
}
|
||||
|
||||
void bCPU::op_and_const() { (regs.p.m)?op_and_constb():op_and_constw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x2d: and addr ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aa ; data low
|
||||
[4a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_and_addrb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
regs.a.l &= op_read(OPMODE_DBR, aa.w); //4
|
||||
flags_and_b();
|
||||
}
|
||||
|
||||
void bCPU::op_and_addrw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
regs.a.l &= op_read(OPMODE_DBR, aa.w); //4
|
||||
regs.a.h &= op_read(OPMODE_DBR, aa.w + 1); //4a
|
||||
flags_and_w();
|
||||
}
|
||||
|
||||
void bCPU::op_and_addr() { (regs.p.m)?op_and_addrb():op_and_addrw(); }
|
||||
|
||||
/************************
|
||||
*** 0x3d: and addr,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; operand
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[3a] dbr,aah,aal+xl ; io [4]
|
||||
[4 ] dbr,aa+x ; data low
|
||||
[4a] dbr,aa+x+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_and_addrxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.x.w); //3a
|
||||
regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.x.w); //4
|
||||
flags_and_b();
|
||||
}
|
||||
|
||||
void bCPU::op_and_addrxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.x.w); //3a
|
||||
regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.x.w); //4
|
||||
regs.a.h &= op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a
|
||||
flags_and_w();
|
||||
}
|
||||
|
||||
void bCPU::op_and_addrx() { (regs.p.m)?op_and_addrxb():op_and_addrxw(); }
|
||||
|
||||
/********************
|
||||
*** 0x25: and dp ***
|
||||
********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; operand
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; data low
|
||||
[3a] 0,d+dp+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_and_dpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
regs.a.l &= op_read(OPMODE_DP, dp); //3
|
||||
flags_and_b();
|
||||
}
|
||||
|
||||
void bCPU::op_and_dpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
regs.a.l &= op_read(OPMODE_DP, dp); //3
|
||||
regs.a.h &= op_read(OPMODE_DP, dp + 1); //3a
|
||||
flags_and_w();
|
||||
}
|
||||
|
||||
void bCPU::op_and_dp() { (regs.p.m)?op_and_dpb():op_and_dpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x32: and (dp) ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] dbr,aa ; data low
|
||||
[5a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_and_idpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
regs.a.l &= op_read(OPMODE_DBR, aa.w); //5
|
||||
flags_and_b();
|
||||
}
|
||||
|
||||
void bCPU::op_and_idpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
regs.a.l &= op_read(OPMODE_DBR, aa.w); //5
|
||||
regs.a.h &= op_read(OPMODE_DBR, aa.w + 1); //5
|
||||
flags_and_w();
|
||||
}
|
||||
|
||||
void bCPU::op_and_idp() { (regs.p.m)?op_and_idpb():op_and_idpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x27: and [dp] ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] 0,d+dp+2 ; aab
|
||||
[6 ] aab,aa ; data low
|
||||
[6a] aab,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_and_ildpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
regs.a.l &= op_read(OPMODE_LONG, aa.d); //6
|
||||
flags_and_b();
|
||||
}
|
||||
|
||||
void bCPU::op_and_ildpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
regs.a.l &= op_read(OPMODE_LONG, aa.d); //6
|
||||
regs.a.h &= op_read(OPMODE_LONG, aa.d + 1); //6a
|
||||
flags_and_w();
|
||||
}
|
||||
|
||||
void bCPU::op_and_ildp() { (regs.p.m)?op_and_ildpb():op_and_ildpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x2f: and long ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] pbr,pc+3 ; aab
|
||||
[5 ] aab,aa ; data low
|
||||
[5a] aab,aa+1 ; data high
|
||||
*/
|
||||
void bCPU::op_and_longb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
regs.a.l &= op_read(OPMODE_LONG, aa.d); //5
|
||||
flags_and_b();
|
||||
}
|
||||
|
||||
void bCPU::op_and_longw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
regs.a.l &= op_read(OPMODE_LONG, aa.d); //5
|
||||
regs.a.h &= op_read(OPMODE_LONG, aa.d + 1); //5a
|
||||
flags_and_w();
|
||||
}
|
||||
|
||||
void bCPU::op_and_long() { (regs.p.m)?op_and_longb():op_and_longw(); }
|
||||
|
||||
/************************
|
||||
*** 0x3f: and long,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] pbr,pc+3 ; aab
|
||||
[5 ] aab,aa+x ; data low
|
||||
[5a] aab,aa+x+1 ; data high
|
||||
*/
|
||||
void bCPU::op_and_longxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
regs.a.l &= op_read(OPMODE_LONG, aa.d + regs.x.w); //5
|
||||
flags_and_b();
|
||||
}
|
||||
|
||||
void bCPU::op_and_longxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
regs.a.l &= op_read(OPMODE_LONG, aa.d + regs.x.w); //5
|
||||
regs.a.h &= op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a
|
||||
flags_and_w();
|
||||
}
|
||||
|
||||
void bCPU::op_and_longx() { (regs.p.m)?op_and_longxb():op_and_longxw(); }
|
||||
|
||||
/************************
|
||||
*** 0x39: and addr,y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; operand
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[3a] dbr,aah,aal+yl ; io [4]
|
||||
[4 ] dbr,aa+y ; data low
|
||||
[4a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_and_addryb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //3a
|
||||
regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.y.w); //4
|
||||
flags_and_b();
|
||||
}
|
||||
|
||||
void bCPU::op_and_addryw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //3a
|
||||
regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.y.w); //4
|
||||
regs.a.h &= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a
|
||||
flags_and_w();
|
||||
}
|
||||
|
||||
void bCPU::op_and_addry() { (regs.p.m)?op_and_addryb():op_and_addryw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x35: and dp,x ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; data low
|
||||
[4a] 0,d+dp+x+1 ; data high
|
||||
*/
|
||||
void bCPU::op_and_dpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
regs.a.l &= op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
flags_and_b();
|
||||
}
|
||||
|
||||
void bCPU::op_and_dpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
regs.a.l &= op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
regs.a.h &= op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
|
||||
flags_and_w();
|
||||
}
|
||||
|
||||
void bCPU::op_and_dpx() { (regs.p.m)?op_and_dpxb():op_and_dpxw(); }
|
||||
|
||||
/************************
|
||||
*** 0x21: and (dp,x) ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; aal
|
||||
[5 ] 0,d+dp+x+1 ; aah
|
||||
[6 ] dbr,aa ; data low
|
||||
[6a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_and_idpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
|
||||
regs.a.l &= op_read(OPMODE_DBR, aa.w); //6
|
||||
flags_and_b();
|
||||
}
|
||||
|
||||
void bCPU::op_and_idpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
|
||||
regs.a.l &= op_read(OPMODE_DBR, aa.w); //6
|
||||
regs.a.h &= op_read(OPMODE_DBR, aa.w + 1); //6a
|
||||
flags_and_w();
|
||||
}
|
||||
|
||||
void bCPU::op_and_idpx() { (regs.p.m)?op_and_idpxb():op_and_idpxw(); }
|
||||
|
||||
/************************
|
||||
*** 0x31: and (dp),y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[4a] dbr,aah,aal+yl ; io [4]
|
||||
[5 ] dbr,aa+y ; data low
|
||||
[5a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_and_idpyb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //4a
|
||||
regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.y.w); //5
|
||||
flags_and_b();
|
||||
}
|
||||
|
||||
void bCPU::op_and_idpyw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //4a
|
||||
regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.y.w); //5
|
||||
regs.a.h &= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a
|
||||
flags_and_w();
|
||||
}
|
||||
|
||||
void bCPU::op_and_idpy() { (regs.p.m)?op_and_idpyb():op_and_idpyw(); }
|
||||
|
||||
/************************
|
||||
*** 0x37: and [dp],y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] 0,d+dp+2 ; aab
|
||||
[6 ] aab,aa+y ; data low
|
||||
[6a] aab,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_and_ildpyb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
regs.a.l &= op_read(OPMODE_LONG, aa.d + regs.y.w); //6
|
||||
flags_and_b();
|
||||
}
|
||||
|
||||
void bCPU::op_and_ildpyw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
regs.a.l &= op_read(OPMODE_LONG, aa.d + regs.y.w); //6
|
||||
regs.a.h &= op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a
|
||||
flags_and_w();
|
||||
}
|
||||
|
||||
void bCPU::op_and_ildpy() { (regs.p.m)?op_and_ildpyb():op_and_ildpyw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x23: and sr,s ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; sp
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+sp ; data low
|
||||
[4a] 0,s+sp+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_and_srb() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
regs.a.l &= op_read(OPMODE_SP, sp); //4
|
||||
flags_and_b();
|
||||
}
|
||||
|
||||
void bCPU::op_and_srw() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
regs.a.l &= op_read(OPMODE_SP, sp); //4
|
||||
regs.a.h &= op_read(OPMODE_SP, sp + 1); //4a
|
||||
flags_and_w();
|
||||
}
|
||||
|
||||
void bCPU::op_and_sr() { (regs.p.m)?op_and_srb():op_and_srw(); }
|
||||
|
||||
/**************************
|
||||
*** 0x33: and (sr,s),y ***
|
||||
**************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; sp
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+sp ; aal
|
||||
[5 ] 0,s+sp+1 ; aah
|
||||
[6 ] 0,s+sp+1 ; io
|
||||
[7 ] dbr,aa+y ; data low
|
||||
[7a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_and_isryb() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_SP, sp); //4
|
||||
aa.h = op_read(OPMODE_SP, sp + 1); //5
|
||||
cpu_io(); //6
|
||||
regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.y.w); //7
|
||||
flags_and_b();
|
||||
}
|
||||
|
||||
void bCPU::op_and_isryw() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_SP, sp); //4
|
||||
aa.h = op_read(OPMODE_SP, sp + 1); //5
|
||||
cpu_io(); //6
|
||||
regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.y.w); //7
|
||||
regs.a.h &= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a
|
||||
flags_and_w();
|
||||
}
|
||||
|
||||
void bCPU::op_and_isry() { (regs.p.m)?op_and_isryb():op_and_isryw(); }
|
||||
@@ -1,478 +0,0 @@
|
||||
void bCPU::flags_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);
|
||||
}
|
||||
|
||||
void bCPU::flags_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);
|
||||
}
|
||||
|
||||
/************************
|
||||
*** 0xc9: cmp #const ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; idl
|
||||
[2a] pbr,pc+2 ; idh [1]
|
||||
*/
|
||||
void bCPU::op_cmp_constb() {
|
||||
rd.l = op_read(); //2
|
||||
flags_cmp_b();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_constw() {
|
||||
rd.l = op_read(); //2
|
||||
rd.h = op_read(); //2a
|
||||
flags_cmp_w();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_const() { (regs.p.m)?op_cmp_constb():op_cmp_constw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xcd: cmp addr ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aa ; data low
|
||||
[4a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_cmp_addrb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
flags_cmp_b();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_addrw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a
|
||||
flags_cmp_w();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_addr() { (regs.p.m)?op_cmp_addrb():op_cmp_addrw(); }
|
||||
|
||||
/************************
|
||||
*** 0xdd: cmp addr,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opercmp
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[3a] dbr,aah,aal+xl ; io [4]
|
||||
[4 ] dbr,aa+x ; data low
|
||||
[4a] dbr,aa+x+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_cmp_addrxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.x.w); //3a
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4
|
||||
flags_cmp_b();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_addrxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.x.w); //3a
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a
|
||||
flags_cmp_w();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_addrx() { (regs.p.m)?op_cmp_addrxb():op_cmp_addrxw(); }
|
||||
|
||||
/********************
|
||||
*** 0xc5: cmp dp ***
|
||||
********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opercmp
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; data low
|
||||
[3a] 0,d+dp+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_cmp_dpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
rd.l = op_read(OPMODE_DP, dp); //3
|
||||
flags_cmp_b();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_dpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
rd.l = op_read(OPMODE_DP, dp); //3
|
||||
rd.h = op_read(OPMODE_DP, dp + 1); //3a
|
||||
flags_cmp_w();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_dp() { (regs.p.m)?op_cmp_dpb():op_cmp_dpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xd2: cmp (dp) ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] dbr,aa ; data low
|
||||
[5a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_cmp_idpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //5
|
||||
flags_cmp_b();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_idpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //5
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + 1); //5
|
||||
flags_cmp_w();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_idp() { (regs.p.m)?op_cmp_idpb():op_cmp_idpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xc7: cmp [dp] ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] 0,d+dp+2 ; aab
|
||||
[6 ] aab,aa ; data low
|
||||
[6a] aab,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_cmp_ildpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
rd.l = op_read(OPMODE_LONG, aa.d); //6
|
||||
flags_cmp_b();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_ildpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
rd.l = op_read(OPMODE_LONG, aa.d); //6
|
||||
rd.h = op_read(OPMODE_LONG, aa.d + 1); //6a
|
||||
flags_cmp_w();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_ildp() { (regs.p.m)?op_cmp_ildpb():op_cmp_ildpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xcf: cmp long ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] pbr,pc+3 ; aab
|
||||
[5 ] aab,aa ; data low
|
||||
[5a] aab,aa+1 ; data high
|
||||
*/
|
||||
void bCPU::op_cmp_longb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
rd.l = op_read(OPMODE_LONG, aa.d); //5
|
||||
flags_cmp_b();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_longw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
rd.l = op_read(OPMODE_LONG, aa.d); //5
|
||||
rd.h = op_read(OPMODE_LONG, aa.d + 1); //5a
|
||||
flags_cmp_w();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_long() { (regs.p.m)?op_cmp_longb():op_cmp_longw(); }
|
||||
|
||||
/************************
|
||||
*** 0xdf: cmp long,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] pbr,pc+3 ; aab
|
||||
[5 ] aab,aa+x ; data low
|
||||
[5a] aab,aa+x+1 ; data high
|
||||
*/
|
||||
void bCPU::op_cmp_longxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5
|
||||
flags_cmp_b();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_longxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5
|
||||
rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a
|
||||
flags_cmp_w();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_longx() { (regs.p.m)?op_cmp_longxb():op_cmp_longxw(); }
|
||||
|
||||
/************************
|
||||
*** 0xd9: cmp addr,y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opercmp
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[3a] dbr,aah,aal+yl ; io [4]
|
||||
[4 ] dbr,aa+y ; data low
|
||||
[4a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_cmp_addryb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //3a
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4
|
||||
flags_cmp_b();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_addryw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //3a
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a
|
||||
flags_cmp_w();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_addry() { (regs.p.m)?op_cmp_addryb():op_cmp_addryw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xd5: cmp dp,x ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; data low
|
||||
[4a] 0,d+dp+x+1 ; data high
|
||||
*/
|
||||
void bCPU::op_cmp_dpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
flags_cmp_b();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_dpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
|
||||
flags_cmp_w();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_dpx() { (regs.p.m)?op_cmp_dpxb():op_cmp_dpxw(); }
|
||||
|
||||
/************************
|
||||
*** 0xc1: cmp (dp,x) ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; aal
|
||||
[5 ] 0,d+dp+x+1 ; aah
|
||||
[6 ] dbr,aa ; data low
|
||||
[6a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_cmp_idpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //6
|
||||
flags_cmp_b();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_idpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //6
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + 1); //6a
|
||||
flags_cmp_w();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_idpx() { (regs.p.m)?op_cmp_idpxb():op_cmp_idpxw(); }
|
||||
|
||||
/************************
|
||||
*** 0xd1: cmp (dp),y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[4a] dbr,aah,aal+yl ; io [4]
|
||||
[5 ] dbr,aa+y ; data low
|
||||
[5a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_cmp_idpyb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //4a
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5
|
||||
flags_cmp_b();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_idpyw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //4a
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a
|
||||
flags_cmp_w();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_idpy() { (regs.p.m)?op_cmp_idpyb():op_cmp_idpyw(); }
|
||||
|
||||
/************************
|
||||
*** 0xd7: cmp [dp],y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] 0,d+dp+2 ; aab
|
||||
[6 ] aab,aa+y ; data low
|
||||
[6a] aab,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_cmp_ildpyb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6
|
||||
flags_cmp_b();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_ildpyw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6
|
||||
rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a
|
||||
flags_cmp_w();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_ildpy() { (regs.p.m)?op_cmp_ildpyb():op_cmp_ildpyw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xc3: cmp sr,s ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; sp
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+sp ; data low
|
||||
[4a] 0,s+sp+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_cmp_srb() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_SP, sp); //4
|
||||
flags_cmp_b();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_srw() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_SP, sp); //4
|
||||
rd.h = op_read(OPMODE_SP, sp + 1); //4a
|
||||
flags_cmp_w();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_sr() { (regs.p.m)?op_cmp_srb():op_cmp_srw(); }
|
||||
|
||||
/**************************
|
||||
*** 0xd3: cmp (sr,s),y ***
|
||||
**************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; sp
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+sp ; aal
|
||||
[5 ] 0,s+sp+1 ; aah
|
||||
[6 ] 0,s+sp+1 ; io
|
||||
[7 ] dbr,aa+y ; data low
|
||||
[7a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_cmp_isryb() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_SP, sp); //4
|
||||
aa.h = op_read(OPMODE_SP, sp + 1); //5
|
||||
cpu_io(); //6
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7
|
||||
flags_cmp_b();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_isryw() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_SP, sp); //4
|
||||
aa.h = op_read(OPMODE_SP, sp + 1); //5
|
||||
cpu_io(); //6
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a
|
||||
flags_cmp_w();
|
||||
}
|
||||
|
||||
void bCPU::op_cmp_isry() { (regs.p.m)?op_cmp_isryb():op_cmp_isryw(); }
|
||||
@@ -1,474 +0,0 @@
|
||||
void bCPU::flags_eor_b() {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::flags_eor_w() {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
/************************
|
||||
*** 0x49: eor #const ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; idl
|
||||
[2a] pbr,pc+2 ; idh [1]
|
||||
*/
|
||||
void bCPU::op_eor_constb() {
|
||||
regs.a.l ^= op_read(); //2
|
||||
flags_eor_b();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_constw() {
|
||||
regs.a.l ^= op_read(); //2
|
||||
regs.a.h ^= op_read(); //2a
|
||||
flags_eor_w();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_const() { (regs.p.m)?op_eor_constb():op_eor_constw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x4d: eor addr ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aa ; data low
|
||||
[4a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_eor_addrb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
regs.a.l ^= op_read(OPMODE_DBR, aa.w); //4
|
||||
flags_eor_b();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_addrw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
regs.a.l ^= op_read(OPMODE_DBR, aa.w); //4
|
||||
regs.a.h ^= op_read(OPMODE_DBR, aa.w + 1); //4a
|
||||
flags_eor_w();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_addr() { (regs.p.m)?op_eor_addrb():op_eor_addrw(); }
|
||||
|
||||
/************************
|
||||
*** 0x5d: eor addr,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opereor
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[3a] dbr,aah,aal+xl ; io [4]
|
||||
[4 ] dbr,aa+x ; data low
|
||||
[4a] dbr,aa+x+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_eor_addrxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.x.w); //3a
|
||||
regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.x.w); //4
|
||||
flags_eor_b();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_addrxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.x.w); //3a
|
||||
regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.x.w); //4
|
||||
regs.a.h ^= op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a
|
||||
flags_eor_w();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_addrx() { (regs.p.m)?op_eor_addrxb():op_eor_addrxw(); }
|
||||
|
||||
/********************
|
||||
*** 0x45: eor dp ***
|
||||
********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opereor
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; data low
|
||||
[3a] 0,d+dp+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_eor_dpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
regs.a.l ^= op_read(OPMODE_DP, dp); //3
|
||||
flags_eor_b();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_dpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
regs.a.l ^= op_read(OPMODE_DP, dp); //3
|
||||
regs.a.h ^= op_read(OPMODE_DP, dp + 1); //3a
|
||||
flags_eor_w();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_dp() { (regs.p.m)?op_eor_dpb():op_eor_dpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x52: eor (dp) ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] dbr,aa ; data low
|
||||
[5a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_eor_idpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
regs.a.l ^= op_read(OPMODE_DBR, aa.w); //5
|
||||
flags_eor_b();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_idpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
regs.a.l ^= op_read(OPMODE_DBR, aa.w); //5
|
||||
regs.a.h ^= op_read(OPMODE_DBR, aa.w + 1); //5
|
||||
flags_eor_w();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_idp() { (regs.p.m)?op_eor_idpb():op_eor_idpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x47: eor [dp] ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] 0,d+dp+2 ; aab
|
||||
[6 ] aab,aa ; data low
|
||||
[6a] aab,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_eor_ildpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
regs.a.l ^= op_read(OPMODE_LONG, aa.d); //6
|
||||
flags_eor_b();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_ildpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
regs.a.l ^= op_read(OPMODE_LONG, aa.d); //6
|
||||
regs.a.h ^= op_read(OPMODE_LONG, aa.d + 1); //6a
|
||||
flags_eor_w();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_ildp() { (regs.p.m)?op_eor_ildpb():op_eor_ildpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x4f: eor long ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] pbr,pc+3 ; aab
|
||||
[5 ] aab,aa ; data low
|
||||
[5a] aab,aa+1 ; data high
|
||||
*/
|
||||
void bCPU::op_eor_longb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
regs.a.l ^= op_read(OPMODE_LONG, aa.d); //5
|
||||
flags_eor_b();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_longw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
regs.a.l ^= op_read(OPMODE_LONG, aa.d); //5
|
||||
regs.a.h ^= op_read(OPMODE_LONG, aa.d + 1); //5a
|
||||
flags_eor_w();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_long() { (regs.p.m)?op_eor_longb():op_eor_longw(); }
|
||||
|
||||
/************************
|
||||
*** 0x5f: eor long,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] pbr,pc+3 ; aab
|
||||
[5 ] aab,aa+x ; data low
|
||||
[5a] aab,aa+x+1 ; data high
|
||||
*/
|
||||
void bCPU::op_eor_longxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
regs.a.l ^= op_read(OPMODE_LONG, aa.d + regs.x.w); //5
|
||||
flags_eor_b();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_longxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
regs.a.l ^= op_read(OPMODE_LONG, aa.d + regs.x.w); //5
|
||||
regs.a.h ^= op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a
|
||||
flags_eor_w();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_longx() { (regs.p.m)?op_eor_longxb():op_eor_longxw(); }
|
||||
|
||||
/************************
|
||||
*** 0x59: eor addr,y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opereor
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[3a] dbr,aah,aal+yl ; io [4]
|
||||
[4 ] dbr,aa+y ; data low
|
||||
[4a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_eor_addryb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //3a
|
||||
regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.y.w); //4
|
||||
flags_eor_b();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_addryw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //3a
|
||||
regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.y.w); //4
|
||||
regs.a.h ^= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a
|
||||
flags_eor_w();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_addry() { (regs.p.m)?op_eor_addryb():op_eor_addryw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x55: eor dp,x ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; data low
|
||||
[4a] 0,d+dp+x+1 ; data high
|
||||
*/
|
||||
void bCPU::op_eor_dpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
regs.a.l ^= op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
flags_eor_b();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_dpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
regs.a.l ^= op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
regs.a.h ^= op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
|
||||
flags_eor_w();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_dpx() { (regs.p.m)?op_eor_dpxb():op_eor_dpxw(); }
|
||||
|
||||
/************************
|
||||
*** 0x41: eor (dp,x) ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; aal
|
||||
[5 ] 0,d+dp+x+1 ; aah
|
||||
[6 ] dbr,aa ; data low
|
||||
[6a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_eor_idpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
|
||||
regs.a.l ^= op_read(OPMODE_DBR, aa.w); //6
|
||||
flags_eor_b();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_idpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
|
||||
regs.a.l ^= op_read(OPMODE_DBR, aa.w); //6
|
||||
regs.a.h ^= op_read(OPMODE_DBR, aa.w + 1); //6a
|
||||
flags_eor_w();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_idpx() { (regs.p.m)?op_eor_idpxb():op_eor_idpxw(); }
|
||||
|
||||
/************************
|
||||
*** 0x51: eor (dp),y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[4a] dbr,aah,aal+yl ; io [4]
|
||||
[5 ] dbr,aa+y ; data low
|
||||
[5a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_eor_idpyb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //4a
|
||||
regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.y.w); //5
|
||||
flags_eor_b();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_idpyw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //4a
|
||||
regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.y.w); //5
|
||||
regs.a.h ^= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a
|
||||
flags_eor_w();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_idpy() { (regs.p.m)?op_eor_idpyb():op_eor_idpyw(); }
|
||||
|
||||
/************************
|
||||
*** 0x57: eor [dp],y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] 0,d+dp+2 ; aab
|
||||
[6 ] aab,aa+y ; data low
|
||||
[6a] aab,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_eor_ildpyb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
regs.a.l ^= op_read(OPMODE_LONG, aa.d + regs.y.w); //6
|
||||
flags_eor_b();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_ildpyw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
regs.a.l ^= op_read(OPMODE_LONG, aa.d + regs.y.w); //6
|
||||
regs.a.h ^= op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a
|
||||
flags_eor_w();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_ildpy() { (regs.p.m)?op_eor_ildpyb():op_eor_ildpyw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x43: eor sr,s ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; sp
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+sp ; data low
|
||||
[4a] 0,s+sp+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_eor_srb() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
regs.a.l ^= op_read(OPMODE_SP, sp); //4
|
||||
flags_eor_b();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_srw() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
regs.a.l ^= op_read(OPMODE_SP, sp); //4
|
||||
regs.a.h ^= op_read(OPMODE_SP, sp + 1); //4a
|
||||
flags_eor_w();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_sr() { (regs.p.m)?op_eor_srb():op_eor_srw(); }
|
||||
|
||||
/**************************
|
||||
*** 0x53: eor (sr,s),y ***
|
||||
**************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; sp
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+sp ; aal
|
||||
[5 ] 0,s+sp+1 ; aah
|
||||
[6 ] 0,s+sp+1 ; io
|
||||
[7 ] dbr,aa+y ; data low
|
||||
[7a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_eor_isryb() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_SP, sp); //4
|
||||
aa.h = op_read(OPMODE_SP, sp + 1); //5
|
||||
cpu_io(); //6
|
||||
regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.y.w); //7
|
||||
flags_eor_b();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_isryw() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_SP, sp); //4
|
||||
aa.h = op_read(OPMODE_SP, sp + 1); //5
|
||||
cpu_io(); //6
|
||||
regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.y.w); //7
|
||||
regs.a.h ^= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a
|
||||
flags_eor_w();
|
||||
}
|
||||
|
||||
void bCPU::op_eor_isry() { (regs.p.m)?op_eor_isryb():op_eor_isryw(); }
|
||||
@@ -1,461 +0,0 @@
|
||||
/*****************
|
||||
*** 0x1a: inc ***
|
||||
*****************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; io
|
||||
*/
|
||||
void bCPU::op_incb() {
|
||||
cpu_io(); //2
|
||||
regs.a.l++;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_incw() {
|
||||
cpu_io(); //2
|
||||
regs.a.w++;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_inc() { (regs.p.m)?op_incb():op_incw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xee: inc addr ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aa ; data low
|
||||
[4a] dbr,aa+1 ; data high [1]
|
||||
[5 ] dbr,aa+1 ; io
|
||||
[6a] dbr,aa+1 ; data high [1]
|
||||
[6 ] dbr,aa ; data low
|
||||
*/
|
||||
void bCPU::op_inc_addrb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
rd.l++;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DBR, aa.w, rd.l); //6
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_inc_addrw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a
|
||||
rd.w++;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a
|
||||
op_write(OPMODE_DBR, aa.w, rd.l); //6
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_inc_addr() { (regs.p.m)?op_inc_addrb():op_inc_addrw(); }
|
||||
|
||||
/************************
|
||||
*** 0xfe: inc addr,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aah,aal+xl ; io
|
||||
[5 ] dbr,aa+x ; data low
|
||||
[5a] dbr,aa+x+1 ; data high [1]
|
||||
[6 ] dbr,aa+x+1 ; io
|
||||
[7a] dbr,aa+x+1 ; data high [1]
|
||||
[7 ] dbr,aa+x ; data low
|
||||
*/
|
||||
void bCPU::op_inc_addrxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_io(); //4
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
|
||||
rd.l++;
|
||||
cpu_io(); //6
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_inc_addrxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_io(); //4
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //5a
|
||||
rd.w++;
|
||||
cpu_io(); //6
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); //7a
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_inc_addrx() { (regs.p.m)?op_inc_addrxb():op_inc_addrxw(); }
|
||||
|
||||
/********************
|
||||
*** 0xe6: inc dp ***
|
||||
********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; data low
|
||||
[3a] 0,d+dp+1 ; data high [1]
|
||||
[4 ] 0,d+dp+1 ; io
|
||||
[5a] 0,d+dp+1 ; data high [1]
|
||||
[5 ] 0,d+dp ; data low
|
||||
*/
|
||||
void bCPU::op_inc_dpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
rd.l = op_read(OPMODE_DP, dp); //3
|
||||
rd.l++;
|
||||
cpu_io(); //4
|
||||
op_write(OPMODE_DP, dp, rd.l); //5
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_inc_dpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
rd.l = op_read(OPMODE_DP, dp); //3
|
||||
rd.h = op_read(OPMODE_DP, dp + 1); //3a
|
||||
rd.w++;
|
||||
cpu_io(); //4
|
||||
op_write(OPMODE_DP, dp + 1, rd.h); //5a
|
||||
op_write(OPMODE_DP, dp, rd.l); //5
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_inc_dp() { (regs.p.m)?op_inc_dpb():op_inc_dpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xf6: inc dp,x ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; data low
|
||||
[4a] 0,d+dp+x+1 ; data high [1]
|
||||
[5 ] 0,d+dp+x+1 ; io
|
||||
[6a] 0,d+dp+x+1 ; data high [1]
|
||||
[6 ] 0,d+dp+x ; data low
|
||||
*/
|
||||
void bCPU::op_inc_dpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
rd.l++;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_inc_dpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
|
||||
rd.w++;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); //6a
|
||||
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_inc_dpx() { (regs.p.m)?op_inc_dpxb():op_inc_dpxw(); }
|
||||
|
||||
/*****************
|
||||
*** 0xe8: inx ***
|
||||
*****************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; io
|
||||
*/
|
||||
void bCPU::op_inxb() {
|
||||
cpu_io(); //2
|
||||
regs.x.l++;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_inxw() {
|
||||
cpu_io(); //2
|
||||
regs.x.w++;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_inx() { (regs.p.x)?op_inxb():op_inxw(); }
|
||||
|
||||
/*****************
|
||||
*** 0xc8: iny ***
|
||||
*****************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; io
|
||||
*/
|
||||
void bCPU::op_inyb() {
|
||||
cpu_io(); //2
|
||||
regs.y.l++;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_inyw() {
|
||||
cpu_io(); //2
|
||||
regs.y.w++;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_iny() { (regs.p.x)?op_inyb():op_inyw(); }
|
||||
|
||||
/*****************
|
||||
*** 0x3a: dec ***
|
||||
*****************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; io
|
||||
*/
|
||||
void bCPU::op_decb() {
|
||||
cpu_io(); //2
|
||||
regs.a.l--;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_decw() {
|
||||
cpu_io(); //2
|
||||
regs.a.w--;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_dec() { (regs.p.m)?op_decb():op_decw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xce: dec addr ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aa ; data low
|
||||
[4a] dbr,aa+1 ; data high [1]
|
||||
[5 ] dbr,aa+1 ; io
|
||||
[6a] dbr,aa+1 ; data high [1]
|
||||
[6 ] dbr,aa ; data low
|
||||
*/
|
||||
void bCPU::op_dec_addrb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
rd.l--;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DBR, aa.w, rd.l); //6
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_dec_addrw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a
|
||||
rd.w--;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a
|
||||
op_write(OPMODE_DBR, aa.w, rd.l); //6
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_dec_addr() { (regs.p.m)?op_dec_addrb():op_dec_addrw(); }
|
||||
|
||||
/************************
|
||||
*** 0xde: dec addr,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aah,aal+xl ; io
|
||||
[5 ] dbr,aa+x ; data low
|
||||
[5a] dbr,aa+x+1 ; data high [1]
|
||||
[6 ] dbr,aa+x+1 ; io
|
||||
[7a] dbr,aa+x+1 ; data high [1]
|
||||
[7 ] dbr,aa+x ; data low
|
||||
*/
|
||||
void bCPU::op_dec_addrxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_io(); //4
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
|
||||
rd.l--;
|
||||
cpu_io(); //6
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_dec_addrxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_io(); //4
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //5a
|
||||
rd.w--;
|
||||
cpu_io(); //6
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); //7a
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_dec_addrx() { (regs.p.m)?op_dec_addrxb():op_dec_addrxw(); }
|
||||
|
||||
/********************
|
||||
*** 0xc6: dec dp ***
|
||||
********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; data low
|
||||
[3a] 0,d+dp+1 ; data high [1]
|
||||
[4 ] 0,d+dp+1 ; io
|
||||
[5a] 0,d+dp+1 ; data high [1]
|
||||
[5 ] 0,d+dp ; data low
|
||||
*/
|
||||
void bCPU::op_dec_dpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
rd.l = op_read(OPMODE_DP, dp); //3
|
||||
rd.l--;
|
||||
cpu_io(); //4
|
||||
op_write(OPMODE_DP, dp, rd.l); //5
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_dec_dpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
rd.l = op_read(OPMODE_DP, dp); //3
|
||||
rd.h = op_read(OPMODE_DP, dp + 1); //3a
|
||||
rd.w--;
|
||||
cpu_io(); //4
|
||||
op_write(OPMODE_DP, dp + 1, rd.h); //5a
|
||||
op_write(OPMODE_DP, dp, rd.l); //5
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_dec_dp() { (regs.p.m)?op_dec_dpb():op_dec_dpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xd6: dec dp,x ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; data low
|
||||
[4a] 0,d+dp+x+1 ; data high [1]
|
||||
[5 ] 0,d+dp+x+1 ; io
|
||||
[6a] 0,d+dp+x+1 ; data high [1]
|
||||
[6 ] 0,d+dp+x ; data low
|
||||
*/
|
||||
void bCPU::op_dec_dpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
rd.l--;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_dec_dpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
|
||||
rd.w--;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); //6a
|
||||
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_dec_dpx() { (regs.p.m)?op_dec_dpxb():op_dec_dpxw(); }
|
||||
|
||||
/*****************
|
||||
*** 0xca: dex ***
|
||||
*****************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; io
|
||||
*/
|
||||
void bCPU::op_dexb() {
|
||||
cpu_io(); //2
|
||||
regs.x.l--;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_dexw() {
|
||||
cpu_io(); //2
|
||||
regs.x.w--;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_dex() { (regs.p.x)?op_dexb():op_dexw(); }
|
||||
|
||||
/*****************
|
||||
*** 0x88: dey ***
|
||||
*****************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; io
|
||||
*/
|
||||
void bCPU::op_deyb() {
|
||||
cpu_io(); //2
|
||||
regs.y.l--;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_deyw() {
|
||||
cpu_io(); //2
|
||||
regs.y.w--;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_dey() { (regs.p.x)?op_deyb():op_deyw(); }
|
||||
@@ -1,474 +0,0 @@
|
||||
void bCPU::flags_lda_b() {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::flags_lda_w() {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
/************************
|
||||
*** 0xa9: lda #const ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; idl
|
||||
[2a] pbr,pc+2 ; idh [1]
|
||||
*/
|
||||
void bCPU::op_lda_constb() {
|
||||
regs.a.l = op_read(); //2
|
||||
flags_lda_b();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_constw() {
|
||||
regs.a.l = op_read(); //2
|
||||
regs.a.h = op_read(); //2a
|
||||
flags_lda_w();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_const() { (regs.p.m)?op_lda_constb():op_lda_constw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xad: lda addr ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aa ; data low
|
||||
[4a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_lda_addrb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
regs.a.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
flags_lda_b();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_addrw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
regs.a.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
regs.a.h = op_read(OPMODE_DBR, aa.w + 1); //4a
|
||||
flags_lda_w();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_addr() { (regs.p.m)?op_lda_addrb():op_lda_addrw(); }
|
||||
|
||||
/************************
|
||||
*** 0xbd: lda addr,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; operand
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[3a] dbr,aah,aal+xl ; io [4]
|
||||
[4 ] dbr,aa+x ; data low
|
||||
[4a] dbr,aa+x+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_lda_addrxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.x.w); //3a
|
||||
regs.a.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4
|
||||
flags_lda_b();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_addrxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.x.w); //3a
|
||||
regs.a.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4
|
||||
regs.a.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a
|
||||
flags_lda_w();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_addrx() { (regs.p.m)?op_lda_addrxb():op_lda_addrxw(); }
|
||||
|
||||
/********************
|
||||
*** 0xa5: lda dp ***
|
||||
********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; operand
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; data low
|
||||
[3a] 0,d+dp+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_lda_dpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
regs.a.l = op_read(OPMODE_DP, dp); //3
|
||||
flags_lda_b();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_dpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
regs.a.l = op_read(OPMODE_DP, dp); //3
|
||||
regs.a.h = op_read(OPMODE_DP, dp + 1); //3a
|
||||
flags_lda_w();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_dp() { (regs.p.m)?op_lda_dpb():op_lda_dpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xb2: lda (dp) ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] dbr,aa ; data low
|
||||
[5a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_lda_idpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
regs.a.l = op_read(OPMODE_DBR, aa.w); //5
|
||||
flags_lda_b();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_idpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
regs.a.l = op_read(OPMODE_DBR, aa.w); //5
|
||||
regs.a.h = op_read(OPMODE_DBR, aa.w + 1); //5
|
||||
flags_lda_w();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_idp() { (regs.p.m)?op_lda_idpb():op_lda_idpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xa7: lda [dp] ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] 0,d+dp+2 ; aab
|
||||
[6 ] aab,aa ; data low
|
||||
[6a] aab,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_lda_ildpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
regs.a.l = op_read(OPMODE_LONG, aa.d); //6
|
||||
flags_lda_b();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_ildpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
regs.a.l = op_read(OPMODE_LONG, aa.d); //6
|
||||
regs.a.h = op_read(OPMODE_LONG, aa.d + 1); //6a
|
||||
flags_lda_w();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_ildp() { (regs.p.m)?op_lda_ildpb():op_lda_ildpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xaf: lda long ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] pbr,pc+3 ; aab
|
||||
[5 ] aab,aa ; data low
|
||||
[5a] aab,aa+1 ; data high
|
||||
*/
|
||||
void bCPU::op_lda_longb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
regs.a.l = op_read(OPMODE_LONG, aa.d); //5
|
||||
flags_lda_b();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_longw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
regs.a.l = op_read(OPMODE_LONG, aa.d); //5
|
||||
regs.a.h = op_read(OPMODE_LONG, aa.d + 1); //5a
|
||||
flags_lda_w();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_long() { (regs.p.m)?op_lda_longb():op_lda_longw(); }
|
||||
|
||||
/************************
|
||||
*** 0xbf: lda long,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] pbr,pc+3 ; aab
|
||||
[5 ] aab,aa+x ; data low
|
||||
[5a] aab,aa+x+1 ; data high
|
||||
*/
|
||||
void bCPU::op_lda_longxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
regs.a.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5
|
||||
flags_lda_b();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_longxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
regs.a.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5
|
||||
regs.a.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a
|
||||
flags_lda_w();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_longx() { (regs.p.m)?op_lda_longxb():op_lda_longxw(); }
|
||||
|
||||
/************************
|
||||
*** 0xb9: lda addr,y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; operand
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[3a] dbr,aah,aal+yl ; io [4]
|
||||
[4 ] dbr,aa+y ; data low
|
||||
[4a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_lda_addryb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //3a
|
||||
regs.a.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4
|
||||
flags_lda_b();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_addryw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //3a
|
||||
regs.a.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4
|
||||
regs.a.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a
|
||||
flags_lda_w();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_addry() { (regs.p.m)?op_lda_addryb():op_lda_addryw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xb5: lda dp,x ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; data low
|
||||
[4a] 0,d+dp+x+1 ; data high
|
||||
*/
|
||||
void bCPU::op_lda_dpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
regs.a.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
flags_lda_b();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_dpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
regs.a.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
regs.a.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
|
||||
flags_lda_w();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_dpx() { (regs.p.m)?op_lda_dpxb():op_lda_dpxw(); }
|
||||
|
||||
/************************
|
||||
*** 0xa1: lda (dp,x) ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; aal
|
||||
[5 ] 0,d+dp+x+1 ; aah
|
||||
[6 ] dbr,aa ; data low
|
||||
[6a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_lda_idpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
|
||||
regs.a.l = op_read(OPMODE_DBR, aa.w); //6
|
||||
flags_lda_b();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_idpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
|
||||
regs.a.l = op_read(OPMODE_DBR, aa.w); //6
|
||||
regs.a.h = op_read(OPMODE_DBR, aa.w + 1); //6a
|
||||
flags_lda_w();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_idpx() { (regs.p.m)?op_lda_idpxb():op_lda_idpxw(); }
|
||||
|
||||
/************************
|
||||
*** 0xb1: lda (dp),y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[4a] dbr,aah,aal+yl ; io [4]
|
||||
[5 ] dbr,aa+y ; data low
|
||||
[5a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_lda_idpyb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //4a
|
||||
regs.a.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5
|
||||
flags_lda_b();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_idpyw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //4a
|
||||
regs.a.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5
|
||||
regs.a.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a
|
||||
flags_lda_w();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_idpy() { (regs.p.m)?op_lda_idpyb():op_lda_idpyw(); }
|
||||
|
||||
/************************
|
||||
*** 0xb7: lda [dp],y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] 0,d+dp+2 ; aab
|
||||
[6 ] aab,aa+y ; data low
|
||||
[6a] aab,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_lda_ildpyb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
regs.a.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6
|
||||
flags_lda_b();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_ildpyw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
regs.a.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6
|
||||
regs.a.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a
|
||||
flags_lda_w();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_ildpy() { (regs.p.m)?op_lda_ildpyb():op_lda_ildpyw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xa3: lda sr,s ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; sp
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+sp ; data low
|
||||
[4a] 0,s+sp+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_lda_srb() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
regs.a.l = op_read(OPMODE_SP, sp); //4
|
||||
flags_lda_b();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_srw() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
regs.a.l = op_read(OPMODE_SP, sp); //4
|
||||
regs.a.h = op_read(OPMODE_SP, sp + 1); //4a
|
||||
flags_lda_w();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_sr() { (regs.p.m)?op_lda_srb():op_lda_srw(); }
|
||||
|
||||
/**************************
|
||||
*** 0xb3: lda (sr,s),y ***
|
||||
**************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; sp
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+sp ; aal
|
||||
[5 ] 0,s+sp+1 ; aah
|
||||
[6 ] 0,s+sp+1 ; io
|
||||
[7 ] dbr,aa+y ; data low
|
||||
[7a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_lda_isryb() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_SP, sp); //4
|
||||
aa.h = op_read(OPMODE_SP, sp + 1); //5
|
||||
cpu_io(); //6
|
||||
regs.a.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7
|
||||
flags_lda_b();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_isryw() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_SP, sp); //4
|
||||
aa.h = op_read(OPMODE_SP, sp + 1); //5
|
||||
cpu_io(); //6
|
||||
regs.a.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7
|
||||
regs.a.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a
|
||||
flags_lda_w();
|
||||
}
|
||||
|
||||
void bCPU::op_lda_isry() { (regs.p.m)?op_lda_isryb():op_lda_isryw(); }
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,474 +0,0 @@
|
||||
void bCPU::flags_ora_b() {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::flags_ora_w() {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
/************************
|
||||
*** 0x09: ora #const ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; idl
|
||||
[2a] pbr,pc+2 ; idh [1]
|
||||
*/
|
||||
void bCPU::op_ora_constb() {
|
||||
regs.a.l |= op_read(); //2
|
||||
flags_ora_b();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_constw() {
|
||||
regs.a.l |= op_read(); //2
|
||||
regs.a.h |= op_read(); //2a
|
||||
flags_ora_w();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_const() { (regs.p.m)?op_ora_constb():op_ora_constw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x0d: ora addr ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aa ; data low
|
||||
[4a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_ora_addrb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
regs.a.l |= op_read(OPMODE_DBR, aa.w); //4
|
||||
flags_ora_b();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_addrw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
regs.a.l |= op_read(OPMODE_DBR, aa.w); //4
|
||||
regs.a.h |= op_read(OPMODE_DBR, aa.w + 1); //4a
|
||||
flags_ora_w();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_addr() { (regs.p.m)?op_ora_addrb():op_ora_addrw(); }
|
||||
|
||||
/************************
|
||||
*** 0x1d: ora addr,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; operora
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[3a] dbr,aah,aal+xl ; io [4]
|
||||
[4 ] dbr,aa+x ; data low
|
||||
[4a] dbr,aa+x+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_ora_addrxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.x.w); //3a
|
||||
regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.x.w); //4
|
||||
flags_ora_b();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_addrxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.x.w); //3a
|
||||
regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.x.w); //4
|
||||
regs.a.h |= op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a
|
||||
flags_ora_w();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_addrx() { (regs.p.m)?op_ora_addrxb():op_ora_addrxw(); }
|
||||
|
||||
/********************
|
||||
*** 0x05: ora dp ***
|
||||
********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; operora
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; data low
|
||||
[3a] 0,d+dp+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_ora_dpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
regs.a.l |= op_read(OPMODE_DP, dp); //3
|
||||
flags_ora_b();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_dpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
regs.a.l |= op_read(OPMODE_DP, dp); //3
|
||||
regs.a.h |= op_read(OPMODE_DP, dp + 1); //3a
|
||||
flags_ora_w();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_dp() { (regs.p.m)?op_ora_dpb():op_ora_dpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x12: ora (dp) ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] dbr,aa ; data low
|
||||
[5a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_ora_idpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
regs.a.l |= op_read(OPMODE_DBR, aa.w); //5
|
||||
flags_ora_b();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_idpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
regs.a.l |= op_read(OPMODE_DBR, aa.w); //5
|
||||
regs.a.h |= op_read(OPMODE_DBR, aa.w + 1); //5
|
||||
flags_ora_w();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_idp() { (regs.p.m)?op_ora_idpb():op_ora_idpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x07: ora [dp] ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] 0,d+dp+2 ; aab
|
||||
[6 ] aab,aa ; data low
|
||||
[6a] aab,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_ora_ildpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
regs.a.l |= op_read(OPMODE_LONG, aa.d); //6
|
||||
flags_ora_b();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_ildpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
regs.a.l |= op_read(OPMODE_LONG, aa.d); //6
|
||||
regs.a.h |= op_read(OPMODE_LONG, aa.d + 1); //6a
|
||||
flags_ora_w();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_ildp() { (regs.p.m)?op_ora_ildpb():op_ora_ildpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x0f: ora long ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] pbr,pc+3 ; aab
|
||||
[5 ] aab,aa ; data low
|
||||
[5a] aab,aa+1 ; data high
|
||||
*/
|
||||
void bCPU::op_ora_longb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
regs.a.l |= op_read(OPMODE_LONG, aa.d); //5
|
||||
flags_ora_b();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_longw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
regs.a.l |= op_read(OPMODE_LONG, aa.d); //5
|
||||
regs.a.h |= op_read(OPMODE_LONG, aa.d + 1); //5a
|
||||
flags_ora_w();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_long() { (regs.p.m)?op_ora_longb():op_ora_longw(); }
|
||||
|
||||
/************************
|
||||
*** 0x1f: ora long,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] pbr,pc+3 ; aab
|
||||
[5 ] aab,aa+x ; data low
|
||||
[5a] aab,aa+x+1 ; data high
|
||||
*/
|
||||
void bCPU::op_ora_longxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
regs.a.l |= op_read(OPMODE_LONG, aa.d + regs.x.w); //5
|
||||
flags_ora_b();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_longxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
regs.a.l |= op_read(OPMODE_LONG, aa.d + regs.x.w); //5
|
||||
regs.a.h |= op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a
|
||||
flags_ora_w();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_longx() { (regs.p.m)?op_ora_longxb():op_ora_longxw(); }
|
||||
|
||||
/************************
|
||||
*** 0x19: ora addr,y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; operora
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[3a] dbr,aah,aal+yl ; io [4]
|
||||
[4 ] dbr,aa+y ; data low
|
||||
[4a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_ora_addryb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //3a
|
||||
regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.y.w); //4
|
||||
flags_ora_b();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_addryw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //3a
|
||||
regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.y.w); //4
|
||||
regs.a.h |= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a
|
||||
flags_ora_w();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_addry() { (regs.p.m)?op_ora_addryb():op_ora_addryw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x15: ora dp,x ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; data low
|
||||
[4a] 0,d+dp+x+1 ; data high
|
||||
*/
|
||||
void bCPU::op_ora_dpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
regs.a.l |= op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
flags_ora_b();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_dpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
regs.a.l |= op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
regs.a.h |= op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
|
||||
flags_ora_w();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_dpx() { (regs.p.m)?op_ora_dpxb():op_ora_dpxw(); }
|
||||
|
||||
/************************
|
||||
*** 0x01: ora (dp,x) ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; aal
|
||||
[5 ] 0,d+dp+x+1 ; aah
|
||||
[6 ] dbr,aa ; data low
|
||||
[6a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_ora_idpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
|
||||
regs.a.l |= op_read(OPMODE_DBR, aa.w); //6
|
||||
flags_ora_b();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_idpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
|
||||
regs.a.l |= op_read(OPMODE_DBR, aa.w); //6
|
||||
regs.a.h |= op_read(OPMODE_DBR, aa.w + 1); //6a
|
||||
flags_ora_w();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_idpx() { (regs.p.m)?op_ora_idpxb():op_ora_idpxw(); }
|
||||
|
||||
/************************
|
||||
*** 0x11: ora (dp),y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[4a] dbr,aah,aal+yl ; io [4]
|
||||
[5 ] dbr,aa+y ; data low
|
||||
[5a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_ora_idpyb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //4a
|
||||
regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.y.w); //5
|
||||
flags_ora_b();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_idpyw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //4a
|
||||
regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.y.w); //5
|
||||
regs.a.h |= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a
|
||||
flags_ora_w();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_idpy() { (regs.p.m)?op_ora_idpyb():op_ora_idpyw(); }
|
||||
|
||||
/************************
|
||||
*** 0x17: ora [dp],y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] 0,d+dp+2 ; aab
|
||||
[6 ] aab,aa+y ; data low
|
||||
[6a] aab,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_ora_ildpyb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
regs.a.l |= op_read(OPMODE_LONG, aa.d + regs.y.w); //6
|
||||
flags_ora_b();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_ildpyw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
regs.a.l |= op_read(OPMODE_LONG, aa.d + regs.y.w); //6
|
||||
regs.a.h |= op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a
|
||||
flags_ora_w();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_ildpy() { (regs.p.m)?op_ora_ildpyb():op_ora_ildpyw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x03: ora sr,s ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; sp
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+sp ; data low
|
||||
[4a] 0,s+sp+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_ora_srb() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
regs.a.l |= op_read(OPMODE_SP, sp); //4
|
||||
flags_ora_b();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_srw() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
regs.a.l |= op_read(OPMODE_SP, sp); //4
|
||||
regs.a.h |= op_read(OPMODE_SP, sp + 1); //4a
|
||||
flags_ora_w();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_sr() { (regs.p.m)?op_ora_srb():op_ora_srw(); }
|
||||
|
||||
/**************************
|
||||
*** 0x13: ora (sr,s),y ***
|
||||
**************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; sp
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+sp ; aal
|
||||
[5 ] 0,s+sp+1 ; aah
|
||||
[6 ] 0,s+sp+1 ; io
|
||||
[7 ] dbr,aa+y ; data low
|
||||
[7a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_ora_isryb() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_SP, sp); //4
|
||||
aa.h = op_read(OPMODE_SP, sp + 1); //5
|
||||
cpu_io(); //6
|
||||
regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.y.w); //7
|
||||
flags_ora_b();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_isryw() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_SP, sp); //4
|
||||
aa.h = op_read(OPMODE_SP, sp + 1); //5
|
||||
cpu_io(); //6
|
||||
regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.y.w); //7
|
||||
regs.a.h |= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a
|
||||
flags_ora_w();
|
||||
}
|
||||
|
||||
void bCPU::op_ora_isry() { (regs.p.m)?op_ora_isryb():op_ora_isryw(); }
|
||||
@@ -1,436 +0,0 @@
|
||||
/**********************
|
||||
*** 0x4c: jmp addr ***
|
||||
**********************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; new pcl
|
||||
[3] pbr,pc+2 ; new pch
|
||||
*/
|
||||
void bCPU::op_jmp_addr() {
|
||||
rd.l = op_read(); //2
|
||||
rd.h = op_read(); //3
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
/**********************
|
||||
*** 0x5c: jmp long ***
|
||||
**********************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; new pcl
|
||||
[3] pbr,pc+2 ; new pch
|
||||
[4] pbr,pc+3 ; new pbr
|
||||
*/
|
||||
void bCPU::op_jmp_long() {
|
||||
rd.l = op_read(); //2
|
||||
rd.h = op_read(); //3
|
||||
rd.b = op_read(); //4
|
||||
regs.pc.d = rd.d;
|
||||
}
|
||||
|
||||
/************************
|
||||
*** 0x6c: jmp (addr) ***
|
||||
************************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; aal
|
||||
[3] pbr,pc+2 ; aah
|
||||
[4] 0,aa ; new pcl
|
||||
[5] 0,aa+1 ; new pch
|
||||
*/
|
||||
void bCPU::op_jmp_iaddr() {
|
||||
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
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
/**************************
|
||||
*** 0x7c: jmp (addr,x) ***
|
||||
**************************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; aal
|
||||
[3] pbr,pc+2 ; aah
|
||||
[4] pbr,pc+2 ; io
|
||||
[5] pbr,aa+x ; new pcl
|
||||
[6] pbr,aa+x+1 ; new pch
|
||||
*/
|
||||
void bCPU::op_jmp_iaddrx() {
|
||||
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
|
||||
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1); //6
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
/************************
|
||||
*** 0xdc: jmp [addr] ***
|
||||
************************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; aal
|
||||
[3] pbr,pc+2 ; aah
|
||||
[4] 0,aa ; new pcl
|
||||
[5] 0,aa+1 ; new pch
|
||||
[6] 0,aa+2 ; new pbr
|
||||
*/
|
||||
void bCPU::op_jmp_iladdr() {
|
||||
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
|
||||
rd.b = op_read(OPMODE_ADDR, aa.w + 2); //6
|
||||
regs.pc.d = rd.d;
|
||||
}
|
||||
|
||||
/**********************
|
||||
*** 0x20: jsr addr ***
|
||||
**********************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; new pcl
|
||||
[3] pbr,pc+2 ; new pch
|
||||
[4] pbr,pc+2 ; io
|
||||
[5] 0,s ; pch
|
||||
[6] 0,s-1 ; pcl
|
||||
*/
|
||||
void bCPU::op_jsr_addr() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_io(); //4
|
||||
regs.pc.w--;
|
||||
stack_write(regs.pc.h); //5
|
||||
stack_write(regs.pc.l); //6
|
||||
regs.pc.w = aa.w;
|
||||
}
|
||||
|
||||
/**********************
|
||||
*** 0x22: jsr long ***
|
||||
**********************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; new pcl
|
||||
[3] pbr,pc+2 ; new pch
|
||||
[4] 0,s ; pbr
|
||||
[5] 0,s ; io
|
||||
[6] pbr,pc+3 ; new pbr
|
||||
[7] 0,s-1 ; pch
|
||||
[8] 0,s-2 ; pcl
|
||||
*/
|
||||
void bCPU::op_jsr_long() {
|
||||
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
|
||||
stack_write(regs.pc.l); //8
|
||||
regs.pc.d = aa.d;
|
||||
}
|
||||
|
||||
/**************************
|
||||
*** 0xfc: jsr (addr,x) ***
|
||||
**************************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; aal
|
||||
[3] 0,s ; pch
|
||||
[4] 0,s-1 ; pcl
|
||||
[5] pbr,pc+2 ; aah
|
||||
[6] pbr,pc+2 ; io
|
||||
[7] pbr,aa+x ; new pcl
|
||||
[8] pbr,aa+x+1 ; new pch
|
||||
*/
|
||||
void bCPU::op_jsr_iaddrx() {
|
||||
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
|
||||
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1); //8
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
/*****************
|
||||
*** 0x40: rti ***
|
||||
*****************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; io
|
||||
[3] pbr,pc+1 ; io
|
||||
[4] 0,s+1 ; p
|
||||
[5] 0,s+2 ; new pcl
|
||||
[6] 0,s+3 ; new pch
|
||||
[7] 0,s+4 ; pbr [7]
|
||||
*/
|
||||
void bCPU::op_rtie() {
|
||||
cpu_io(); //2
|
||||
cpu_io(); //3
|
||||
regs.p = stack_read(); //4
|
||||
rd.l = stack_read(); //5
|
||||
rd.h = stack_read(); //6
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
void bCPU::op_rtin() {
|
||||
cpu_io(); //2
|
||||
cpu_io(); //3
|
||||
regs.p = stack_read(); //4
|
||||
rd.l = stack_read(); //5
|
||||
rd.h = stack_read(); //6
|
||||
rd.b = stack_read(); //7
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
regs.pc.d = rd.d;
|
||||
}
|
||||
|
||||
void bCPU::op_rti() { (regs.e)?op_rtie():op_rtin(); }
|
||||
|
||||
/*****************
|
||||
*** 0x60: rts ***
|
||||
*****************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; io
|
||||
[3] pbr,pc+1 ; io
|
||||
[4] 0,s+1 ; pcl
|
||||
[5] 0,s+2 ; pch
|
||||
[6] 0,s+2 ; io
|
||||
*/
|
||||
void bCPU::op_rts() {
|
||||
cpu_io(); //2
|
||||
cpu_io(); //3
|
||||
rd.l = stack_read(); //4
|
||||
rd.h = stack_read(); //5
|
||||
cpu_io(); //6
|
||||
regs.pc.w = rd.w;
|
||||
regs.pc.w++;
|
||||
}
|
||||
|
||||
/*****************
|
||||
*** 0x6b: rtl ***
|
||||
*****************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; io
|
||||
[3] pbr,pc+1 ; io
|
||||
[4] 0,s+1 ; pcl
|
||||
[5] 0,s+2 ; pch
|
||||
[6] 0,s+3 ; pbr
|
||||
*/
|
||||
void bCPU::op_rtl() {
|
||||
cpu_io(); //2
|
||||
cpu_io(); //3
|
||||
rd.l = stack_read(); //4
|
||||
rd.h = stack_read(); //5
|
||||
rd.b = stack_read(); //6
|
||||
regs.pc.d = rd.d;
|
||||
regs.pc.w++;
|
||||
}
|
||||
|
||||
/**********************
|
||||
*** 0x80: bra near ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; offset
|
||||
[2a] pbr,pc+1 ; io [5]
|
||||
[2b] pbr,pc+1 ; io [6]
|
||||
*/
|
||||
void bCPU::op_bra() {
|
||||
uint16 r;
|
||||
rd.l = op_read(); //2
|
||||
cpu_io(); //2a
|
||||
r = regs.pc + (int8)rd.l;
|
||||
cpu_c6(r); //2b
|
||||
regs.pc.w = r;
|
||||
}
|
||||
|
||||
/*********************
|
||||
*** 0x82: brl far ***
|
||||
*********************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; offset low
|
||||
[3] pbr,pc+2 ; offset high
|
||||
[4] pbr,pc+2 ; io
|
||||
*/
|
||||
void bCPU::op_brl() {
|
||||
uint16 r;
|
||||
rd.l = op_read(); //2
|
||||
rd.h = op_read(); //3
|
||||
cpu_io(); //4
|
||||
r = regs.pc + (int16)rd.w;
|
||||
regs.pc.w = r;
|
||||
}
|
||||
|
||||
/**********************
|
||||
*** 0x90: bcc near ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; offset
|
||||
[2a] pbr,pc+1 ; io [5]
|
||||
[2b] pbr,pc+1 ; io [6]
|
||||
*/
|
||||
void bCPU::op_bcc() {
|
||||
uint16 r;
|
||||
rd.l = op_read(); //2
|
||||
if(!regs.p.c) {
|
||||
cpu_io(); //2a
|
||||
r = regs.pc + (int8)rd.l;
|
||||
cpu_c6(r); //2b
|
||||
regs.pc.w = r;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
*** 0xb0: bcs near ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; offset
|
||||
[2a] pbr,pc+1 ; io [5]
|
||||
[2b] pbr,pc+1 ; io [6]
|
||||
*/
|
||||
void bCPU::op_bcs() {
|
||||
uint16 r;
|
||||
rd.l = op_read(); //2
|
||||
if(regs.p.c) {
|
||||
cpu_io(); //2a
|
||||
r = regs.pc + (int8)rd.l;
|
||||
cpu_c6(r); //2b
|
||||
regs.pc.w = r;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
*** 0xd0: bne near ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; offset
|
||||
[2a] pbr,pc+1 ; io [5]
|
||||
[2b] pbr,pc+1 ; io [6]
|
||||
*/
|
||||
void bCPU::op_bne() {
|
||||
uint16 r;
|
||||
rd.l = op_read(); //2
|
||||
if(!regs.p.z) {
|
||||
cpu_io(); //2a
|
||||
r = regs.pc + (int8)rd.l;
|
||||
cpu_c6(r); //2b
|
||||
regs.pc.w = r;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
*** 0xf0: beq near ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; offset
|
||||
[2a] pbr,pc+1 ; io [5]
|
||||
[2b] pbr,pc+1 ; io [6]
|
||||
*/
|
||||
void bCPU::op_beq() {
|
||||
uint16 r;
|
||||
rd.l = op_read(); //2
|
||||
if(regs.p.z) {
|
||||
cpu_io(); //2a
|
||||
r = regs.pc + (int8)rd.l;
|
||||
cpu_c6(r); //2b
|
||||
regs.pc.w = r;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
*** 0x10: bpl near ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; offset
|
||||
[2a] pbr,pc+1 ; io [5]
|
||||
[2b] pbr,pc+1 ; io [6]
|
||||
*/
|
||||
void bCPU::op_bpl() {
|
||||
uint16 r;
|
||||
rd.l = op_read(); //2
|
||||
if(!regs.p.n) {
|
||||
cpu_io(); //2a
|
||||
r = regs.pc + (int8)rd.l;
|
||||
cpu_c6(r); //2b
|
||||
regs.pc.w = r;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
*** 0x30: bmi near ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; offset
|
||||
[2a] pbr,pc+1 ; io [5]
|
||||
[2b] pbr,pc+1 ; io [6]
|
||||
*/
|
||||
void bCPU::op_bmi() {
|
||||
uint16 r;
|
||||
rd.l = op_read(); //2
|
||||
if(regs.p.n) {
|
||||
cpu_io(); //2a
|
||||
r = regs.pc + (int8)rd.l;
|
||||
cpu_c6(r); //2b
|
||||
regs.pc.w = r;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
*** 0x50: bvc near ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; offset
|
||||
[2a] pbr,pc+1 ; io [5]
|
||||
[2b] pbr,pc+1 ; io [6]
|
||||
*/
|
||||
void bCPU::op_bvc() {
|
||||
uint16 r;
|
||||
rd.l = op_read(); //2
|
||||
if(!regs.p.v) {
|
||||
cpu_io(); //2a
|
||||
r = regs.pc + (int8)rd.l;
|
||||
cpu_c6(r); //2b
|
||||
regs.pc.w = r;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
*** 0x70: bvs near ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; offset
|
||||
[2a] pbr,pc+1 ; io [5]
|
||||
[2b] pbr,pc+1 ; io [6]
|
||||
*/
|
||||
void bCPU::op_bvs() {
|
||||
uint16 r;
|
||||
rd.l = op_read(); //2
|
||||
if(regs.p.v) {
|
||||
cpu_io(); //2a
|
||||
r = regs.pc + (int8)rd.l;
|
||||
cpu_c6(r); //2b
|
||||
regs.pc.w = r;
|
||||
}
|
||||
}
|
||||
@@ -1,494 +0,0 @@
|
||||
void bCPU::flags_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;
|
||||
}
|
||||
|
||||
void bCPU::flags_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;
|
||||
}
|
||||
|
||||
/************************
|
||||
*** 0xe9: sbc #const ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; idl
|
||||
[2a] pbr,pc+2 ; idh [1]
|
||||
*/
|
||||
void bCPU::op_sbc_constb() {
|
||||
rd.l = op_read(); //2
|
||||
flags_sbc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_constw() {
|
||||
rd.l = op_read(); //2
|
||||
rd.h = op_read(); //2a
|
||||
flags_sbc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_const() { (regs.p.m)?op_sbc_constb():op_sbc_constw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xed: sbc addr ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aa ; data low
|
||||
[4a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sbc_addrb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
flags_sbc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_addrw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a
|
||||
flags_sbc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_addr() { (regs.p.m)?op_sbc_addrb():op_sbc_addrw(); }
|
||||
|
||||
/************************
|
||||
*** 0xfd: sbc addr,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opersbc
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[3a] dbr,aah,aal+xl ; io [4]
|
||||
[4 ] dbr,aa+x ; data low
|
||||
[4a] dbr,aa+x+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sbc_addrxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.x.w); //3a
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4
|
||||
flags_sbc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_addrxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.x.w); //3a
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a
|
||||
flags_sbc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_addrx() { (regs.p.m)?op_sbc_addrxb():op_sbc_addrxw(); }
|
||||
|
||||
/********************
|
||||
*** 0xe5: sbc dp ***
|
||||
********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opersbc
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; data low
|
||||
[3a] 0,d+dp+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sbc_dpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
rd.l = op_read(OPMODE_DP, dp); //3
|
||||
flags_sbc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_dpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
rd.l = op_read(OPMODE_DP, dp); //3
|
||||
rd.h = op_read(OPMODE_DP, dp + 1); //3a
|
||||
flags_sbc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_dp() { (regs.p.m)?op_sbc_dpb():op_sbc_dpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xf2: sbc (dp) ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] dbr,aa ; data low
|
||||
[5a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sbc_idpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //5
|
||||
flags_sbc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_idpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //5
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + 1); //5
|
||||
flags_sbc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_idp() { (regs.p.m)?op_sbc_idpb():op_sbc_idpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xe7: sbc [dp] ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] 0,d+dp+2 ; aab
|
||||
[6 ] aab,aa ; data low
|
||||
[6a] aab,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sbc_ildpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
rd.l = op_read(OPMODE_LONG, aa.d); //6
|
||||
flags_sbc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_ildpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
rd.l = op_read(OPMODE_LONG, aa.d); //6
|
||||
rd.h = op_read(OPMODE_LONG, aa.d + 1); //6a
|
||||
flags_sbc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_ildp() { (regs.p.m)?op_sbc_ildpb():op_sbc_ildpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xef: sbc long ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] pbr,pc+3 ; aab
|
||||
[5 ] aab,aa ; data low
|
||||
[5a] aab,aa+1 ; data high
|
||||
*/
|
||||
void bCPU::op_sbc_longb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
rd.l = op_read(OPMODE_LONG, aa.d); //5
|
||||
flags_sbc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_longw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
rd.l = op_read(OPMODE_LONG, aa.d); //5
|
||||
rd.h = op_read(OPMODE_LONG, aa.d + 1); //5a
|
||||
flags_sbc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_long() { (regs.p.m)?op_sbc_longb():op_sbc_longw(); }
|
||||
|
||||
/************************
|
||||
*** 0xff: sbc long,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] pbr,pc+3 ; aab
|
||||
[5 ] aab,aa+x ; data low
|
||||
[5a] aab,aa+x+1 ; data high
|
||||
*/
|
||||
void bCPU::op_sbc_longxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5
|
||||
flags_sbc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_longxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5
|
||||
rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a
|
||||
flags_sbc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_longx() { (regs.p.m)?op_sbc_longxb():op_sbc_longxw(); }
|
||||
|
||||
/************************
|
||||
*** 0xf9: sbc addr,y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opersbc
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[3a] dbr,aah,aal+yl ; io [4]
|
||||
[4 ] dbr,aa+y ; data low
|
||||
[4a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sbc_addryb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //3a
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4
|
||||
flags_sbc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_addryw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //3a
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a
|
||||
flags_sbc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_addry() { (regs.p.m)?op_sbc_addryb():op_sbc_addryw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xf5: sbc dp,x ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; data low
|
||||
[4a] 0,d+dp+x+1 ; data high
|
||||
*/
|
||||
void bCPU::op_sbc_dpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
flags_sbc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_dpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
|
||||
flags_sbc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_dpx() { (regs.p.m)?op_sbc_dpxb():op_sbc_dpxw(); }
|
||||
|
||||
/************************
|
||||
*** 0xe1: sbc (dp,x) ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; aal
|
||||
[5 ] 0,d+dp+x+1 ; aah
|
||||
[6 ] dbr,aa ; data low
|
||||
[6a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sbc_idpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //6
|
||||
flags_sbc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_idpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //6
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + 1); //6a
|
||||
flags_sbc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_idpx() { (regs.p.m)?op_sbc_idpxb():op_sbc_idpxw(); }
|
||||
|
||||
/************************
|
||||
*** 0xf1: sbc (dp),y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[4a] dbr,aah,aal+yl ; io [4]
|
||||
[5 ] dbr,aa+y ; data low
|
||||
[5a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sbc_idpyb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //4a
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5
|
||||
flags_sbc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_idpyw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //4a
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a
|
||||
flags_sbc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_idpy() { (regs.p.m)?op_sbc_idpyb():op_sbc_idpyw(); }
|
||||
|
||||
/************************
|
||||
*** 0xf7: sbc [dp],y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] 0,d+dp+2 ; aab
|
||||
[6 ] aab,aa+y ; data low
|
||||
[6a] aab,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sbc_ildpyb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6
|
||||
flags_sbc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_ildpyw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6
|
||||
rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a
|
||||
flags_sbc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_ildpy() { (regs.p.m)?op_sbc_ildpyb():op_sbc_ildpyw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xe3: sbc sr,s ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; sp
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+sp ; data low
|
||||
[4a] 0,s+sp+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sbc_srb() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_SP, sp); //4
|
||||
flags_sbc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_srw() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_SP, sp); //4
|
||||
rd.h = op_read(OPMODE_SP, sp + 1); //4a
|
||||
flags_sbc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_sr() { (regs.p.m)?op_sbc_srb():op_sbc_srw(); }
|
||||
|
||||
/**************************
|
||||
*** 0xf3: sbc (sr,s),y ***
|
||||
**************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; sp
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+sp ; aal
|
||||
[5 ] 0,s+sp+1 ; aah
|
||||
[6 ] 0,s+sp+1 ; io
|
||||
[7 ] dbr,aa+y ; data low
|
||||
[7a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sbc_isryb() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_SP, sp); //4
|
||||
aa.h = op_read(OPMODE_SP, sp + 1); //5
|
||||
cpu_io(); //6
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7
|
||||
flags_sbc_b();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_isryw() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_SP, sp); //4
|
||||
aa.h = op_read(OPMODE_SP, sp + 1); //5
|
||||
cpu_io(); //6
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a
|
||||
flags_sbc_w();
|
||||
}
|
||||
|
||||
void bCPU::op_sbc_isry() { (regs.p.m)?op_sbc_isryb():op_sbc_isryw(); }
|
||||
@@ -1,819 +0,0 @@
|
||||
/*****************
|
||||
*** 0x0a: asl ***
|
||||
*****************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; io
|
||||
*/
|
||||
void bCPU::op_aslb() {
|
||||
cpu_io(); //2
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_aslw() {
|
||||
cpu_io(); //2
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_asl() { (regs.p.m)?op_aslb():op_aslw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x0e: asl addr ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aa ; data low
|
||||
[4a] dbr,aa+1 ; data high [1]
|
||||
[5 ] dbr,aa+1 ; io
|
||||
[6a] dbr,aa+1 ; data high [1]
|
||||
[6 ] dbr,aa ; data low
|
||||
*/
|
||||
void bCPU::op_asl_addrb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
regs.p.c = !!(rd.l & 0x80);
|
||||
rd.l <<= 1;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DBR, aa.w, rd.l); //6
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_asl_addrw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a
|
||||
regs.p.c = !!(rd.w & 0x8000);
|
||||
rd.w <<= 1;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a
|
||||
op_write(OPMODE_DBR, aa.w, rd.l); //6
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_asl_addr() { (regs.p.m)?op_asl_addrb():op_asl_addrw(); }
|
||||
|
||||
/************************
|
||||
*** 0x1e: asl addr,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aah,aal+xl ; io
|
||||
[5 ] dbr,aa+x ; data low
|
||||
[5a] dbr,aa+x+1 ; data high [1]
|
||||
[6 ] dbr,aa+x+1 ; io
|
||||
[7a] dbr,aa+x+1 ; data high [1]
|
||||
[7 ] dbr,aa+x ; data low
|
||||
*/
|
||||
void bCPU::op_asl_addrxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_io(); //4
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
|
||||
regs.p.c = !!(rd.l & 0x80);
|
||||
rd.l <<= 1;
|
||||
cpu_io(); //6
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_asl_addrxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_io(); //4
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //5a
|
||||
regs.p.c = !!(rd.w & 0x8000);
|
||||
rd.w <<= 1;
|
||||
cpu_io(); //6
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); //7a
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_asl_addrx() { (regs.p.m)?op_asl_addrxb():op_asl_addrxw(); }
|
||||
|
||||
/********************
|
||||
*** 0x06: asl dp ***
|
||||
********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; data low
|
||||
[3a] 0,d+dp+1 ; data high [1]
|
||||
[4 ] 0,d+dp+1 ; io
|
||||
[5a] 0,d+dp+1 ; data high [1]
|
||||
[5 ] 0,d+dp ; data low
|
||||
*/
|
||||
void bCPU::op_asl_dpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
rd.l = op_read(OPMODE_DP, dp); //3
|
||||
regs.p.c = !!(rd.l & 0x80);
|
||||
rd.l <<= 1;
|
||||
cpu_io(); //4
|
||||
op_write(OPMODE_DP, dp, rd.l); //5
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_asl_dpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
rd.l = op_read(OPMODE_DP, dp); //3
|
||||
rd.h = op_read(OPMODE_DP, dp + 1); //3a
|
||||
regs.p.c = !!(rd.w & 0x8000);
|
||||
rd.w <<= 1;
|
||||
cpu_io(); //4
|
||||
op_write(OPMODE_DP, dp + 1, rd.h); //5a
|
||||
op_write(OPMODE_DP, dp, rd.l); //5
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_asl_dp() { (regs.p.m)?op_asl_dpb():op_asl_dpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x16: asl dp,x ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; data low
|
||||
[4a] 0,d+dp+x+1 ; data high [1]
|
||||
[5 ] 0,d+dp+x+1 ; io
|
||||
[6a] 0,d+dp+x+1 ; data high [1]
|
||||
[6 ] 0,d+dp+x ; data low
|
||||
*/
|
||||
void bCPU::op_asl_dpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
regs.p.c = !!(rd.l & 0x80);
|
||||
rd.l <<= 1;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_asl_dpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
|
||||
regs.p.c = !!(rd.w & 0x8000);
|
||||
rd.w <<= 1;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); //6a
|
||||
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_asl_dpx() { (regs.p.m)?op_asl_dpxb():op_asl_dpxw(); }
|
||||
|
||||
/*****************
|
||||
*** 0x4a: lsr ***
|
||||
*****************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; io
|
||||
*/
|
||||
void bCPU::op_lsrb() {
|
||||
cpu_io(); //2
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_lsrw() {
|
||||
cpu_io(); //2
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_lsr() { (regs.p.m)?op_lsrb():op_lsrw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x4e: lsr addr ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aa ; data low
|
||||
[4a] dbr,aa+1 ; data high [1]
|
||||
[5 ] dbr,aa+1 ; io
|
||||
[6a] dbr,aa+1 ; data high [1]
|
||||
[6 ] dbr,aa ; data low
|
||||
*/
|
||||
void bCPU::op_lsr_addrb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DBR, aa.w, rd.l); //6
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_lsr_addrw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a
|
||||
op_write(OPMODE_DBR, aa.w, rd.l); //6
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_lsr_addr() { (regs.p.m)?op_lsr_addrb():op_lsr_addrw(); }
|
||||
|
||||
/************************
|
||||
*** 0x5e: lsr addr,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aah,aal+xl ; io
|
||||
[5 ] dbr,aa+x ; data low
|
||||
[5a] dbr,aa+x+1 ; data high [1]
|
||||
[6 ] dbr,aa+x+1 ; io
|
||||
[7a] dbr,aa+x+1 ; data high [1]
|
||||
[7 ] dbr,aa+x ; data low
|
||||
*/
|
||||
void bCPU::op_lsr_addrxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_io(); //4
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
cpu_io(); //6
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_lsr_addrxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_io(); //4
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //5a
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
cpu_io(); //6
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); //7a
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_lsr_addrx() { (regs.p.m)?op_lsr_addrxb():op_lsr_addrxw(); }
|
||||
|
||||
/********************
|
||||
*** 0x46: lsr dp ***
|
||||
********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; data low
|
||||
[3a] 0,d+dp+1 ; data high [1]
|
||||
[4 ] 0,d+dp+1 ; io
|
||||
[5a] 0,d+dp+1 ; data high [1]
|
||||
[5 ] 0,d+dp ; data low
|
||||
*/
|
||||
void bCPU::op_lsr_dpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
rd.l = op_read(OPMODE_DP, dp); //3
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
cpu_io(); //4
|
||||
op_write(OPMODE_DP, dp, rd.l); //5
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_lsr_dpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
rd.l = op_read(OPMODE_DP, dp); //3
|
||||
rd.h = op_read(OPMODE_DP, dp + 1); //3a
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
cpu_io(); //4
|
||||
op_write(OPMODE_DP, dp + 1, rd.h); //5a
|
||||
op_write(OPMODE_DP, dp, rd.l); //5
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_lsr_dp() { (regs.p.m)?op_lsr_dpb():op_lsr_dpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x56: lsr dp,x ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; data low
|
||||
[4a] 0,d+dp+x+1 ; data high [1]
|
||||
[5 ] 0,d+dp+x+1 ; io
|
||||
[6a] 0,d+dp+x+1 ; data high [1]
|
||||
[6 ] 0,d+dp+x ; data low
|
||||
*/
|
||||
void bCPU::op_lsr_dpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_lsr_dpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); //6a
|
||||
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_lsr_dpx() { (regs.p.m)?op_lsr_dpxb():op_lsr_dpxw(); }
|
||||
|
||||
/*****************
|
||||
*** 0x2a: rol ***
|
||||
*****************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; io
|
||||
*/
|
||||
void bCPU::op_rolb() {
|
||||
uint8 c = regs.p.c;
|
||||
cpu_io(); //2
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_rolw() {
|
||||
uint16 c = regs.p.c;
|
||||
cpu_io(); //2
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_rol() { (regs.p.m)?op_rolb():op_rolw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x2e: rol addr ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aa ; data low
|
||||
[4a] dbr,aa+1 ; data high [1]
|
||||
[5 ] dbr,aa+1 ; io
|
||||
[6a] dbr,aa+1 ; data high [1]
|
||||
[6 ] dbr,aa ; data low
|
||||
*/
|
||||
void bCPU::op_rol_addrb() {
|
||||
uint8 c = regs.p.c;
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
regs.p.c = !!(rd.l & 0x80);
|
||||
rd.l <<= 1;
|
||||
rd.l |= c;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DBR, aa.w, rd.l); //6
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_rol_addrw() {
|
||||
uint16 c = regs.p.c;
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a
|
||||
regs.p.c = !!(rd.w & 0x8000);
|
||||
rd.w <<= 1;
|
||||
rd.w |= c;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a
|
||||
op_write(OPMODE_DBR, aa.w, rd.l); //6
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_rol_addr() { (regs.p.m)?op_rol_addrb():op_rol_addrw(); }
|
||||
|
||||
/************************
|
||||
*** 0x3e: rol addr,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aah,aal+xl ; io
|
||||
[5 ] dbr,aa+x ; data low
|
||||
[5a] dbr,aa+x+1 ; data high [1]
|
||||
[6 ] dbr,aa+x+1 ; io
|
||||
[7a] dbr,aa+x+1 ; data high [1]
|
||||
[7 ] dbr,aa+x ; data low
|
||||
*/
|
||||
void bCPU::op_rol_addrxb() {
|
||||
uint8 c = regs.p.c;
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_io(); //4
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
|
||||
regs.p.c = !!(rd.l & 0x80);
|
||||
rd.l <<= 1;
|
||||
rd.l |= c;
|
||||
cpu_io(); //6
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_rol_addrxw() {
|
||||
uint16 c = regs.p.c;
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_io(); //4
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //5a
|
||||
regs.p.c = !!(rd.w & 0x8000);
|
||||
rd.w <<= 1;
|
||||
rd.w |= c;
|
||||
cpu_io(); //6
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); //7a
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_rol_addrx() { (regs.p.m)?op_rol_addrxb():op_rol_addrxw(); }
|
||||
|
||||
/********************
|
||||
*** 0x26: rol dp ***
|
||||
********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; data low
|
||||
[3a] 0,d+dp+1 ; data high [1]
|
||||
[4 ] 0,d+dp+1 ; io
|
||||
[5a] 0,d+dp+1 ; data high [1]
|
||||
[5 ] 0,d+dp ; data low
|
||||
*/
|
||||
void bCPU::op_rol_dpb() {
|
||||
uint8 c = regs.p.c;
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
rd.l = op_read(OPMODE_DP, dp); //3
|
||||
regs.p.c = !!(rd.l & 0x80);
|
||||
rd.l <<= 1;
|
||||
rd.l |= c;
|
||||
cpu_io(); //4
|
||||
op_write(OPMODE_DP, dp, rd.l); //5
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_rol_dpw() {
|
||||
uint16 c = regs.p.c;
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
rd.l = op_read(OPMODE_DP, dp); //3
|
||||
rd.h = op_read(OPMODE_DP, dp + 1); //3a
|
||||
regs.p.c = !!(rd.w & 0x8000);
|
||||
rd.w <<= 1;
|
||||
rd.w |= c;
|
||||
cpu_io(); //4
|
||||
op_write(OPMODE_DP, dp + 1, rd.h); //5a
|
||||
op_write(OPMODE_DP, dp, rd.l); //5
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_rol_dp() { (regs.p.m)?op_rol_dpb():op_rol_dpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x36: rol dp,x ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; data low
|
||||
[4a] 0,d+dp+x+1 ; data high [1]
|
||||
[5 ] 0,d+dp+x+1 ; io
|
||||
[6a] 0,d+dp+x+1 ; data high [1]
|
||||
[6 ] 0,d+dp+x ; data low
|
||||
*/
|
||||
void bCPU::op_rol_dpxb() {
|
||||
uint8 c = regs.p.c;
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
regs.p.c = !!(rd.l & 0x80);
|
||||
rd.l <<= 1;
|
||||
rd.l |= c;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_rol_dpxw() {
|
||||
uint16 c = regs.p.c;
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
|
||||
regs.p.c = !!(rd.w & 0x8000);
|
||||
rd.w <<= 1;
|
||||
rd.w |= c;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); //6a
|
||||
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_rol_dpx() { (regs.p.m)?op_rol_dpxb():op_rol_dpxw(); }
|
||||
|
||||
/*****************
|
||||
*** 0x6a: ror ***
|
||||
*****************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; io
|
||||
*/
|
||||
void bCPU::op_rorb() {
|
||||
uint8 c = (regs.p.c)?0x80:0;
|
||||
cpu_io(); //2
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_rorw() {
|
||||
uint16 c = (regs.p.c)?0x8000:0;
|
||||
cpu_io(); //2
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_ror() { (regs.p.m)?op_rorb():op_rorw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x6e: ror addr ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aa ; data low
|
||||
[4a] dbr,aa+1 ; data high [1]
|
||||
[5 ] dbr,aa+1 ; io
|
||||
[6a] dbr,aa+1 ; data high [1]
|
||||
[6 ] dbr,aa ; data low
|
||||
*/
|
||||
void bCPU::op_ror_addrb() {
|
||||
uint8 c = (regs.p.c)?0x80:0;
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
rd.l |= c;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DBR, aa.w, rd.l); //6
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_ror_addrw() {
|
||||
uint16 c = (regs.p.c)?0x8000:0;
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
rd.l = op_read(OPMODE_DBR, aa.w); //4
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
rd.w |= c;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a
|
||||
op_write(OPMODE_DBR, aa.w, rd.l); //6
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_ror_addr() { (regs.p.m)?op_ror_addrb():op_ror_addrw(); }
|
||||
|
||||
/************************
|
||||
*** 0x7e: ror addr,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aah,aal+xl ; io
|
||||
[5 ] dbr,aa+x ; data low
|
||||
[5a] dbr,aa+x+1 ; data high [1]
|
||||
[6 ] dbr,aa+x+1 ; io
|
||||
[7a] dbr,aa+x+1 ; data high [1]
|
||||
[7 ] dbr,aa+x ; data low
|
||||
*/
|
||||
void bCPU::op_ror_addrxb() {
|
||||
uint8 c = (regs.p.c)?0x80:0;
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_io(); //4
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
rd.l |= c;
|
||||
cpu_io(); //6
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_ror_addrxw() {
|
||||
uint16 c = (regs.p.c)?0x8000:0;
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_io(); //4
|
||||
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
|
||||
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //5a
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
rd.w |= c;
|
||||
cpu_io(); //6
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); //7a
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_ror_addrx() { (regs.p.m)?op_ror_addrxb():op_ror_addrxw(); }
|
||||
|
||||
/********************
|
||||
*** 0x66: ror dp ***
|
||||
********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; data low
|
||||
[3a] 0,d+dp+1 ; data high [1]
|
||||
[4 ] 0,d+dp+1 ; io
|
||||
[5a] 0,d+dp+1 ; data high [1]
|
||||
[5 ] 0,d+dp ; data low
|
||||
*/
|
||||
void bCPU::op_ror_dpb() {
|
||||
uint8 c = (regs.p.c)?0x80:0;
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
rd.l = op_read(OPMODE_DP, dp); //3
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
rd.l |= c;
|
||||
cpu_io(); //4
|
||||
op_write(OPMODE_DP, dp, rd.l); //5
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_ror_dpw() {
|
||||
uint16 c = (regs.p.c)?0x8000:0;
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
rd.l = op_read(OPMODE_DP, dp); //3
|
||||
rd.h = op_read(OPMODE_DP, dp + 1); //3a
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
rd.w |= c;
|
||||
cpu_io(); //4
|
||||
op_write(OPMODE_DP, dp + 1, rd.h); //5a
|
||||
op_write(OPMODE_DP, dp, rd.l); //5
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_ror_dp() { (regs.p.m)?op_ror_dpb():op_ror_dpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x76: ror dp,x ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; data low
|
||||
[4a] 0,d+dp+x+1 ; data high [1]
|
||||
[5 ] 0,d+dp+x+1 ; io
|
||||
[6a] 0,d+dp+x+1 ; data high [1]
|
||||
[6 ] 0,d+dp+x ; data low
|
||||
*/
|
||||
void bCPU::op_ror_dpxb() {
|
||||
uint8 c = (regs.p.c)?0x80:0;
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
rd.l |= c;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_ror_dpxw() {
|
||||
uint16 c = (regs.p.c)?0x8000:0;
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
rd.w |= c;
|
||||
cpu_io(); //5
|
||||
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); //6a
|
||||
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_ror_dpx() { (regs.p.m)?op_ror_dpxb():op_ror_dpxw(); }
|
||||
@@ -1,415 +0,0 @@
|
||||
/**********************
|
||||
*** 0x8d: sta addr ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] dbr,aa ; data low
|
||||
[4a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sta_addrb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
op_write(OPMODE_DBR, aa.w, regs.a.l); //4
|
||||
}
|
||||
|
||||
void bCPU::op_sta_addrw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
op_write(OPMODE_DBR, aa.w, regs.a.l); //4
|
||||
op_write(OPMODE_DBR, aa.w + 1, regs.a.h); //4a
|
||||
}
|
||||
|
||||
void bCPU::op_sta_addr() { (regs.p.m)?op_sta_addrb():op_sta_addrw(); }
|
||||
|
||||
/************************
|
||||
*** 0x9d: sta addr,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; operand
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[3a] dbr,aah,aal+xl ; io [4]
|
||||
[4 ] dbr,aa+x ; data low
|
||||
[4a] dbr,aa+x+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sta_addrxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.x.w); //3a
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w, regs.a.l); //4
|
||||
}
|
||||
|
||||
void bCPU::op_sta_addrxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.x.w); //3a
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w, regs.a.l); //4
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, regs.a.h); //4a
|
||||
}
|
||||
|
||||
void bCPU::op_sta_addrx() { (regs.p.m)?op_sta_addrxb():op_sta_addrxw(); }
|
||||
|
||||
/********************
|
||||
*** 0x85: sta dp ***
|
||||
********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; operand
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; data low
|
||||
[3a] 0,d+dp+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sta_dpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
op_write(OPMODE_DP, dp, regs.a.l); //3
|
||||
}
|
||||
|
||||
void bCPU::op_sta_dpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
op_write(OPMODE_DP, dp, regs.a.l); //3
|
||||
op_write(OPMODE_DP, dp + 1, regs.a.h); //3a
|
||||
}
|
||||
|
||||
void bCPU::op_sta_dp() { (regs.p.m)?op_sta_dpb():op_sta_dpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x92: sta (dp) ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] dbr,aa ; data low
|
||||
[5a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sta_idpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
op_write(OPMODE_DBR, aa.w, regs.a.l); //5
|
||||
}
|
||||
|
||||
void bCPU::op_sta_idpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
op_write(OPMODE_DBR, aa.w, regs.a.l); //5
|
||||
op_write(OPMODE_DBR, aa.w + 1, regs.a.h); //5
|
||||
}
|
||||
|
||||
void bCPU::op_sta_idp() { (regs.p.m)?op_sta_idpb():op_sta_idpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x87: sta [dp] ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] 0,d+dp+2 ; aab
|
||||
[6 ] aab,aa ; data low
|
||||
[6a] aab,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sta_ildpb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
op_write(OPMODE_LONG, aa.d, regs.a.l); //6
|
||||
}
|
||||
|
||||
void bCPU::op_sta_ildpw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
op_write(OPMODE_LONG, aa.d, regs.a.l); //6
|
||||
op_write(OPMODE_LONG, aa.d + 1, regs.a.h); //6a
|
||||
}
|
||||
|
||||
void bCPU::op_sta_ildp() { (regs.p.m)?op_sta_ildpb():op_sta_ildpw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x8f: sta long ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] pbr,pc+3 ; aab
|
||||
[5 ] aab,aa ; data low
|
||||
[5a] aab,aa+1 ; data high
|
||||
*/
|
||||
void bCPU::op_sta_longb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
op_write(OPMODE_LONG, aa.d, regs.a.l); //5
|
||||
}
|
||||
|
||||
void bCPU::op_sta_longw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
op_write(OPMODE_LONG, aa.d, regs.a.l); //5
|
||||
op_write(OPMODE_LONG, aa.d + 1, regs.a.h); //5a
|
||||
}
|
||||
|
||||
void bCPU::op_sta_long() { (regs.p.m)?op_sta_longb():op_sta_longw(); }
|
||||
|
||||
/************************
|
||||
*** 0x9f: sta long,x ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[4 ] pbr,pc+3 ; aab
|
||||
[5 ] aab,aa+x ; data low
|
||||
[5a] aab,aa+x+1 ; data high
|
||||
*/
|
||||
void bCPU::op_sta_longxb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
op_write(OPMODE_LONG, aa.d + regs.x.w, regs.a.l); //5
|
||||
}
|
||||
|
||||
void bCPU::op_sta_longxw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
aa.b = op_read(); //4
|
||||
op_write(OPMODE_LONG, aa.d + regs.x.w, regs.a.l); //5
|
||||
op_write(OPMODE_LONG, aa.d + regs.x.w + 1, regs.a.h); //5a
|
||||
}
|
||||
|
||||
void bCPU::op_sta_longx() { (regs.p.m)?op_sta_longxb():op_sta_longxw(); }
|
||||
|
||||
/************************
|
||||
*** 0x99: sta addr,y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; operand
|
||||
[2 ] pbr,pc+1 ; aal
|
||||
[3 ] pbr,pc+2 ; aah
|
||||
[3a] dbr,aah,aal+yl ; io [4]
|
||||
[4 ] dbr,aa+y ; data low
|
||||
[4a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sta_addryb() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //3a
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //4
|
||||
}
|
||||
|
||||
void bCPU::op_sta_addryw() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //3a
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //4
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h); //4a
|
||||
}
|
||||
|
||||
void bCPU::op_sta_addry() { (regs.p.m)?op_sta_addryb():op_sta_addryw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x95: sta dp,x ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; data low
|
||||
[4a] 0,d+dp+x+1 ; data high
|
||||
*/
|
||||
void bCPU::op_sta_dpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
op_write(OPMODE_DP, dp + regs.x.w, regs.a.l); //4
|
||||
}
|
||||
|
||||
void bCPU::op_sta_dpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
op_write(OPMODE_DP, dp + regs.x.w, regs.a.l); //4
|
||||
op_write(OPMODE_DP, dp + regs.x.w + 1, regs.a.h); //4a
|
||||
}
|
||||
|
||||
void bCPU::op_sta_dpx() { (regs.p.m)?op_sta_dpxb():op_sta_dpxw(); }
|
||||
|
||||
/************************
|
||||
*** 0x81: sta (dp,x) ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,d+dp+x ; aal
|
||||
[5 ] 0,d+dp+x+1 ; aah
|
||||
[6 ] dbr,aa ; data low
|
||||
[6a] dbr,aa+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sta_idpxb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
|
||||
op_write(OPMODE_DBR, aa.w, regs.a.l); //6
|
||||
}
|
||||
|
||||
void bCPU::op_sta_idpxw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
|
||||
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
|
||||
op_write(OPMODE_DBR, aa.w, regs.a.l); //6
|
||||
op_write(OPMODE_DBR, aa.w + 1, regs.a.h); //6a
|
||||
}
|
||||
|
||||
void bCPU::op_sta_idpx() { (regs.p.m)?op_sta_idpxb():op_sta_idpxw(); }
|
||||
|
||||
/************************
|
||||
*** 0x91: sta (dp),y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[4a] dbr,aah,aal+yl ; io [4]
|
||||
[5 ] dbr,aa+y ; data low
|
||||
[5a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sta_idpyb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //4a
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //5
|
||||
}
|
||||
|
||||
void bCPU::op_sta_idpyw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
cpu_c4(aa.w, aa.w + regs.y.w); //4a
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //5
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h); //5a
|
||||
}
|
||||
|
||||
void bCPU::op_sta_idpy() { (regs.p.m)?op_sta_idpyb():op_sta_idpyw(); }
|
||||
|
||||
/************************
|
||||
*** 0x97: sta [dp],y ***
|
||||
************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io [2]
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] 0,d+dp+2 ; aab
|
||||
[6 ] aab,aa+y ; data low
|
||||
[6a] aab,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sta_ildpyb() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
op_write(OPMODE_LONG, aa.d + regs.y.w, regs.a.l); //6
|
||||
}
|
||||
|
||||
void bCPU::op_sta_ildpyw() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
aa.b = op_read(OPMODE_DP, dp + 2); //5
|
||||
op_write(OPMODE_LONG, aa.d + regs.y.w, regs.a.l); //6
|
||||
op_write(OPMODE_LONG, aa.d + regs.y.w + 1, regs.a.h); //6a
|
||||
}
|
||||
|
||||
void bCPU::op_sta_ildpy() { (regs.p.m)?op_sta_ildpyb():op_sta_ildpyw(); }
|
||||
|
||||
/**********************
|
||||
*** 0x83: sta sr,s ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; sp
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+sp ; data low
|
||||
[4a] 0,s+sp+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sta_srb() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
op_write(OPMODE_SP, sp, regs.a.l); //4
|
||||
}
|
||||
|
||||
void bCPU::op_sta_srw() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
op_write(OPMODE_SP, sp, regs.a.l); //4
|
||||
op_write(OPMODE_SP, sp + 1, regs.a.h); //4a
|
||||
}
|
||||
|
||||
void bCPU::op_sta_sr() { (regs.p.m)?op_sta_srb():op_sta_srw(); }
|
||||
|
||||
/**************************
|
||||
*** 0x93: sta (sr,s),y ***
|
||||
**************************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; sp
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+sp ; aal
|
||||
[5 ] 0,s+sp+1 ; aah
|
||||
[6 ] 0,s+sp+1 ; io
|
||||
[7 ] dbr,aa+y ; data low
|
||||
[7a] dbr,aa+y+1 ; data high [1]
|
||||
*/
|
||||
void bCPU::op_sta_isryb() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_SP, sp); //4
|
||||
aa.h = op_read(OPMODE_SP, sp + 1); //5
|
||||
cpu_io(); //6
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //7
|
||||
}
|
||||
|
||||
void bCPU::op_sta_isryw() {
|
||||
sp = op_read(); //2
|
||||
cpu_io(); //3
|
||||
aa.l = op_read(OPMODE_SP, sp); //4
|
||||
aa.h = op_read(OPMODE_SP, sp + 1); //5
|
||||
cpu_io(); //6
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //7
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h); //7a
|
||||
}
|
||||
|
||||
void bCPU::op_sta_isry() { (regs.p.m)?op_sta_isryb():op_sta_isryw(); }
|
||||
@@ -1,320 +0,0 @@
|
||||
/*****************
|
||||
*** 0x48: pha ***
|
||||
*****************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; io
|
||||
[3a] 0,s ; reg high [1]
|
||||
[3 ] 0,s-1 ; reg low
|
||||
*/
|
||||
void bCPU::op_phab() {
|
||||
cpu_io(); //2
|
||||
stack_write(regs.a.l); //3
|
||||
}
|
||||
|
||||
void bCPU::op_phaw() {
|
||||
cpu_io(); //2
|
||||
stack_write(regs.a.h); //3a
|
||||
stack_write(regs.a.l); //3
|
||||
}
|
||||
|
||||
void bCPU::op_pha() { (regs.p.m)?op_phab():op_phaw(); }
|
||||
|
||||
/*****************
|
||||
*** 0x8b: phb ***
|
||||
*****************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; io
|
||||
[3 ] 0,s-1 ; dbr
|
||||
*/
|
||||
void bCPU::op_phb() {
|
||||
cpu_io(); //2
|
||||
stack_write(regs.db); //3
|
||||
}
|
||||
|
||||
/*****************
|
||||
*** 0x0b: phd ***
|
||||
*****************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; io
|
||||
[3a] 0,s ; reg high
|
||||
[3 ] 0,s-1 ; reg low
|
||||
*/
|
||||
void bCPU::op_phd() {
|
||||
cpu_io(); //2
|
||||
stack_write(regs.d.h); //3a
|
||||
stack_write(regs.d.l); //3
|
||||
}
|
||||
|
||||
/*****************
|
||||
*** 0x4b: phk ***
|
||||
*****************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; io
|
||||
[3 ] 0,s-1 ; pcb
|
||||
*/
|
||||
void bCPU::op_phk() {
|
||||
cpu_io(); //2
|
||||
stack_write(regs.pc.b); //3
|
||||
}
|
||||
|
||||
/*****************
|
||||
*** 0x08: php ***
|
||||
*****************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; io
|
||||
[3 ] 0,s-1 ; reg low
|
||||
*/
|
||||
void bCPU::op_php() {
|
||||
cpu_io(); //2
|
||||
stack_write(regs.p); //3
|
||||
}
|
||||
|
||||
/*****************
|
||||
*** 0xda: phx ***
|
||||
*****************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; io
|
||||
[3a] 0,s ; reg high [1]
|
||||
[3 ] 0,s-1 ; reg low
|
||||
*/
|
||||
void bCPU::op_phxb() {
|
||||
cpu_io(); //2
|
||||
stack_write(regs.x.l); //3
|
||||
}
|
||||
|
||||
void bCPU::op_phxw() {
|
||||
cpu_io(); //2
|
||||
stack_write(regs.x.h); //3a
|
||||
stack_write(regs.x.l); //3
|
||||
}
|
||||
|
||||
void bCPU::op_phx() { (regs.p.x)?op_phxb():op_phxw(); }
|
||||
|
||||
/*****************
|
||||
*** 0x5a: phy ***
|
||||
*****************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; io
|
||||
[3a] 0,s ; reg high [1]
|
||||
[3 ] 0,s-1 ; reg low
|
||||
*/
|
||||
void bCPU::op_phyb() {
|
||||
cpu_io(); //2
|
||||
stack_write(regs.y.l); //3
|
||||
}
|
||||
|
||||
void bCPU::op_phyw() {
|
||||
cpu_io(); //2
|
||||
stack_write(regs.y.h); //3a
|
||||
stack_write(regs.y.l); //3
|
||||
}
|
||||
|
||||
void bCPU::op_phy() { (regs.p.x)?op_phyb():op_phyw(); }
|
||||
|
||||
/*****************
|
||||
*** 0x68: pla ***
|
||||
*****************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; io
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+1 ; reg low
|
||||
[4a] 0,s+2 ; reg high [1]
|
||||
*/
|
||||
void bCPU::op_plab() {
|
||||
cpu_io(); //2
|
||||
cpu_io(); //3
|
||||
regs.a.l = stack_read(); //4
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_plaw() {
|
||||
cpu_io(); //2
|
||||
cpu_io(); //3
|
||||
regs.a.l = stack_read(); //4
|
||||
regs.a.h = stack_read(); //4a
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_pla() { (regs.p.m)?op_plab():op_plaw(); }
|
||||
|
||||
/*****************
|
||||
*** 0xab: plb ***
|
||||
*****************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; io
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+1 ; reg low
|
||||
*/
|
||||
void bCPU::op_plb() {
|
||||
cpu_io(); //2
|
||||
cpu_io(); //3
|
||||
regs.db = stack_read(); //4
|
||||
regs.p.n = !!(regs.db & 0x80);
|
||||
regs.p.z = (regs.db == 0);
|
||||
}
|
||||
|
||||
/*****************
|
||||
*** 0x2b: pld ***
|
||||
*****************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; io
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+1 ; reg low
|
||||
[4a] 0,s+2 ; reg high
|
||||
*/
|
||||
void bCPU::op_pld() {
|
||||
cpu_io(); //2
|
||||
cpu_io(); //3
|
||||
regs.d.l = stack_read(); //4
|
||||
regs.d.h = stack_read(); //4a
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
}
|
||||
|
||||
/*****************
|
||||
*** 0x28: plp ***
|
||||
*****************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; io
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+1 ; reg low
|
||||
*/
|
||||
void bCPU::op_plp() {
|
||||
cpu_io(); //2
|
||||
cpu_io(); //3
|
||||
regs.p = stack_read(); //4
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************
|
||||
*** 0xfa: plx ***
|
||||
*****************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; io
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+1 ; reg low
|
||||
[4a] 0,s+2 ; reg high [1]
|
||||
*/
|
||||
void bCPU::op_plxb() {
|
||||
cpu_io(); //2
|
||||
cpu_io(); //3
|
||||
regs.x.l = stack_read(); //4
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_plxw() {
|
||||
cpu_io(); //2
|
||||
cpu_io(); //3
|
||||
regs.x.l = stack_read(); //4
|
||||
regs.x.h = stack_read(); //4a
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_plx() { (regs.p.x)?op_plxb():op_plxw(); }
|
||||
|
||||
/*****************
|
||||
*** 0x7a: ply ***
|
||||
*****************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; io
|
||||
[3 ] pbr,pc+1 ; io
|
||||
[4 ] 0,s+1 ; reg low
|
||||
[4a] 0,s+2 ; reg high [1]
|
||||
*/
|
||||
void bCPU::op_plyb() {
|
||||
cpu_io(); //2
|
||||
cpu_io(); //3
|
||||
regs.y.l = stack_read(); //4
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_plyw() {
|
||||
cpu_io(); //2
|
||||
cpu_io(); //3
|
||||
regs.y.l = stack_read(); //4
|
||||
regs.y.h = stack_read(); //4a
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
|
||||
void bCPU::op_ply() { (regs.p.x)?op_plyb():op_plyw(); }
|
||||
|
||||
/**********************
|
||||
*** 0xf4: pea addr ***
|
||||
**********************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; aal
|
||||
[3] pbr,pc+2 ; aah
|
||||
[4] 0,s ; aah
|
||||
[5] 0,s-1 ; aal
|
||||
*/
|
||||
void bCPU::op_pea() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
stack_write(aa.h); //4
|
||||
stack_write(aa.l); //5
|
||||
}
|
||||
|
||||
/**********************
|
||||
*** 0xd4: pei (dp) ***
|
||||
**********************
|
||||
cycles:
|
||||
[1 ] pbr,pc ; opcode
|
||||
[2 ] pbr,pc+1 ; dp
|
||||
[2a] pbr,pc+1 ; io
|
||||
[3 ] 0,d+dp ; aal
|
||||
[4 ] 0,d+dp+1 ; aah
|
||||
[5 ] 0,s ; aah
|
||||
[6 ] 0,s-1 ; aal
|
||||
*/
|
||||
void bCPU::op_pei() {
|
||||
dp = op_read(); //2
|
||||
cpu_c2(); //2a
|
||||
aa.l = op_read(OPMODE_DP, dp); //3
|
||||
aa.h = op_read(OPMODE_DP, dp + 1); //4
|
||||
stack_write(aa.h); //5
|
||||
stack_write(aa.l); //6
|
||||
}
|
||||
|
||||
/**********************
|
||||
*** 0x62: per addr ***
|
||||
**********************
|
||||
cycles:
|
||||
[1] pbr,pc ; opcode
|
||||
[2] pbr,pc+1 ; offset low
|
||||
[3] pbr,pc+2 ; offset high
|
||||
[4] pbr,pc+2 ; io
|
||||
[5] 0,s ; pch+offset
|
||||
[6] 0,s-1 ; pcl+offset
|
||||
*/
|
||||
void bCPU::op_per() {
|
||||
aa.l = op_read(); //2
|
||||
aa.h = op_read(); //3
|
||||
cpu_io(); //4
|
||||
rd.w = regs.pc.d + (int16)aa.w;
|
||||
stack_write(rd.h); //5
|
||||
stack_write(rd.l); //6
|
||||
}
|
||||
+7
-2
@@ -1,6 +1,11 @@
|
||||
#include "../base.h"
|
||||
#include "../base.h"
|
||||
#define CPU_CPP
|
||||
|
||||
#include "dcpu.cpp"
|
||||
|
||||
CPU::CPU() {
|
||||
mmio = &mmio_unmapped;
|
||||
cpu_version = 2;
|
||||
}
|
||||
|
||||
CPU::~CPU() {
|
||||
}
|
||||
+52
-14
@@ -1,23 +1,56 @@
|
||||
#include "cpuregs.h"
|
||||
|
||||
class CPU {
|
||||
class CPU : public MMIO {
|
||||
public:
|
||||
MMIO *mmio;
|
||||
CPURegs regs;
|
||||
virtual void enter() = 0;
|
||||
|
||||
//CPU version number
|
||||
//* 1 and 2 are known
|
||||
//* reported by $4210
|
||||
//* affects DRAM refresh behavior
|
||||
uint8 cpu_version;
|
||||
|
||||
//timing
|
||||
virtual uint16 vcounter() = 0;
|
||||
virtual uint16 hcounter() = 0;
|
||||
virtual uint16 hdot() = 0;
|
||||
|
||||
virtual uint8 pio() = 0;
|
||||
virtual bool joylatch() = 0;
|
||||
virtual uint8 port_read(uint8 port) = 0;
|
||||
virtual void port_write(uint8 port, uint8 value) = 0;
|
||||
|
||||
CPURegs regs;
|
||||
enum {
|
||||
FLAG_N = 0x80, FLAG_V = 0x40,
|
||||
FLAG_M = 0x20, FLAG_X = 0x10,
|
||||
FLAG_D = 0x08, FLAG_I = 0x04,
|
||||
FLAG_Z = 0x02, FLAG_C = 0x01
|
||||
};
|
||||
virtual uint8 pio_status() = 0;
|
||||
virtual void run() = 0;
|
||||
virtual void scanline() = 0;
|
||||
virtual void frame() = 0;
|
||||
virtual void power() = 0;
|
||||
virtual void reset() = 0;
|
||||
|
||||
virtual void scanline() = 0;
|
||||
virtual void frame() = 0;
|
||||
virtual void power() = 0;
|
||||
virtual void reset() = 0;
|
||||
|
||||
//opcode disassembler
|
||||
/*****
|
||||
* in opcode-based CPU emulators, the main emulation routine
|
||||
* will only be able to call the disassemble_opcode() function
|
||||
* on clean opcode edges. but with cycle-based CPU emulators,
|
||||
* the CPU may be in the middle of executing an opcode when the
|
||||
* emulator (e.g. debugger) wants to disassemble an opcode. this
|
||||
* would mean that important registers may not reflect what they
|
||||
* did at the start of the opcode (especially regs.pc), so in
|
||||
* cycle-based emulators, this function should be overridden to
|
||||
* reflect whether or not an opcode has only been partially
|
||||
* executed. if not, the debugger should abort attempts to skip,
|
||||
* disable, or disassemble the current opcode.
|
||||
*****/
|
||||
virtual bool in_opcode() { return false; }
|
||||
|
||||
/*****
|
||||
* opcode disassembler
|
||||
*****/
|
||||
enum {
|
||||
OPTYPE_DP = 0, //dp
|
||||
OPTYPE_DPX, //dp,x
|
||||
@@ -37,13 +70,18 @@ CPURegs regs;
|
||||
OPTYPE_SR, //sr,s
|
||||
OPTYPE_ISRY, //(sr,s),y
|
||||
OPTYPE_ADDR_PC, //pbr:addr
|
||||
OPTYPE_IADDR_PC //pbr:(addr)
|
||||
OPTYPE_IADDR_PC, //pbr:(addr)
|
||||
OPTYPE_RELB, //relb
|
||||
OPTYPE_RELW, //relw
|
||||
};
|
||||
|
||||
void disassemble_opcode(char *output);
|
||||
uint32 resolve_offset(uint8 offset_type, uint32 addr);
|
||||
uint8 dreadb(uint32 addr);
|
||||
uint16 dreadw(uint32 addr);
|
||||
uint32 dreadl(uint32 addr);
|
||||
uint32 decode(uint8 offset_type, uint32 addr);
|
||||
uint8 opcode_length();
|
||||
uint16 __relb(int8 offset);
|
||||
uint16 __relw(int16 offset);
|
||||
|
||||
CPU();
|
||||
virtual ~CPU();
|
||||
};
|
||||
+67
-63
@@ -1,84 +1,88 @@
|
||||
template<int mask>
|
||||
struct CPUFlag {
|
||||
uint8 &data;
|
||||
|
||||
inline operator bool() const { return data & mask; }
|
||||
inline CPUFlag& operator=(bool i) { data = (data & ~mask) | (-i & mask); return *this; }
|
||||
|
||||
CPUFlag(uint8 &data_) : data(data_) {}
|
||||
};
|
||||
|
||||
class CPURegFlags {
|
||||
private:
|
||||
template <uint8 B> class bit {
|
||||
public:
|
||||
uint8 b;
|
||||
inline operator bool() { return (b & B); }
|
||||
inline operator = (bool i) { (i) ? b |= B : b &= ~B; return (b & B); }
|
||||
inline operator & (bool i) { if(i)b &= ~B; return (b & B); }
|
||||
inline operator | (bool i) { if(i)b |= B; return (b & B); }
|
||||
inline operator ^ (bool i) { if(i)b ^= B; return (b & B); }
|
||||
};
|
||||
public:
|
||||
union {
|
||||
uint8 b;
|
||||
bit<0x80> n;
|
||||
bit<0x40> v;
|
||||
bit<0x20> m;
|
||||
bit<0x10> x;
|
||||
bit<0x08> d;
|
||||
bit<0x04> i;
|
||||
bit<0x02> z;
|
||||
bit<0x01> c;
|
||||
};
|
||||
public:
|
||||
uint8 data;
|
||||
CPUFlag<0x80> n;
|
||||
CPUFlag<0x40> v;
|
||||
CPUFlag<0x20> m;
|
||||
CPUFlag<0x10> x;
|
||||
CPUFlag<0x08> d;
|
||||
CPUFlag<0x04> i;
|
||||
CPUFlag<0x02> z;
|
||||
CPUFlag<0x01> c;
|
||||
|
||||
CPURegFlags() { 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; }
|
||||
inline operator unsigned() const { return data; }
|
||||
inline unsigned operator = (unsigned i) { data = i; return data; }
|
||||
inline unsigned operator |= (unsigned i) { data |= i; return data; }
|
||||
inline unsigned operator ^= (unsigned i) { data ^= i; return data; }
|
||||
inline unsigned operator &= (unsigned i) { data &= i; return data; }
|
||||
|
||||
CPURegFlags() : data(0), n(data), v(data), m(data), x(data), d(data), i(data), z(data), c(data) {}
|
||||
};
|
||||
|
||||
class CPUReg16 {
|
||||
public:
|
||||
union {
|
||||
uint16 w;
|
||||
struct { uint8 l, h; };
|
||||
uint16 w;
|
||||
struct { uint8 order_lsb2(l, h); };
|
||||
};
|
||||
|
||||
CPUReg16() { w = 0; }
|
||||
inline operator uint16() { return w; }
|
||||
inline unsigned operator = (uint16 i) { w = i; return w; }
|
||||
inline unsigned operator += (uint16 i) { w += i; return w; }
|
||||
inline unsigned operator -= (uint16 i) { w -= i; return w; }
|
||||
inline unsigned operator *= (uint16 i) { w *= i; return w; }
|
||||
inline unsigned operator /= (uint16 i) { w /= i; return w; }
|
||||
inline unsigned operator &= (uint16 i) { w &= i; return w; }
|
||||
inline unsigned operator |= (uint16 i) { w |= i; return w; }
|
||||
inline unsigned operator ^= (uint16 i) { w ^= i; return w; }
|
||||
inline unsigned operator <<= (uint16 i) { w <<= i; return w; }
|
||||
inline unsigned operator >>= (uint16 i) { w >>= i; return w; }
|
||||
inline operator unsigned() const { return w; }
|
||||
inline unsigned operator = (unsigned i) { w = i; return w; }
|
||||
inline unsigned operator |= (unsigned i) { w |= i; return w; }
|
||||
inline unsigned operator ^= (unsigned i) { w ^= i; return w; }
|
||||
inline unsigned operator &= (unsigned i) { w &= i; return w; }
|
||||
inline unsigned operator <<= (unsigned i) { w <<= i; return w; }
|
||||
inline unsigned operator >>= (unsigned i) { w >>= i; return w; }
|
||||
inline unsigned operator += (unsigned i) { w += i; return w; }
|
||||
inline unsigned operator -= (unsigned i) { w -= i; return w; }
|
||||
inline unsigned operator *= (unsigned i) { w *= i; return w; }
|
||||
inline unsigned operator /= (unsigned i) { w /= i; return w; }
|
||||
inline unsigned operator %= (unsigned i) { w %= i; return w; }
|
||||
|
||||
CPUReg16() : w(0) {}
|
||||
};
|
||||
|
||||
class CPUReg24 {
|
||||
public:
|
||||
union {
|
||||
uint16 w;
|
||||
uint32 d;
|
||||
struct { uint8 l, h, b; };
|
||||
uint32 d;
|
||||
struct { uint16 order_lsb2(w, wh); };
|
||||
struct { uint8 order_lsb4(l, h, b, bh); };
|
||||
};
|
||||
|
||||
CPUReg24() { d = 0; }
|
||||
inline operator uint32() { return (d & 0xffffff); }
|
||||
inline unsigned operator = (uint16 i) { d = i; return d; }
|
||||
inline unsigned operator += (uint16 i) { d += i; return d; }
|
||||
inline unsigned operator -= (uint16 i) { d -= i; return d; }
|
||||
inline unsigned operator *= (uint16 i) { d *= i; return d; }
|
||||
inline unsigned operator /= (uint16 i) { d /= i; return d; }
|
||||
inline unsigned operator &= (uint16 i) { d &= i; return d; }
|
||||
inline unsigned operator |= (uint16 i) { d |= i; return d; }
|
||||
inline unsigned operator ^= (uint16 i) { d ^= i; return d; }
|
||||
inline unsigned operator <<= (uint16 i) { d <<= i; return d; }
|
||||
inline unsigned operator >>= (uint16 i) { d >>= i; return d; }
|
||||
inline operator unsigned() const { return d; }
|
||||
inline unsigned operator = (unsigned i) { d = uclip<24>(i); return d; }
|
||||
inline unsigned operator |= (unsigned i) { d = uclip<24>(d | i); return d; }
|
||||
inline unsigned operator ^= (unsigned i) { d = uclip<24>(d ^ i); return d; }
|
||||
inline unsigned operator &= (unsigned i) { d = uclip<24>(d & i); return d; }
|
||||
inline unsigned operator <<= (unsigned i) { d = uclip<24>(d << i); return d; }
|
||||
inline unsigned operator >>= (unsigned i) { d = uclip<24>(d >> i); return d; }
|
||||
inline unsigned operator += (unsigned i) { d = uclip<24>(d + i); return d; }
|
||||
inline unsigned operator -= (unsigned i) { d = uclip<24>(d - i); return d; }
|
||||
inline unsigned operator *= (unsigned i) { d = uclip<24>(d * i); return d; }
|
||||
inline unsigned operator /= (unsigned i) { d = uclip<24>(d / i); return d; }
|
||||
inline unsigned operator %= (unsigned i) { d = uclip<24>(d % i); return d; }
|
||||
|
||||
CPUReg24() : d(0) {}
|
||||
};
|
||||
|
||||
class CPURegs {
|
||||
public:
|
||||
CPUReg24 pc;
|
||||
CPUReg16 a, x, y, s, d;
|
||||
CPURegFlags p;
|
||||
uint8 db;
|
||||
bool e;
|
||||
CPURegs() { db = 0; e = false; }
|
||||
CPUReg24 pc;
|
||||
CPUReg16 a, x, y, s, d;
|
||||
CPURegFlags p;
|
||||
uint8 db;
|
||||
uint8 mdr;
|
||||
bool e;
|
||||
CPURegs() : db(0), mdr(0), e(false) {}
|
||||
};
|
||||
+372
-332
@@ -1,16 +1,30 @@
|
||||
uint16 CPU::__relb(int8 offset) {
|
||||
uint32 addr;
|
||||
addr = (regs.pc.d & 0xff0000) | ((regs.pc.d + 2) & 0xffff);
|
||||
return addr + offset;
|
||||
#ifdef CPU_CPP
|
||||
|
||||
uint8 CPU::dreadb(uint32 addr) {
|
||||
if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) {
|
||||
//$[00-3f|80-bf]:[2000-5fff]
|
||||
//do not read MMIO registers within debugger
|
||||
return 0x00;
|
||||
}
|
||||
return bus.read(addr);
|
||||
}
|
||||
|
||||
uint16 CPU::__relw(int16 offset) {
|
||||
uint32 addr;
|
||||
addr = (regs.pc.d & 0xff0000) | ((regs.pc.d + 3) & 0xffff);
|
||||
return addr + offset;
|
||||
uint16 CPU::dreadw(uint32 addr) {
|
||||
uint16 r;
|
||||
r = dreadb((addr + 0) & 0xffffff) << 0;
|
||||
r |= dreadb((addr + 1) & 0xffffff) << 8;
|
||||
return r;
|
||||
}
|
||||
|
||||
uint32 CPU::resolve_offset(uint8 offset_type, uint32 addr) {
|
||||
uint32 CPU::dreadl(uint32 addr) {
|
||||
uint32 r;
|
||||
r = dreadb((addr + 0) & 0xffffff) << 0;
|
||||
r |= dreadb((addr + 1) & 0xffffff) << 8;
|
||||
r |= dreadb((addr + 2) & 0xffffff) << 16;
|
||||
return r;
|
||||
}
|
||||
|
||||
uint32 CPU::decode(uint8 offset_type, uint32 addr) {
|
||||
uint32 r = 0;
|
||||
switch(offset_type) {
|
||||
case OPTYPE_DP:
|
||||
@@ -24,23 +38,23 @@ uint32 r = 0;
|
||||
break;
|
||||
case OPTYPE_IDP:
|
||||
addr = (regs.d + (addr & 0xffff)) & 0xffff;
|
||||
r = (regs.db << 16) + mem_bus->read_word(addr);
|
||||
r = (regs.db << 16) + dreadw(addr);
|
||||
break;
|
||||
case OPTYPE_IDPX:
|
||||
addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff;
|
||||
r = (regs.db << 16) + mem_bus->read_word(addr);
|
||||
r = (regs.db << 16) + dreadw(addr);
|
||||
break;
|
||||
case OPTYPE_IDPY:
|
||||
addr = (regs.d + (addr & 0xffff)) & 0xffff;
|
||||
r = (regs.db << 16) + mem_bus->read_word(addr) + regs.y;
|
||||
r = (regs.db << 16) + dreadw(addr) + regs.y;
|
||||
break;
|
||||
case OPTYPE_ILDP:
|
||||
addr = (regs.d + (addr & 0xffff)) & 0xffff;
|
||||
r = mem_bus->read_long(addr);
|
||||
r = dreadl(addr);
|
||||
break;
|
||||
case OPTYPE_ILDPY:
|
||||
addr = (regs.d + (addr & 0xffff)) & 0xffff;
|
||||
r = mem_bus->read_long(addr) + regs.y;
|
||||
r = dreadl(addr) + regs.y;
|
||||
break;
|
||||
case OPTYPE_ADDR:
|
||||
r = (regs.db << 16) + (addr & 0xffff);
|
||||
@@ -61,356 +75,376 @@ uint32 r = 0;
|
||||
r = (regs.pc.b << 16) + ((addr + regs.x) & 0xffff);
|
||||
break;
|
||||
case OPTYPE_ILADDR:
|
||||
r = addr & 0xffffff;
|
||||
r = addr;
|
||||
break;
|
||||
case OPTYPE_LONG:
|
||||
r = addr & 0xffffff;
|
||||
r = addr;
|
||||
break;
|
||||
case OPTYPE_LONGX:
|
||||
r = (addr + regs.x) & 0xffffff;
|
||||
r = (addr + regs.x);
|
||||
break;
|
||||
case OPTYPE_SR:
|
||||
r = (regs.s + (addr & 0xff)) & 0xffff;
|
||||
break;
|
||||
case OPTYPE_ISRY:
|
||||
addr = (regs.s + (addr & 0xff)) & 0xffff;
|
||||
r = (regs.db << 16) + mem_bus->read_word(addr) + regs.y;
|
||||
r = (regs.db << 16) + dreadw(addr) + regs.y;
|
||||
break;
|
||||
case OPTYPE_RELB:
|
||||
r = (regs.pc.b << 16) + ((regs.pc.w + 2) & 0xffff);
|
||||
r += int8(addr);
|
||||
break;
|
||||
case OPTYPE_RELW:
|
||||
r = (regs.pc.b << 16) + ((regs.pc.w + 3) & 0xffff);
|
||||
r += int16(addr);
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
return(r & 0xffffff);
|
||||
}
|
||||
|
||||
void CPU::disassemble_opcode(char *output) {
|
||||
char *s = output;
|
||||
static CPUReg24 pc;
|
||||
char t[256];
|
||||
uint8 op, op0, op1, op2;
|
||||
sprintf(s, "%0.6x ", regs.pc.d);
|
||||
char *s = output;
|
||||
|
||||
//TODO: This should wrap around the bank byte
|
||||
op = mem_bus->read(regs.pc.d);
|
||||
op0 = mem_bus->read(regs.pc.d + 1);
|
||||
op1 = mem_bus->read(regs.pc.d + 2);
|
||||
op2 = mem_bus->read(regs.pc.d + 3);
|
||||
|
||||
switch(op) {
|
||||
case 0x00:sprintf(t, "brk #$%0.2x ", op0);break;
|
||||
case 0x01:sprintf(t, "ora ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
|
||||
case 0x02:sprintf(t, "cop #$%0.2x ", op0);break;
|
||||
case 0x03:sprintf(t, "ora $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
|
||||
case 0x04:sprintf(t, "tsb $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0x05:sprintf(t, "ora $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0x06:sprintf(t, "asl $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0x07:sprintf(t, "ora [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
|
||||
case 0x08:sprintf(t, "php ");break;
|
||||
case 0x09:
|
||||
if(regs.p.m)sprintf(t, "ora #$%0.2x ", op0);
|
||||
else sprintf(t, "ora #$%0.4x ", op0|op1<<8);break;
|
||||
case 0x0a:sprintf(t, "asl a ");break;
|
||||
case 0x0b:sprintf(t, "phd ");break;
|
||||
case 0x0c:sprintf(t, "tsb $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0x0d:sprintf(t, "ora $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0x0e:sprintf(t, "asl $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0x0f:sprintf(t, "ora $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
|
||||
case 0x10:sprintf(t, "bpl $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
|
||||
case 0x11:sprintf(t, "ora ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
|
||||
case 0x12:sprintf(t, "ora ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
|
||||
case 0x13:sprintf(t, "ora ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
|
||||
case 0x14:sprintf(t, "trb $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0x15:sprintf(t, "ora $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
|
||||
case 0x16:sprintf(t, "asl $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
|
||||
case 0x17:sprintf(t, "ora [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
|
||||
case 0x18:sprintf(t, "clc ");break;
|
||||
case 0x19:sprintf(t, "ora $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
|
||||
case 0x1a:sprintf(t, "inc ");break;
|
||||
case 0x1b:sprintf(t, "tcs ");break;
|
||||
case 0x1c:sprintf(t, "trb $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0x1d:sprintf(t, "ora $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
|
||||
case 0x1e:sprintf(t, "asl $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
|
||||
case 0x1f:sprintf(t, "ora $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
|
||||
case 0x20:sprintf(t, "jsr $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR_PC, (op0|op1<<8)));break;
|
||||
case 0x21:sprintf(t, "and ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
|
||||
case 0x22:sprintf(t, "jsl $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
|
||||
case 0x23:sprintf(t, "and $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
|
||||
case 0x24:sprintf(t, "bit $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0x25:sprintf(t, "and $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0x26:sprintf(t, "rol $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0x27:sprintf(t, "and [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
|
||||
case 0x28:sprintf(t, "plp ");break;
|
||||
case 0x29:
|
||||
if(regs.p.m)sprintf(t, "and #$%0.2x ", op0);
|
||||
else sprintf(t, "and #$%0.4x ", op0|op1<<8);break;
|
||||
case 0x2a:sprintf(t, "rol a ");break;
|
||||
case 0x2b:sprintf(t, "pld ");break;
|
||||
case 0x2c:sprintf(t, "bit $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0x2d:sprintf(t, "and $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0x2e:sprintf(t, "rol $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0x2f:sprintf(t, "and $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
|
||||
case 0x30:sprintf(t, "bmi $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
|
||||
case 0x31:sprintf(t, "and ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
|
||||
case 0x32:sprintf(t, "and ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
|
||||
case 0x33:sprintf(t, "and ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
|
||||
case 0x34:sprintf(t, "bit $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
|
||||
case 0x35:sprintf(t, "and $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
|
||||
case 0x36:sprintf(t, "rol $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
|
||||
case 0x37:sprintf(t, "and [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
|
||||
case 0x38:sprintf(t, "sec ");break;
|
||||
case 0x39:sprintf(t, "and $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
|
||||
case 0x3a:sprintf(t, "dec ");break;
|
||||
case 0x3b:sprintf(t, "tsc ");break;
|
||||
case 0x3c:sprintf(t, "bit $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
|
||||
case 0x3d:sprintf(t, "and $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
|
||||
case 0x3e:sprintf(t, "rol $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
|
||||
case 0x3f:sprintf(t, "and $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
|
||||
case 0x40:sprintf(t, "rti ");break;
|
||||
case 0x41:sprintf(t, "eor ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
|
||||
case 0x42:sprintf(t, "wdm ");break;
|
||||
case 0x43:sprintf(t, "eor $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
|
||||
case 0x44:sprintf(t, "mvp $%0.2x,$%0.2x ", op1, op0);break;
|
||||
case 0x45:sprintf(t, "eor $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0x46:sprintf(t, "lsr $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0x47:sprintf(t, "eor [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
|
||||
case 0x48:sprintf(t, "pha ");break;
|
||||
case 0x49:
|
||||
if(regs.p.m)sprintf(t, "eor #$%0.2x ", op0);
|
||||
else sprintf(t, "eor #$%0.4x ", op0|op1<<8);break;
|
||||
case 0x4a:sprintf(t, "lsr a ");break;
|
||||
case 0x4b:sprintf(t, "phk ");break;
|
||||
case 0x4c:sprintf(t, "jmp $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR_PC, (op0|op1<<8)));break;
|
||||
case 0x4d:sprintf(t, "eor $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0x4e:sprintf(t, "lsr $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0x4f:sprintf(t, "eor $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
|
||||
case 0x50:sprintf(t, "bvc $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
|
||||
case 0x51:sprintf(t, "eor ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
|
||||
case 0x52:sprintf(t, "eor ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
|
||||
case 0x53:sprintf(t, "eor ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
|
||||
case 0x54:sprintf(t, "mvn $%0.2x,$%0.2x ", op1, op0);break;
|
||||
case 0x55:sprintf(t, "eor $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
|
||||
case 0x56:sprintf(t, "lsr $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
|
||||
case 0x57:sprintf(t, "eor [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
|
||||
case 0x58:sprintf(t, "cli ");break;
|
||||
case 0x59:sprintf(t, "eor $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
|
||||
case 0x5a:sprintf(t, "phy ");break;
|
||||
case 0x5b:sprintf(t, "tcd ");break;
|
||||
case 0x5c:sprintf(t, "jml $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
|
||||
case 0x5d:sprintf(t, "eor $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
|
||||
case 0x5e:sprintf(t, "lsr $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
|
||||
case 0x5f:sprintf(t, "eor $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
|
||||
case 0x60:sprintf(t, "rts ");break;
|
||||
case 0x61:sprintf(t, "adc ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
|
||||
case 0x62:sprintf(t, "per $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0x63:sprintf(t, "adc $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
|
||||
case 0x64:sprintf(t, "stz $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0x65:sprintf(t, "adc $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0x66:sprintf(t, "ror $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0x67:sprintf(t, "adc [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
|
||||
case 0x68:sprintf(t, "pla ");break;
|
||||
case 0x69:
|
||||
if(regs.p.m)sprintf(t, "adc #$%0.2x ", op0);
|
||||
else sprintf(t, "adc #$%0.4x ", op0|op1<<8);break;
|
||||
case 0x6a:sprintf(t, "ror a ");break;
|
||||
case 0x6b:sprintf(t, "rtl ");break;
|
||||
case 0x6c:sprintf(t, "jmp ($%0.4x) [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_IADDR_PC, (op0|op1<<8)));break;
|
||||
case 0x6d:sprintf(t, "adc $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0x6e:sprintf(t, "ror $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0x6f:sprintf(t, "adc $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
|
||||
case 0x70:sprintf(t, "bvs $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
|
||||
case 0x71:sprintf(t, "adc ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
|
||||
case 0x72:sprintf(t, "adc ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
|
||||
case 0x73:sprintf(t, "adc ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
|
||||
case 0x74:sprintf(t, "stz $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
|
||||
case 0x75:sprintf(t, "adc $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
|
||||
case 0x76:sprintf(t, "ror $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
|
||||
case 0x77:sprintf(t, "adc [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
|
||||
case 0x78:sprintf(t, "sei ");break;
|
||||
case 0x79:sprintf(t, "adc $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
|
||||
case 0x7a:sprintf(t, "ply ");break;
|
||||
case 0x7b:sprintf(t, "tdc ");break;
|
||||
case 0x7c:sprintf(t, "jmp ($%0.4x,x) [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_IADDRX, (op0|op1<<8)));break;
|
||||
case 0x7d:sprintf(t, "adc $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
|
||||
case 0x7e:sprintf(t, "ror $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
|
||||
case 0x7f:sprintf(t, "adc $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
|
||||
case 0x80:sprintf(t, "bra $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
|
||||
case 0x81:sprintf(t, "sta ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
|
||||
case 0x82:sprintf(t, "brl $%0.4x [$%0.6x]", __relw(op0|op1<<8)&0xffff, __relw(op0|op1<<8)&0xffffff);break;
|
||||
case 0x83:sprintf(t, "sta $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
|
||||
case 0x84:sprintf(t, "sty $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0x85:sprintf(t, "sta $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0x86:sprintf(t, "stx $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0x87:sprintf(t, "sta [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
|
||||
case 0x88:sprintf(t, "dey ");break;
|
||||
case 0x89:
|
||||
if(regs.p.m)sprintf(t, "bit #$%0.2x ", op0);
|
||||
else sprintf(t, "bit #$%0.4x ", op0|op1<<8);break;
|
||||
case 0x8a:sprintf(t, "txa ");break;
|
||||
case 0x8b:sprintf(t, "phb ");break;
|
||||
case 0x8c:sprintf(t, "sty $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0x8d:sprintf(t, "sta $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0x8e:sprintf(t, "stx $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0x8f:sprintf(t, "sta $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
|
||||
case 0x90:sprintf(t, "bcc $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
|
||||
case 0x91:sprintf(t, "sta ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
|
||||
case 0x92:sprintf(t, "sta ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
|
||||
case 0x93:sprintf(t, "sta ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
|
||||
case 0x94:sprintf(t, "sty $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
|
||||
case 0x95:sprintf(t, "sta $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
|
||||
case 0x96:sprintf(t, "stx $%0.2x,y [$%0.6x]", op0, resolve_offset(OPTYPE_DPY, op0));break;
|
||||
case 0x97:sprintf(t, "sta [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
|
||||
case 0x98:sprintf(t, "tya ");break;
|
||||
case 0x99:sprintf(t, "sta $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
|
||||
case 0x9a:sprintf(t, "txs ");break;
|
||||
case 0x9b:sprintf(t, "txy ");break;
|
||||
case 0x9c:sprintf(t, "stz $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0x9d:sprintf(t, "sta $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
|
||||
case 0x9e:sprintf(t, "stz $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
|
||||
case 0x9f:sprintf(t, "sta $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
|
||||
case 0xa0:
|
||||
if(regs.p.x)sprintf(t, "ldy #$%0.2x ", op0);
|
||||
else sprintf(t, "ldy #$%0.4x ", op0|op1<<8);break;
|
||||
case 0xa1:sprintf(t, "lda ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
|
||||
case 0xa2:
|
||||
if(regs.p.x)sprintf(t, "ldx #$%0.2x ", op0);
|
||||
else sprintf(t, "ldx #$%0.4x ", op0|op1<<8);break;
|
||||
case 0xa3:sprintf(t, "lda $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
|
||||
case 0xa4:sprintf(t, "ldy $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0xa5:sprintf(t, "lda $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0xa6:sprintf(t, "ldx $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0xa7:sprintf(t, "lda [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
|
||||
case 0xa8:sprintf(t, "tay ");break;
|
||||
case 0xa9:
|
||||
if(regs.p.m)sprintf(t, "lda #$%0.2x ", op0);
|
||||
else sprintf(t, "lda #$%0.4x ", op0|op1<<8);break;
|
||||
case 0xaa:sprintf(t, "tax ");break;
|
||||
case 0xab:sprintf(t, "plb ");break;
|
||||
case 0xac:sprintf(t, "ldy $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0xad:sprintf(t, "lda $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0xae:sprintf(t, "ldx $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0xaf:sprintf(t, "lda $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
|
||||
case 0xb0:sprintf(t, "bcs $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
|
||||
case 0xb1:sprintf(t, "lda ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
|
||||
case 0xb2:sprintf(t, "lda ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
|
||||
case 0xb3:sprintf(t, "lda ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
|
||||
case 0xb4:sprintf(t, "ldy $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
|
||||
case 0xb5:sprintf(t, "lda $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
|
||||
case 0xb6:sprintf(t, "ldx $%0.2x,y [$%0.6x]", op0, resolve_offset(OPTYPE_DPY, op0));break;
|
||||
case 0xb7:sprintf(t, "lda [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
|
||||
case 0xb8:sprintf(t, "clv ");break;
|
||||
case 0xb9:sprintf(t, "lda $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
|
||||
case 0xba:sprintf(t, "tsx ");break;
|
||||
case 0xbb:sprintf(t, "tyx ");break;
|
||||
case 0xbc:sprintf(t, "ldy $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
|
||||
case 0xbd:sprintf(t, "lda $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
|
||||
case 0xbe:sprintf(t, "ldx $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
|
||||
case 0xbf:sprintf(t, "lda $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
|
||||
case 0xc0:
|
||||
if(regs.p.x)sprintf(t, "cpy #$%0.2x ", op0);
|
||||
else sprintf(t, "cpy #$%0.4x ", op0|op1<<8);break;
|
||||
case 0xc1:sprintf(t, "cmp ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
|
||||
case 0xc2:sprintf(t, "rep #$%0.2x ", op0);break;
|
||||
case 0xc3:sprintf(t, "cmp $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
|
||||
case 0xc4:sprintf(t, "cpy $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0xc5:sprintf(t, "cmp $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0xc6:sprintf(t, "dec $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0xc7:sprintf(t, "cmp [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
|
||||
case 0xc8:sprintf(t, "iny ");break;
|
||||
case 0xc9:
|
||||
if(regs.p.m)sprintf(t, "cmp #$%0.2x ", op0);
|
||||
else sprintf(t, "cmp #$%0.4x ", op0|op1<<8);break;
|
||||
case 0xca:sprintf(t, "dex ");break;
|
||||
case 0xcb:sprintf(t, "wai ");break;
|
||||
case 0xcc:sprintf(t, "cpy $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0xcd:sprintf(t, "cmp $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0xce:sprintf(t, "dec $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0xcf:sprintf(t, "cmp $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
|
||||
case 0xd0:sprintf(t, "bne $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
|
||||
case 0xd1:sprintf(t, "cmp ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
|
||||
case 0xd2:sprintf(t, "cmp ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
|
||||
case 0xd3:sprintf(t, "cmp ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
|
||||
case 0xd4:sprintf(t, "pei ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
|
||||
case 0xd5:sprintf(t, "cmp $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
|
||||
case 0xd6:sprintf(t, "dec $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
|
||||
case 0xd7:sprintf(t, "cmp [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
|
||||
case 0xd8:sprintf(t, "cld ");break;
|
||||
case 0xd9:sprintf(t, "cmp $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
|
||||
case 0xda:sprintf(t, "phx ");break;
|
||||
case 0xdb:sprintf(t, "stp ");break;
|
||||
case 0xdc:sprintf(t, "jmp [$%0.4x] [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ILADDR, (op0|op1<<8)));break;
|
||||
case 0xdd:sprintf(t, "cmp $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
|
||||
case 0xde:sprintf(t, "dec $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
|
||||
case 0xdf:sprintf(t, "cmp $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
|
||||
case 0xe0:
|
||||
if(regs.p.x)sprintf(t, "cpx #$%0.2x ", op0);
|
||||
else sprintf(t, "cpx #$%0.4x ", op0|op1<<8);break;
|
||||
case 0xe1:sprintf(t, "sbc ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
|
||||
case 0xe2:sprintf(t, "sep #$%0.2x ", op0);break;
|
||||
case 0xe3:sprintf(t, "sbc $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
|
||||
case 0xe4:sprintf(t, "cpx $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0xe5:sprintf(t, "sbc $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0xe6:sprintf(t, "inc $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
|
||||
case 0xe7:sprintf(t, "sbc [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
|
||||
case 0xe8:sprintf(t, "inx ");break;
|
||||
case 0xe9:
|
||||
if(regs.p.m)sprintf(t, "sbc #$%0.2x ", op0);
|
||||
else sprintf(t, "sbc #$%0.4x ", op0|op1<<8);break;
|
||||
case 0xea:sprintf(t, "nop ");break;
|
||||
case 0xeb:sprintf(t, "xba ");break;
|
||||
case 0xec:sprintf(t, "cpx $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0xed:sprintf(t, "sbc $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0xee:sprintf(t, "inc $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0xef:sprintf(t, "sbc $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
|
||||
case 0xf0:sprintf(t, "beq $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
|
||||
case 0xf1:sprintf(t, "sbc ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
|
||||
case 0xf2:sprintf(t, "sbc ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
|
||||
case 0xf3:sprintf(t, "sbc ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
|
||||
case 0xf4:sprintf(t, "pea $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
|
||||
case 0xf5:sprintf(t, "sbc $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
|
||||
case 0xf6:sprintf(t, "inc $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
|
||||
case 0xf7:sprintf(t, "sbc [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
|
||||
case 0xf8:sprintf(t, "sed ");break;
|
||||
case 0xf9:sprintf(t, "sbc $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
|
||||
case 0xfa:sprintf(t, "plx ");break;
|
||||
case 0xfb:sprintf(t, "xce ");break;
|
||||
case 0xfc:sprintf(t, "jsr ($%0.4x,x) [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_IADDRX, (op0|op1<<8)));break;
|
||||
case 0xfd:sprintf(t, "sbc $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
|
||||
case 0xfe:sprintf(t, "inc $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
|
||||
case 0xff:sprintf(t, "sbc $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
|
||||
if(in_opcode() == true) {
|
||||
strcpy(s, "?????? <CPU within opcode>");
|
||||
return;
|
||||
}
|
||||
|
||||
pc.d = regs.pc.d;
|
||||
sprintf(s, "%0.6x ", uint32(pc.d));
|
||||
|
||||
uint8 op = dreadb(pc.d); pc.w++;
|
||||
uint8 op0 = dreadb(pc.d); pc.w++;
|
||||
uint8 op1 = dreadb(pc.d); pc.w++;
|
||||
uint8 op2 = dreadb(pc.d);
|
||||
|
||||
#define op8 ((op0))
|
||||
#define op16 ((op0) | (op1 << 8))
|
||||
#define op24 ((op0) | (op1 << 8) | (op2 << 16))
|
||||
#define a8 (regs.e || regs.p.m)
|
||||
#define x8 (regs.e || regs.p.x)
|
||||
switch(op) {
|
||||
case 0x00: sprintf(t, "brk #$%0.2x ", op8); break;
|
||||
case 0x01: sprintf(t, "ora ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
|
||||
case 0x02: sprintf(t, "cop #$%0.2x ", op8); break;
|
||||
case 0x03: sprintf(t, "ora $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
|
||||
case 0x04: sprintf(t, "tsb $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0x05: sprintf(t, "ora $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0x06: sprintf(t, "asl $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0x07: sprintf(t, "ora [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
|
||||
case 0x08: sprintf(t, "php "); break;
|
||||
case 0x09: if(a8)sprintf(t, "ora #$%0.2x ", op8);
|
||||
else sprintf(t, "ora #$%0.4x ", op16); break;
|
||||
case 0x0a: sprintf(t, "asl a "); break;
|
||||
case 0x0b: sprintf(t, "phd "); break;
|
||||
case 0x0c: sprintf(t, "tsb $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0x0d: sprintf(t, "ora $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0x0e: sprintf(t, "asl $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0x0f: sprintf(t, "ora $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
|
||||
case 0x10: sprintf(t, "bpl $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
|
||||
case 0x11: sprintf(t, "ora ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
|
||||
case 0x12: sprintf(t, "ora ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
|
||||
case 0x13: sprintf(t, "ora ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
|
||||
case 0x14: sprintf(t, "trb $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0x15: sprintf(t, "ora $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
|
||||
case 0x16: sprintf(t, "asl $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
|
||||
case 0x17: sprintf(t, "ora [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
|
||||
case 0x18: sprintf(t, "clc "); break;
|
||||
case 0x19: sprintf(t, "ora $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
|
||||
case 0x1a: sprintf(t, "inc "); break;
|
||||
case 0x1b: sprintf(t, "tcs "); break;
|
||||
case 0x1c: sprintf(t, "trb $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0x1d: sprintf(t, "ora $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
|
||||
case 0x1e: sprintf(t, "asl $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
|
||||
case 0x1f: sprintf(t, "ora $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
|
||||
case 0x20: sprintf(t, "jsr $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break;
|
||||
case 0x21: sprintf(t, "and ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
|
||||
case 0x22: sprintf(t, "jsl $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
|
||||
case 0x23: sprintf(t, "and $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
|
||||
case 0x24: sprintf(t, "bit $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0x25: sprintf(t, "and $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0x26: sprintf(t, "rol $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0x27: sprintf(t, "and [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
|
||||
case 0x28: sprintf(t, "plp "); break;
|
||||
case 0x29: if(a8)sprintf(t, "and #$%0.2x ", op8);
|
||||
else sprintf(t, "and #$%0.4x ", op16); break;
|
||||
case 0x2a: sprintf(t, "rol a "); break;
|
||||
case 0x2b: sprintf(t, "pld "); break;
|
||||
case 0x2c: sprintf(t, "bit $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0x2d: sprintf(t, "and $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0x2e: sprintf(t, "rol $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0x2f: sprintf(t, "and $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
|
||||
case 0x30: sprintf(t, "bmi $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
|
||||
case 0x31: sprintf(t, "and ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
|
||||
case 0x32: sprintf(t, "and ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
|
||||
case 0x33: sprintf(t, "and ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
|
||||
case 0x34: sprintf(t, "bit $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
|
||||
case 0x35: sprintf(t, "and $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
|
||||
case 0x36: sprintf(t, "rol $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
|
||||
case 0x37: sprintf(t, "and [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
|
||||
case 0x38: sprintf(t, "sec "); break;
|
||||
case 0x39: sprintf(t, "and $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
|
||||
case 0x3a: sprintf(t, "dec "); break;
|
||||
case 0x3b: sprintf(t, "tsc "); break;
|
||||
case 0x3c: sprintf(t, "bit $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
|
||||
case 0x3d: sprintf(t, "and $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
|
||||
case 0x3e: sprintf(t, "rol $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
|
||||
case 0x3f: sprintf(t, "and $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
|
||||
case 0x40: sprintf(t, "rti "); break;
|
||||
case 0x41: sprintf(t, "eor ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
|
||||
case 0x42: sprintf(t, "wdm "); break;
|
||||
case 0x43: sprintf(t, "eor $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
|
||||
case 0x44: sprintf(t, "mvp $%0.2x,$%0.2x ", op1, op8); break;
|
||||
case 0x45: sprintf(t, "eor $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0x46: sprintf(t, "lsr $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0x47: sprintf(t, "eor [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
|
||||
case 0x48: sprintf(t, "pha "); break;
|
||||
case 0x49: if(a8)sprintf(t, "eor #$%0.2x ", op8);
|
||||
else sprintf(t, "eor #$%0.4x ", op16); break;
|
||||
case 0x4a: sprintf(t, "lsr a "); break;
|
||||
case 0x4b: sprintf(t, "phk "); break;
|
||||
case 0x4c: sprintf(t, "jmp $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break;
|
||||
case 0x4d: sprintf(t, "eor $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0x4e: sprintf(t, "lsr $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0x4f: sprintf(t, "eor $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
|
||||
case 0x50: sprintf(t, "bvc $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
|
||||
case 0x51: sprintf(t, "eor ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
|
||||
case 0x52: sprintf(t, "eor ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
|
||||
case 0x53: sprintf(t, "eor ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
|
||||
case 0x54: sprintf(t, "mvn $%0.2x,$%0.2x ", op1, op8); break;
|
||||
case 0x55: sprintf(t, "eor $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
|
||||
case 0x56: sprintf(t, "lsr $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
|
||||
case 0x57: sprintf(t, "eor [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
|
||||
case 0x58: sprintf(t, "cli "); break;
|
||||
case 0x59: sprintf(t, "eor $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
|
||||
case 0x5a: sprintf(t, "phy "); break;
|
||||
case 0x5b: sprintf(t, "tcd "); break;
|
||||
case 0x5c: sprintf(t, "jml $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
|
||||
case 0x5d: sprintf(t, "eor $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
|
||||
case 0x5e: sprintf(t, "lsr $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
|
||||
case 0x5f: sprintf(t, "eor $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
|
||||
case 0x60: sprintf(t, "rts "); break;
|
||||
case 0x61: sprintf(t, "adc ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
|
||||
case 0x62: sprintf(t, "per $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0x63: sprintf(t, "adc $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
|
||||
case 0x64: sprintf(t, "stz $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0x65: sprintf(t, "adc $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0x66: sprintf(t, "ror $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0x67: sprintf(t, "adc [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
|
||||
case 0x68: sprintf(t, "pla "); break;
|
||||
case 0x69: if(a8)sprintf(t, "adc #$%0.2x ", op8);
|
||||
else sprintf(t, "adc #$%0.4x ", op16); break;
|
||||
case 0x6a: sprintf(t, "ror a "); break;
|
||||
case 0x6b: sprintf(t, "rtl "); break;
|
||||
case 0x6c: sprintf(t, "jmp ($%0.4x) [$%0.6x]", op16, decode(OPTYPE_IADDR_PC, op16)); break;
|
||||
case 0x6d: sprintf(t, "adc $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0x6e: sprintf(t, "ror $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0x6f: sprintf(t, "adc $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
|
||||
case 0x70: sprintf(t, "bvs $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
|
||||
case 0x71: sprintf(t, "adc ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
|
||||
case 0x72: sprintf(t, "adc ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
|
||||
case 0x73: sprintf(t, "adc ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
|
||||
case 0x74: sprintf(t, "stz $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
|
||||
case 0x75: sprintf(t, "adc $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
|
||||
case 0x76: sprintf(t, "ror $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
|
||||
case 0x77: sprintf(t, "adc [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
|
||||
case 0x78: sprintf(t, "sei "); break;
|
||||
case 0x79: sprintf(t, "adc $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
|
||||
case 0x7a: sprintf(t, "ply "); break;
|
||||
case 0x7b: sprintf(t, "tdc "); break;
|
||||
case 0x7c: sprintf(t, "jmp ($%0.4x,x) [$%0.6x]", op16, decode(OPTYPE_IADDRX, op16)); break;
|
||||
case 0x7d: sprintf(t, "adc $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
|
||||
case 0x7e: sprintf(t, "ror $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
|
||||
case 0x7f: sprintf(t, "adc $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
|
||||
case 0x80: sprintf(t, "bra $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
|
||||
case 0x81: sprintf(t, "sta ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
|
||||
case 0x82: sprintf(t, "brl $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELW, op16)), decode(OPTYPE_RELW, op16)); break;
|
||||
case 0x83: sprintf(t, "sta $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
|
||||
case 0x84: sprintf(t, "sty $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0x85: sprintf(t, "sta $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0x86: sprintf(t, "stx $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0x87: sprintf(t, "sta [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
|
||||
case 0x88: sprintf(t, "dey "); break;
|
||||
case 0x89: if(a8)sprintf(t, "bit #$%0.2x ", op8);
|
||||
else sprintf(t, "bit #$%0.4x ", op16); break;
|
||||
case 0x8a: sprintf(t, "txa "); break;
|
||||
case 0x8b: sprintf(t, "phb "); break;
|
||||
case 0x8c: sprintf(t, "sty $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0x8d: sprintf(t, "sta $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0x8e: sprintf(t, "stx $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0x8f: sprintf(t, "sta $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
|
||||
case 0x90: sprintf(t, "bcc $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
|
||||
case 0x91: sprintf(t, "sta ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
|
||||
case 0x92: sprintf(t, "sta ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
|
||||
case 0x93: sprintf(t, "sta ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
|
||||
case 0x94: sprintf(t, "sty $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
|
||||
case 0x95: sprintf(t, "sta $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
|
||||
case 0x96: sprintf(t, "stx $%0.2x,y [$%0.6x]", op8, decode(OPTYPE_DPY, op8)); break;
|
||||
case 0x97: sprintf(t, "sta [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
|
||||
case 0x98: sprintf(t, "tya "); break;
|
||||
case 0x99: sprintf(t, "sta $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
|
||||
case 0x9a: sprintf(t, "txs "); break;
|
||||
case 0x9b: sprintf(t, "txy "); break;
|
||||
case 0x9c: sprintf(t, "stz $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0x9d: sprintf(t, "sta $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
|
||||
case 0x9e: sprintf(t, "stz $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
|
||||
case 0x9f: sprintf(t, "sta $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
|
||||
case 0xa0: if(x8)sprintf(t, "ldy #$%0.2x ", op8);
|
||||
else sprintf(t, "ldy #$%0.4x ", op16); break;
|
||||
case 0xa1: sprintf(t, "lda ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
|
||||
case 0xa2: if(x8)sprintf(t, "ldx #$%0.2x ", op8);
|
||||
else sprintf(t, "ldx #$%0.4x ", op16); break;
|
||||
case 0xa3: sprintf(t, "lda $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
|
||||
case 0xa4: sprintf(t, "ldy $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0xa5: sprintf(t, "lda $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0xa6: sprintf(t, "ldx $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0xa7: sprintf(t, "lda [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
|
||||
case 0xa8: sprintf(t, "tay "); break;
|
||||
case 0xa9: if(a8)sprintf(t, "lda #$%0.2x ", op8);
|
||||
else sprintf(t, "lda #$%0.4x ", op16); break;
|
||||
case 0xaa: sprintf(t, "tax "); break;
|
||||
case 0xab: sprintf(t, "plb "); break;
|
||||
case 0xac: sprintf(t, "ldy $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0xad: sprintf(t, "lda $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0xae: sprintf(t, "ldx $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0xaf: sprintf(t, "lda $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
|
||||
case 0xb0: sprintf(t, "bcs $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
|
||||
case 0xb1: sprintf(t, "lda ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
|
||||
case 0xb2: sprintf(t, "lda ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
|
||||
case 0xb3: sprintf(t, "lda ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
|
||||
case 0xb4: sprintf(t, "ldy $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
|
||||
case 0xb5: sprintf(t, "lda $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
|
||||
case 0xb6: sprintf(t, "ldx $%0.2x,y [$%0.6x]", op8, decode(OPTYPE_DPY, op8)); break;
|
||||
case 0xb7: sprintf(t, "lda [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
|
||||
case 0xb8: sprintf(t, "clv "); break;
|
||||
case 0xb9: sprintf(t, "lda $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
|
||||
case 0xba: sprintf(t, "tsx "); break;
|
||||
case 0xbb: sprintf(t, "tyx "); break;
|
||||
case 0xbc: sprintf(t, "ldy $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
|
||||
case 0xbd: sprintf(t, "lda $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
|
||||
case 0xbe: sprintf(t, "ldx $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
|
||||
case 0xbf: sprintf(t, "lda $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
|
||||
case 0xc0: if(x8)sprintf(t, "cpy #$%0.2x ", op8);
|
||||
else sprintf(t, "cpy #$%0.4x ", op16); break;
|
||||
case 0xc1: sprintf(t, "cmp ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
|
||||
case 0xc2: sprintf(t, "rep #$%0.2x ", op8); break;
|
||||
case 0xc3: sprintf(t, "cmp $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
|
||||
case 0xc4: sprintf(t, "cpy $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0xc5: sprintf(t, "cmp $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0xc6: sprintf(t, "dec $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0xc7: sprintf(t, "cmp [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
|
||||
case 0xc8: sprintf(t, "iny "); break;
|
||||
case 0xc9: if(a8)sprintf(t, "cmp #$%0.2x ", op8);
|
||||
else sprintf(t, "cmp #$%0.4x ", op16); break;
|
||||
case 0xca: sprintf(t, "dex "); break;
|
||||
case 0xcb: sprintf(t, "wai "); break;
|
||||
case 0xcc: sprintf(t, "cpy $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0xcd: sprintf(t, "cmp $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0xce: sprintf(t, "dec $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0xcf: sprintf(t, "cmp $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
|
||||
case 0xd0: sprintf(t, "bne $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
|
||||
case 0xd1: sprintf(t, "cmp ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
|
||||
case 0xd2: sprintf(t, "cmp ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
|
||||
case 0xd3: sprintf(t, "cmp ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
|
||||
case 0xd4: sprintf(t, "pei ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
|
||||
case 0xd5: sprintf(t, "cmp $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
|
||||
case 0xd6: sprintf(t, "dec $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
|
||||
case 0xd7: sprintf(t, "cmp [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
|
||||
case 0xd8: sprintf(t, "cld "); break;
|
||||
case 0xd9: sprintf(t, "cmp $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
|
||||
case 0xda: sprintf(t, "phx "); break;
|
||||
case 0xdb: sprintf(t, "stp "); break;
|
||||
case 0xdc: sprintf(t, "jmp [$%0.4x] [$%0.6x]", op16, decode(OPTYPE_ILADDR, op16)); break;
|
||||
case 0xdd: sprintf(t, "cmp $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
|
||||
case 0xde: sprintf(t, "dec $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
|
||||
case 0xdf: sprintf(t, "cmp $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
|
||||
case 0xe0: if(x8)sprintf(t, "cpx #$%0.2x ", op8);
|
||||
else sprintf(t, "cpx #$%0.4x ", op16); break;
|
||||
case 0xe1: sprintf(t, "sbc ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
|
||||
case 0xe2: sprintf(t, "sep #$%0.2x ", op8); break;
|
||||
case 0xe3: sprintf(t, "sbc $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
|
||||
case 0xe4: sprintf(t, "cpx $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0xe5: sprintf(t, "sbc $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0xe6: sprintf(t, "inc $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
|
||||
case 0xe7: sprintf(t, "sbc [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
|
||||
case 0xe8: sprintf(t, "inx "); break;
|
||||
case 0xe9: if(a8)sprintf(t, "sbc #$%0.2x ", op8);
|
||||
else sprintf(t, "sbc #$%0.4x ", op16); break;
|
||||
case 0xea: sprintf(t, "nop "); break;
|
||||
case 0xeb: sprintf(t, "xba "); break;
|
||||
case 0xec: sprintf(t, "cpx $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0xed: sprintf(t, "sbc $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0xee: sprintf(t, "inc $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0xef: sprintf(t, "sbc $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
|
||||
case 0xf0: sprintf(t, "beq $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
|
||||
case 0xf1: sprintf(t, "sbc ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
|
||||
case 0xf2: sprintf(t, "sbc ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
|
||||
case 0xf3: sprintf(t, "sbc ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
|
||||
case 0xf4: sprintf(t, "pea $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
|
||||
case 0xf5: sprintf(t, "sbc $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
|
||||
case 0xf6: sprintf(t, "inc $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
|
||||
case 0xf7: sprintf(t, "sbc [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
|
||||
case 0xf8: sprintf(t, "sed "); break;
|
||||
case 0xf9: sprintf(t, "sbc $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
|
||||
case 0xfa: sprintf(t, "plx "); break;
|
||||
case 0xfb: sprintf(t, "xce "); break;
|
||||
case 0xfc: sprintf(t, "jsr ($%0.4x,x) [$%0.6x]", op16, decode(OPTYPE_IADDRX, op16)); break;
|
||||
case 0xfd: sprintf(t, "sbc $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
|
||||
case 0xfe: sprintf(t, "inc $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
|
||||
case 0xff: sprintf(t, "sbc $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
|
||||
}
|
||||
#undef op8
|
||||
#undef op16
|
||||
#undef op24
|
||||
#undef a8
|
||||
#undef x8
|
||||
|
||||
strcat(s, t);
|
||||
strcat(s, " ");
|
||||
|
||||
sprintf(t, "A:%0.4x X:%0.4x Y:%0.4x S:%0.4x D:%0.4x DB:%0.2x ",
|
||||
regs.a.w, regs.x.w, regs.y.w, regs.s.w, regs.d, regs.db);
|
||||
regs.a.w, regs.x.w, regs.y.w, regs.s.w, regs.d.w, regs.db);
|
||||
strcat(s, t);
|
||||
|
||||
if(regs.e) {
|
||||
sprintf(t, "%c%c%c%c%c%c%c%c",
|
||||
(regs.p.n)?'N':'n', (regs.p.v)?'V':'v',
|
||||
(regs.p.m)?'1':'0', (regs.p.x)?'B':'b',
|
||||
(regs.p.d)?'D':'d', (regs.p.i)?'I':'i',
|
||||
(regs.p.z)?'Z':'z', (regs.p.c)?'C':'c');
|
||||
(regs.p.n) ? 'N' : 'n', (regs.p.v) ? 'V' : 'v',
|
||||
(regs.p.m) ? '1' : '0', (regs.p.x) ? 'B' : 'b',
|
||||
(regs.p.d) ? 'D' : 'd', (regs.p.i) ? 'I' : 'i',
|
||||
(regs.p.z) ? 'Z' : 'z', (regs.p.c) ? 'C' : 'c');
|
||||
} else {
|
||||
sprintf(t, "%c%c%c%c%c%c%c%c",
|
||||
(regs.p.n)?'N':'n', (regs.p.v)?'V':'v',
|
||||
(regs.p.m)?'M':'m', (regs.p.x)?'X':'x',
|
||||
(regs.p.d)?'D':'d', (regs.p.i)?'I':'i',
|
||||
(regs.p.z)?'Z':'z', (regs.p.c)?'C':'c');
|
||||
(regs.p.n) ? 'N' : 'n', (regs.p.v) ? 'V' : 'v',
|
||||
(regs.p.m) ? 'M' : 'm', (regs.p.x) ? 'X' : 'x',
|
||||
(regs.p.d) ? 'D' : 'd', (regs.p.i) ? 'I' : 'i',
|
||||
(regs.p.z) ? 'Z' : 'z', (regs.p.c) ? 'C' : 'c');
|
||||
}
|
||||
|
||||
strcat(s, t);
|
||||
strcat(s, " ");
|
||||
|
||||
sprintf(t, "V:%3d H:%4d", vcounter(), hcounter());
|
||||
strcat(s, t);
|
||||
}
|
||||
|
||||
/*
|
||||
opcode_length() retrieves the length of the next opcode
|
||||
to be executed. It is used by the debugger to step over,
|
||||
disable, and proceed cpu opcodes.
|
||||
|
||||
5 and 6 are special cases, 5 is used for #consts based on
|
||||
the A register size, 6 for the X/Y register size. the
|
||||
rest are literal sizes. There's no need to test for
|
||||
emulation mode, as regs.p.m/regs.p.x should *always* be
|
||||
set in emulation mode.
|
||||
*/
|
||||
/*****
|
||||
* opcode_length() retrieves the length of the next opcode
|
||||
* to be executed. It is used by the debugger to step over,
|
||||
* disable and proceed cpu opcodes.
|
||||
*
|
||||
* 5 and 6 are special cases, 5 is used for #consts based on
|
||||
* the A register size, 6 for the X/Y register size. the
|
||||
* rest are literal sizes. There's no need to test for
|
||||
* emulation mode, as regs.p.m/regs.p.x should *always* be
|
||||
* set in emulation mode.
|
||||
*****/
|
||||
uint8 CPU::opcode_length() {
|
||||
uint8 op, len;
|
||||
static uint8 op_len_tbl[256] = {
|
||||
//0,1,2,3, 4,5,6,7, 8,9,a,b, c,d,e,f
|
||||
|
||||
2,2,2,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x0n
|
||||
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0x1n
|
||||
3,2,4,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x2n
|
||||
@@ -431,9 +465,15 @@ static uint8 op_len_tbl[256] = {
|
||||
6,2,2,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0xen
|
||||
2,2,2,2, 3,2,2,2, 1,3,1,1, 3,3,3,4 //0xfn
|
||||
};
|
||||
op = mem_bus->read(regs.pc.d);
|
||||
if(in_opcode() == true) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
op = dreadb(regs.pc.d);
|
||||
len = op_len_tbl[op];
|
||||
if(len == 5)return (regs.p.m)?2:3;
|
||||
if(len == 6)return (regs.p.x)?2:3;
|
||||
if(len == 5)return (regs.e || regs.p.m) ? 2 : 3;
|
||||
if(len == 6)return (regs.e || regs.p.x) ? 2 : 3;
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif //ifdef CPU_CPP
|
||||
@@ -0,0 +1,4 @@
|
||||
g++ -c scpugen.cpp -I../../../lib
|
||||
g++ -c ../../../lib/nall/string.cpp -I../../../lib
|
||||
g++ -o scpugen scpugen.o string.o
|
||||
rm *.o
|
||||
@@ -0,0 +1 @@
|
||||
rm scpugen
|
||||
@@ -0,0 +1,83 @@
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
#include "opfn.cpp"
|
||||
|
||||
void sCPU::enter() { loop:
|
||||
if(event.irq) {
|
||||
event.irq = false;
|
||||
if(status.nmi_pending == true) {
|
||||
status.nmi_pending = false;
|
||||
event.irq_vector = (regs.e == false) ? 0xffea : 0xfffa;
|
||||
} else if(status.irq_pending == true) {
|
||||
status.irq_pending = false;
|
||||
event.irq_vector = (regs.e == false) ? 0xffee : 0xfffe;
|
||||
}
|
||||
op_irq();
|
||||
}
|
||||
|
||||
tracer.trace_cpuop(); //traces CPU opcode (only if tracer is enabled)
|
||||
|
||||
status.in_opcode = true;
|
||||
switch(op_readpc()) {
|
||||
#include "op_read.cpp"
|
||||
#include "op_write.cpp"
|
||||
#include "op_rmw.cpp"
|
||||
#include "op_pc.cpp"
|
||||
#include "op_misc.cpp"
|
||||
}
|
||||
status.in_opcode = false;
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
void sCPU::op_irq() {
|
||||
op_read(regs.pc.d);
|
||||
op_io();
|
||||
if(!regs.e)op_writestack(regs.pc.b);
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestack(regs.e ? (regs.p & ~0x10) : regs.p);
|
||||
rd.l = op_read(event.irq_vector + 0);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
rd.h = op_read(event.irq_vector + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
//immediate, 2-cycle opcodes with I/O cycle will become bus read
|
||||
//when an IRQ is to be triggered immediately after opcode completion
|
||||
//this affects the following opcodes:
|
||||
// clc, cld, cli, clv, sec, sed, sei,
|
||||
// tax, tay, txa, txy, tya, tyx,
|
||||
// tcd, tcs, tdc, tsc, tsx, tcs,
|
||||
// inc, inx, iny, dec, dex, dey,
|
||||
// asl, lsr, rol, ror, nop, xce.
|
||||
alwaysinline void sCPU::op_io_irq() {
|
||||
if(event.irq) {
|
||||
//IRQ pending, modify I/O cycle to bus read cycle, do not increment PC
|
||||
op_read(regs.pc.d);
|
||||
} else {
|
||||
op_io();
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_io_cond2() {
|
||||
if(regs.d.l != 0x00) {
|
||||
op_io();
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_io_cond4(uint16 x, uint16 y) {
|
||||
if(!regs.p.x || (x & 0xff00) != (y & 0xff00)) {
|
||||
op_io();
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_io_cond6(uint16 addr) {
|
||||
if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) {
|
||||
op_io();
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef SCPU_CPP
|
||||
@@ -0,0 +1,54 @@
|
||||
CPUReg24 aa, rd;
|
||||
uint8_t dp, sp;
|
||||
|
||||
void op_irq();
|
||||
|
||||
inline bool in_opcode() { return status.in_opcode; }
|
||||
|
||||
//op_read
|
||||
void op_adc_b();
|
||||
void op_adc_w();
|
||||
void op_and_b();
|
||||
void op_and_w();
|
||||
void op_bit_b();
|
||||
void op_bit_w();
|
||||
void op_cmp_b();
|
||||
void op_cmp_w();
|
||||
void op_cpx_b();
|
||||
void op_cpx_w();
|
||||
void op_cpy_b();
|
||||
void op_cpy_w();
|
||||
void op_eor_b();
|
||||
void op_eor_w();
|
||||
void op_lda_b();
|
||||
void op_lda_w();
|
||||
void op_ldx_b();
|
||||
void op_ldx_w();
|
||||
void op_ldy_b();
|
||||
void op_ldy_w();
|
||||
void op_ora_b();
|
||||
void op_ora_w();
|
||||
void op_sbc_b();
|
||||
void op_sbc_w();
|
||||
//op_rmw
|
||||
void op_inc_b();
|
||||
void op_inc_w();
|
||||
void op_dec_b();
|
||||
void op_dec_w();
|
||||
void op_asl_b();
|
||||
void op_asl_w();
|
||||
void op_lsr_b();
|
||||
void op_lsr_w();
|
||||
void op_rol_b();
|
||||
void op_rol_w();
|
||||
void op_ror_b();
|
||||
void op_ror_w();
|
||||
void op_trb_b();
|
||||
void op_trb_w();
|
||||
void op_tsb_b();
|
||||
void op_tsb_w();
|
||||
|
||||
void op_io_irq();
|
||||
void op_io_cond2();
|
||||
void op_io_cond4(uint16 x, uint16 y);
|
||||
void op_io_cond6(uint16 addr);
|
||||
@@ -0,0 +1,298 @@
|
||||
nop(0xea) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
}
|
||||
|
||||
wdm(0x42) {
|
||||
1:last_cycle();
|
||||
op_readpc();
|
||||
}
|
||||
|
||||
xba(0xeb) {
|
||||
1:op_io();
|
||||
2:last_cycle();
|
||||
op_io();
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.a.h ^= regs.a.l;
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
mvn(0x54, ++),
|
||||
mvp(0x44, --) {
|
||||
1:dp = op_readpc();
|
||||
2:sp = op_readpc();
|
||||
3:regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
4:op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
5:op_io();
|
||||
if(regs.p.x) {
|
||||
regs.x.l $1;
|
||||
regs.y.l $1;
|
||||
} else {
|
||||
regs.x.w $1;
|
||||
regs.y.w $1;
|
||||
}
|
||||
6:last_cycle();
|
||||
op_io();
|
||||
if(regs.a.w--) regs.pc.w -= 3;
|
||||
}
|
||||
|
||||
brk(0x00, 0xfffe, 0xffff, 0xffe6, 0xffe7),
|
||||
cop(0x02, 0xfff4, 0xfff5, 0xffe4, 0xffe5) {
|
||||
1:op_readpc();
|
||||
2:if(!regs.e) op_writestack(regs.pc.b);
|
||||
3:op_writestack(regs.pc.h);
|
||||
4:op_writestack(regs.pc.l);
|
||||
5:op_writestack(regs.p);
|
||||
6:rd.l = op_readlong(regs.e ? $1 : $3);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
7:last_cycle();
|
||||
rd.h = op_readlong(regs.e ? $2 : $4);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
stp(0xdb) {
|
||||
1:op_io();
|
||||
2:last_cycle();
|
||||
while(true) op_io();
|
||||
}
|
||||
|
||||
wai(0xcb) {
|
||||
//last_cycle() will clear event.wai once an NMI / IRQ edge is reached
|
||||
1:event.wai = true;
|
||||
while(event.wai) {
|
||||
last_cycle();
|
||||
op_io();
|
||||
}
|
||||
2:op_io();
|
||||
}
|
||||
|
||||
xce(0xfb) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = regs.e;
|
||||
regs.e = carry;
|
||||
if(regs.e) {
|
||||
regs.p |= 0x30;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
clc(0x18, regs.p.c = 0),
|
||||
cld(0xd8, regs.p.d = 0),
|
||||
cli(0x58, regs.p.i = 0),
|
||||
clv(0xb8, regs.p.v = 0),
|
||||
sec(0x38, regs.p.c = 1),
|
||||
sed(0xf8, regs.p.d = 1),
|
||||
sei(0x78, regs.p.i = 1) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
$1;
|
||||
}
|
||||
|
||||
rep(0xc2, &=~),
|
||||
sep(0xe2, |=) {
|
||||
1:rd.l = op_readpc();
|
||||
2:last_cycle();
|
||||
op_io();
|
||||
regs.p $1 rd.l;
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
tax(0xaa, regs.p.x, x, a),
|
||||
tay(0xa8, regs.p.x, y, a),
|
||||
txa(0x8a, regs.p.m, a, x),
|
||||
txy(0x9b, regs.p.x, y, x),
|
||||
tya(0x98, regs.p.m, a, y),
|
||||
tyx(0xbb, regs.p.x, x, y) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if($1) {
|
||||
regs.$2.l = regs.$3.l;
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
} else {
|
||||
regs.$2.w = regs.$3.w;
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
tcd(0x5b) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
regs.d.w = regs.a.w;
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
}
|
||||
|
||||
tcs(0x1b) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
regs.s.w = regs.a.w;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
tdc(0x7b) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
regs.a.w = regs.d.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
tsc(0x3b) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
regs.a.w = regs.s.w;
|
||||
if(regs.e) {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
tsx(0xba) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.s.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.s.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
txs(0x9a) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.e) {
|
||||
regs.s.l = regs.x.l;
|
||||
} else {
|
||||
regs.s.w = regs.x.w;
|
||||
}
|
||||
}
|
||||
|
||||
pha(0x48, regs.p.m, a),
|
||||
phx(0xda, regs.p.x, x),
|
||||
phy(0x5a, regs.p.x, y) {
|
||||
1:op_io();
|
||||
2:if(!$1)op_writestack(regs.$2.h);
|
||||
3:last_cycle();
|
||||
op_writestack(regs.$2.l);
|
||||
}
|
||||
|
||||
phd(0x0b) {
|
||||
1:op_io();
|
||||
2:op_writestackn(regs.d.h);
|
||||
3:last_cycle();
|
||||
op_writestackn(regs.d.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
phb(0x8b, regs.db),
|
||||
phk(0x4b, regs.pc.b),
|
||||
php(0x08, regs.p) {
|
||||
1:op_io();
|
||||
2:last_cycle();
|
||||
op_writestack($1);
|
||||
}
|
||||
|
||||
pla(0x68, regs.p.m, a),
|
||||
plx(0xfa, regs.p.x, x),
|
||||
ply(0x7a, regs.p.x, y) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:if($1)last_cycle();
|
||||
regs.$2.l = op_readstack();
|
||||
if($1) {
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
end;
|
||||
}
|
||||
4:last_cycle();
|
||||
regs.$2.h = op_readstack();
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
|
||||
pld(0x2b) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:regs.d.l = op_readstackn();
|
||||
4:last_cycle();
|
||||
regs.d.h = op_readstackn();
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
plb(0xab) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:last_cycle();
|
||||
regs.db = op_readstack();
|
||||
regs.p.n = !!(regs.db & 0x80);
|
||||
regs.p.z = (regs.db == 0);
|
||||
}
|
||||
|
||||
plp(0x28) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:last_cycle();
|
||||
regs.p = op_readstack();
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
pea(0xf4) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_writestackn(aa.h);
|
||||
4:last_cycle();
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
pei(0xd4) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:op_writestackn(aa.h);
|
||||
6:last_cycle();
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
per(0x62) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
rd.w = regs.pc.d + (int16)aa.w;
|
||||
4:op_writestackn(rd.h);
|
||||
5:last_cycle();
|
||||
op_writestackn(rd.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
@@ -0,0 +1,536 @@
|
||||
//nop
|
||||
case 0xea: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
} break;
|
||||
|
||||
//wdm
|
||||
case 0x42: {
|
||||
last_cycle();
|
||||
op_readpc();
|
||||
} break;
|
||||
|
||||
//xba
|
||||
case 0xeb: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.a.h ^= regs.a.l;
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} break;
|
||||
|
||||
//mvn
|
||||
case 0x54: {
|
||||
dp = op_readpc();
|
||||
sp = op_readpc();
|
||||
regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
op_io();
|
||||
if(regs.p.x) {
|
||||
regs.x.l ++;
|
||||
regs.y.l ++;
|
||||
} else {
|
||||
regs.x.w ++;
|
||||
regs.y.w ++;
|
||||
}
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.a.w--) regs.pc.w -= 3;
|
||||
} break;
|
||||
|
||||
//mvp
|
||||
case 0x44: {
|
||||
dp = op_readpc();
|
||||
sp = op_readpc();
|
||||
regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
op_io();
|
||||
if(regs.p.x) {
|
||||
regs.x.l --;
|
||||
regs.y.l --;
|
||||
} else {
|
||||
regs.x.w --;
|
||||
regs.y.w --;
|
||||
}
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.a.w--) regs.pc.w -= 3;
|
||||
} break;
|
||||
|
||||
//brk
|
||||
case 0x00: {
|
||||
op_readpc();
|
||||
if(!regs.e) op_writestack(regs.pc.b);
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestack(regs.p);
|
||||
rd.l = op_readlong(regs.e ? 0xfffe : 0xffe6);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
last_cycle();
|
||||
rd.h = op_readlong(regs.e ? 0xffff : 0xffe7);
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
|
||||
//cop
|
||||
case 0x02: {
|
||||
op_readpc();
|
||||
if(!regs.e) op_writestack(regs.pc.b);
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestack(regs.p);
|
||||
rd.l = op_readlong(regs.e ? 0xfff4 : 0xffe4);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
last_cycle();
|
||||
rd.h = op_readlong(regs.e ? 0xfff5 : 0xffe5);
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
|
||||
//stp
|
||||
case 0xdb: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
while(true) op_io();
|
||||
} break;
|
||||
|
||||
//wai
|
||||
case 0xcb: {
|
||||
//last_cycle() will clear event.wai once an NMI / IRQ edge is reached
|
||||
event.wai = true;
|
||||
while(event.wai) {
|
||||
last_cycle();
|
||||
op_io();
|
||||
}
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//xce
|
||||
case 0xfb: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = regs.e;
|
||||
regs.e = carry;
|
||||
if(regs.e) {
|
||||
regs.p |= 0x30;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
} break;
|
||||
|
||||
//clc
|
||||
case 0x18: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.c = 0;
|
||||
} break;
|
||||
|
||||
//cld
|
||||
case 0xd8: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.d = 0;
|
||||
} break;
|
||||
|
||||
//cli
|
||||
case 0x58: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.i = 0;
|
||||
} break;
|
||||
|
||||
//clv
|
||||
case 0xb8: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.v = 0;
|
||||
} break;
|
||||
|
||||
//sec
|
||||
case 0x38: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.c = 1;
|
||||
} break;
|
||||
|
||||
//sed
|
||||
case 0xf8: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.d = 1;
|
||||
} break;
|
||||
|
||||
//sei
|
||||
case 0x78: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.i = 1;
|
||||
} break;
|
||||
|
||||
//rep
|
||||
case 0xc2: {
|
||||
rd.l = op_readpc();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.p &=~ rd.l;
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
} break;
|
||||
|
||||
//sep
|
||||
case 0xe2: {
|
||||
rd.l = op_readpc();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.p |= rd.l;
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
} break;
|
||||
|
||||
//tax
|
||||
case 0xaa: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.a.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.a.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//tay
|
||||
case 0xa8: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.y.l = regs.a.l;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w = regs.a.w;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//txa
|
||||
case 0x8a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.a.l = regs.x.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w = regs.x.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//txy
|
||||
case 0x9b: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.y.l = regs.x.l;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w = regs.x.w;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//tya
|
||||
case 0x98: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.a.l = regs.y.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w = regs.y.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//tyx
|
||||
case 0xbb: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.y.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.y.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//tcd
|
||||
case 0x5b: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.d.w = regs.a.w;
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
} break;
|
||||
|
||||
//tcs
|
||||
case 0x1b: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.s.w = regs.a.w;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//tdc
|
||||
case 0x7b: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.a.w = regs.d.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
} break;
|
||||
|
||||
//tsc
|
||||
case 0x3b: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.a.w = regs.s.w;
|
||||
if(regs.e) {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//tsx
|
||||
case 0xba: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.s.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.s.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//txs
|
||||
case 0x9a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.e) {
|
||||
regs.s.l = regs.x.l;
|
||||
} else {
|
||||
regs.s.w = regs.x.w;
|
||||
}
|
||||
} break;
|
||||
|
||||
//pha
|
||||
case 0x48: {
|
||||
op_io();
|
||||
if(!regs.p.m)op_writestack(regs.a.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.a.l);
|
||||
} break;
|
||||
|
||||
//phx
|
||||
case 0xda: {
|
||||
op_io();
|
||||
if(!regs.p.x)op_writestack(regs.x.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.x.l);
|
||||
} break;
|
||||
|
||||
//phy
|
||||
case 0x5a: {
|
||||
op_io();
|
||||
if(!regs.p.x)op_writestack(regs.y.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.y.l);
|
||||
} break;
|
||||
|
||||
//phd
|
||||
case 0x0b: {
|
||||
op_io();
|
||||
op_writestackn(regs.d.h);
|
||||
last_cycle();
|
||||
op_writestackn(regs.d.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//phb
|
||||
case 0x8b: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_writestack(regs.db);
|
||||
} break;
|
||||
|
||||
//phk
|
||||
case 0x4b: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_writestack(regs.pc.b);
|
||||
} break;
|
||||
|
||||
//php
|
||||
case 0x08: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_writestack(regs.p);
|
||||
} break;
|
||||
|
||||
//pla
|
||||
case 0x68: {
|
||||
op_io();
|
||||
op_io();
|
||||
if(regs.p.m)last_cycle();
|
||||
regs.a.l = op_readstack();
|
||||
if(regs.p.m) {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
break;
|
||||
}
|
||||
last_cycle();
|
||||
regs.a.h = op_readstack();
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
} break;
|
||||
|
||||
//plx
|
||||
case 0xfa: {
|
||||
op_io();
|
||||
op_io();
|
||||
if(regs.p.x)last_cycle();
|
||||
regs.x.l = op_readstack();
|
||||
if(regs.p.x) {
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
break;
|
||||
}
|
||||
last_cycle();
|
||||
regs.x.h = op_readstack();
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
} break;
|
||||
|
||||
//ply
|
||||
case 0x7a: {
|
||||
op_io();
|
||||
op_io();
|
||||
if(regs.p.x)last_cycle();
|
||||
regs.y.l = op_readstack();
|
||||
if(regs.p.x) {
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
break;
|
||||
}
|
||||
last_cycle();
|
||||
regs.y.h = op_readstack();
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
} break;
|
||||
|
||||
//pld
|
||||
case 0x2b: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.d.l = op_readstackn();
|
||||
last_cycle();
|
||||
regs.d.h = op_readstackn();
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//plb
|
||||
case 0xab: {
|
||||
op_io();
|
||||
op_io();
|
||||
last_cycle();
|
||||
regs.db = op_readstack();
|
||||
regs.p.n = !!(regs.db & 0x80);
|
||||
regs.p.z = (regs.db == 0);
|
||||
} break;
|
||||
|
||||
//plp
|
||||
case 0x28: {
|
||||
op_io();
|
||||
op_io();
|
||||
last_cycle();
|
||||
regs.p = op_readstack();
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
} break;
|
||||
|
||||
//pea
|
||||
case 0xf4: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(aa.h);
|
||||
last_cycle();
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//pei
|
||||
case 0xd4: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_writestackn(aa.h);
|
||||
last_cycle();
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//per
|
||||
case 0x62: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.w = regs.pc.d + (int16)aa.w;
|
||||
op_writestackn(rd.h);
|
||||
last_cycle();
|
||||
op_writestackn(rd.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
bcc(0x90, !regs.p.c),
|
||||
bcs(0xb0, regs.p.c),
|
||||
bne(0xd0, !regs.p.z),
|
||||
beq(0xf0, regs.p.z),
|
||||
bpl(0x10, !regs.p.n),
|
||||
bmi(0x30, regs.p.n),
|
||||
bvc(0x50, !regs.p.v),
|
||||
bvs(0x70, regs.p.v) {
|
||||
1:if(!$1) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if($1) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
end;
|
||||
}
|
||||
2:op_io_cond6(aa.w);
|
||||
3:last_cycle();
|
||||
op_io();
|
||||
}
|
||||
|
||||
bra(0x80) {
|
||||
1:rd.l = op_readpc();
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
2:op_io_cond6(aa.w);
|
||||
3:last_cycle();
|
||||
op_io();
|
||||
}
|
||||
|
||||
brl(0x82) {
|
||||
1:rd.l = op_readpc();
|
||||
2:rd.h = op_readpc();
|
||||
3:last_cycle();
|
||||
op_io();
|
||||
regs.pc.w = regs.pc.d + (int16)rd.w;
|
||||
}
|
||||
|
||||
jmp_addr(0x4c) {
|
||||
1:rd.l = op_readpc();
|
||||
2:last_cycle();
|
||||
rd.h = op_readpc();
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
jmp_long(0x5c) {
|
||||
1:rd.l = op_readpc();
|
||||
2:rd.h = op_readpc();
|
||||
3:last_cycle();
|
||||
rd.b = op_readpc();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
jmp_iaddr(0x6c) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:rd.l = op_readaddr(aa.w);
|
||||
4:last_cycle();
|
||||
rd.h = op_readaddr(aa.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
jmp_iaddrx(0x7c) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
4:rd.l = op_readpbr(aa.w + regs.x.w);
|
||||
5:last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
jmp_iladdr(0xdc) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:rd.l = op_readaddr(aa.w);
|
||||
4:rd.h = op_readaddr(aa.w + 1);
|
||||
5:last_cycle();
|
||||
rd.b = op_readaddr(aa.w + 2);
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
jsr_addr(0x20) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
4:regs.pc.w--;
|
||||
op_writestack(regs.pc.h);
|
||||
5:last_cycle();
|
||||
op_writestack(regs.pc.l);
|
||||
regs.pc.w = aa.w;
|
||||
}
|
||||
|
||||
jsr_long(0x22) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_writestackn(regs.pc.b);
|
||||
4:op_io();
|
||||
5:aa.b = op_readpc();
|
||||
6:regs.pc.w--;
|
||||
op_writestackn(regs.pc.h);
|
||||
7:last_cycle();
|
||||
op_writestackn(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
jsr_iaddrx(0xfc) {
|
||||
1:aa.l = op_readpc();
|
||||
2:op_writestackn(regs.pc.h);
|
||||
3:op_writestackn(regs.pc.l);
|
||||
4:aa.h = op_readpc();
|
||||
5:op_io();
|
||||
6:rd.l = op_readpbr(aa.w + regs.x.w);
|
||||
7:last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
rti(0x40) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:regs.p = op_readstack();
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
4:rd.l = op_readstack();
|
||||
5:if(regs.e) last_cycle();
|
||||
rd.h = op_readstack();
|
||||
if(regs.e) {
|
||||
regs.pc.w = rd.w;
|
||||
end;
|
||||
}
|
||||
6:last_cycle();
|
||||
rd.b = op_readstack();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
rts(0x60) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:rd.l = op_readstack();
|
||||
4:rd.h = op_readstack();
|
||||
5:last_cycle();
|
||||
op_io();
|
||||
regs.pc.w = rd.w;
|
||||
regs.pc.w++;
|
||||
}
|
||||
|
||||
rtl(0x6b) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:rd.l = op_readstackn();
|
||||
4:rd.h = op_readstackn();
|
||||
5:last_cycle();
|
||||
rd.b = op_readstackn();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
regs.pc.w++;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
//bcc
|
||||
case 0x90: {
|
||||
if(!!regs.p.c) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(!regs.p.c) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//bcs
|
||||
case 0xb0: {
|
||||
if(!regs.p.c) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.c) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//bne
|
||||
case 0xd0: {
|
||||
if(!!regs.p.z) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(!regs.p.z) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//beq
|
||||
case 0xf0: {
|
||||
if(!regs.p.z) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.z) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//bpl
|
||||
case 0x10: {
|
||||
if(!!regs.p.n) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(!regs.p.n) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//bmi
|
||||
case 0x30: {
|
||||
if(!regs.p.n) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.n) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//bvc
|
||||
case 0x50: {
|
||||
if(!!regs.p.v) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(!regs.p.v) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//bvs
|
||||
case 0x70: {
|
||||
if(!regs.p.v) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.v) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//bra
|
||||
case 0x80: {
|
||||
rd.l = op_readpc();
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//brl
|
||||
case 0x82: {
|
||||
rd.l = op_readpc();
|
||||
rd.h = op_readpc();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.pc.w = regs.pc.d + (int16)rd.w;
|
||||
} break;
|
||||
|
||||
//jmp_addr
|
||||
case 0x4c: {
|
||||
rd.l = op_readpc();
|
||||
last_cycle();
|
||||
rd.h = op_readpc();
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
|
||||
//jmp_long
|
||||
case 0x5c: {
|
||||
rd.l = op_readpc();
|
||||
rd.h = op_readpc();
|
||||
last_cycle();
|
||||
rd.b = op_readpc();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
} break;
|
||||
|
||||
//jmp_iaddr
|
||||
case 0x6c: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readaddr(aa.w);
|
||||
last_cycle();
|
||||
rd.h = op_readaddr(aa.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
|
||||
//jmp_iaddrx
|
||||
case 0x7c: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readpbr(aa.w + regs.x.w);
|
||||
last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
|
||||
//jmp_iladdr
|
||||
case 0xdc: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readaddr(aa.w);
|
||||
rd.h = op_readaddr(aa.w + 1);
|
||||
last_cycle();
|
||||
rd.b = op_readaddr(aa.w + 2);
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
} break;
|
||||
|
||||
//jsr_addr
|
||||
case 0x20: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
regs.pc.w--;
|
||||
op_writestack(regs.pc.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.pc.l);
|
||||
regs.pc.w = aa.w;
|
||||
} break;
|
||||
|
||||
//jsr_long
|
||||
case 0x22: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(regs.pc.b);
|
||||
op_io();
|
||||
aa.b = op_readpc();
|
||||
regs.pc.w--;
|
||||
op_writestackn(regs.pc.h);
|
||||
last_cycle();
|
||||
op_writestackn(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//jsr_iaddrx
|
||||
case 0xfc: {
|
||||
aa.l = op_readpc();
|
||||
op_writestackn(regs.pc.h);
|
||||
op_writestackn(regs.pc.l);
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readpbr(aa.w + regs.x.w);
|
||||
last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//rti
|
||||
case 0x40: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p = op_readstack();
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
rd.l = op_readstack();
|
||||
if(regs.e) last_cycle();
|
||||
rd.h = op_readstack();
|
||||
if(regs.e) {
|
||||
regs.pc.w = rd.w;
|
||||
break;
|
||||
}
|
||||
last_cycle();
|
||||
rd.b = op_readstack();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
} break;
|
||||
|
||||
//rts
|
||||
case 0x60: {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstack();
|
||||
rd.h = op_readstack();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.pc.w = rd.w;
|
||||
regs.pc.w++;
|
||||
} break;
|
||||
|
||||
//rtl
|
||||
case 0x6b: {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstackn();
|
||||
rd.h = op_readstackn();
|
||||
last_cycle();
|
||||
rd.b = op_readstackn();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
regs.pc.w++;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
adc_const(0x69, adc, regs.p.m),
|
||||
and_const(0x29, and, regs.p.m),
|
||||
cmp_const(0xc9, cmp, regs.p.m),
|
||||
cpx_const(0xe0, cpx, regs.p.x),
|
||||
cpy_const(0xc0, cpy, regs.p.x),
|
||||
eor_const(0x49, eor, regs.p.m),
|
||||
lda_const(0xa9, lda, regs.p.m),
|
||||
ldx_const(0xa2, ldx, regs.p.x),
|
||||
ldy_const(0xa0, ldy, regs.p.x),
|
||||
ora_const(0x09, ora, regs.p.m),
|
||||
sbc_const(0xe9, sbc, regs.p.m) {
|
||||
1:if($2) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if($2) { op_$1_b(); end; }
|
||||
2:last_cycle();
|
||||
rd.h = op_readpc();
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_addr(0x6d, adc, regs.p.m),
|
||||
and_addr(0x2d, and, regs.p.m),
|
||||
bit_addr(0x2c, bit, regs.p.m),
|
||||
cmp_addr(0xcd, cmp, regs.p.m),
|
||||
cpx_addr(0xec, cpx, regs.p.x),
|
||||
cpy_addr(0xcc, cpy, regs.p.x),
|
||||
eor_addr(0x4d, eor, regs.p.m),
|
||||
lda_addr(0xad, lda, regs.p.m),
|
||||
ldx_addr(0xae, ldx, regs.p.x),
|
||||
ldy_addr(0xac, ldy, regs.p.x),
|
||||
ora_addr(0x0d, ora, regs.p.m),
|
||||
sbc_addr(0xed, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
4:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_addrx(0x7d, adc, regs.p.m),
|
||||
and_addrx(0x3d, and, regs.p.m),
|
||||
bit_addrx(0x3c, bit, regs.p.m),
|
||||
cmp_addrx(0xdd, cmp, regs.p.m),
|
||||
eor_addrx(0x5d, eor, regs.p.m),
|
||||
lda_addrx(0xbd, lda, regs.p.m),
|
||||
ldy_addrx(0xbc, ldy, regs.p.x),
|
||||
ora_addrx(0x1d, ora, regs.p.m),
|
||||
sbc_addrx(0xfd, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io_cond4(aa.w, aa.w + regs.x.w);
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_addry(0x79, adc, regs.p.m),
|
||||
and_addry(0x39, and, regs.p.m),
|
||||
cmp_addry(0xd9, cmp, regs.p.m),
|
||||
eor_addry(0x59, eor, regs.p.m),
|
||||
lda_addry(0xb9, lda, regs.p.m),
|
||||
ldx_addry(0xbe, ldx, regs.p.x),
|
||||
ora_addry(0x19, ora, regs.p.m),
|
||||
sbc_addry(0xf9, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_long(0x6f, adc, regs.p.m),
|
||||
and_long(0x2f, and, regs.p.m),
|
||||
cmp_long(0xcf, cmp, regs.p.m),
|
||||
eor_long(0x4f, eor, regs.p.m),
|
||||
lda_long(0xaf, lda, regs.p.m),
|
||||
ora_long(0x0f, ora, regs.p.m),
|
||||
sbc_long(0xef, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:aa.b = op_readpc();
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readlong(aa.d);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readlong(aa.d + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_longx(0x7f, adc, regs.p.m),
|
||||
and_longx(0x3f, and, regs.p.m),
|
||||
cmp_longx(0xdf, cmp, regs.p.m),
|
||||
eor_longx(0x5f, eor, regs.p.m),
|
||||
lda_longx(0xbf, lda, regs.p.m),
|
||||
ora_longx(0x1f, ora, regs.p.m),
|
||||
sbc_longx(0xff, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:aa.b = op_readpc();
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readlong(aa.d + regs.x.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readlong(aa.d + regs.x.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_dp(0x65, adc, regs.p.m),
|
||||
and_dp(0x25, and, regs.p.m),
|
||||
bit_dp(0x24, bit, regs.p.m),
|
||||
cmp_dp(0xc5, cmp, regs.p.m),
|
||||
cpx_dp(0xe4, cpx, regs.p.x),
|
||||
cpy_dp(0xc4, cpy, regs.p.x),
|
||||
eor_dp(0x45, eor, regs.p.m),
|
||||
lda_dp(0xa5, lda, regs.p.m),
|
||||
ldx_dp(0xa6, ldx, regs.p.x),
|
||||
ldy_dp(0xa4, ldy, regs.p.x),
|
||||
ora_dp(0x05, ora, regs.p.m),
|
||||
sbc_dp(0xe5, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:if($2) last_cycle();
|
||||
rd.l = op_readdp(dp);
|
||||
if($2) { op_$1_b(); end; }
|
||||
4:last_cycle();
|
||||
rd.h = op_readdp(dp + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_dpx(0x75, adc, regs.p.m),
|
||||
and_dpx(0x35, and, regs.p.m),
|
||||
bit_dpx(0x34, bit, regs.p.m),
|
||||
cmp_dpx(0xd5, cmp, regs.p.m),
|
||||
eor_dpx(0x55, eor, regs.p.m),
|
||||
lda_dpx(0xb5, lda, regs.p.m),
|
||||
ldy_dpx(0xb4, ldy, regs.p.x),
|
||||
ora_dpx(0x15, ora, regs.p.m),
|
||||
sbc_dpx(0xf5, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
ldx_dpy(0xb6, ldx, regs.p.x) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readdp(dp + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readdp(dp + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_idp(0x72, adc, regs.p.m),
|
||||
and_idp(0x32, and, regs.p.m),
|
||||
cmp_idp(0xd2, cmp, regs.p.m),
|
||||
eor_idp(0x52, eor, regs.p.m),
|
||||
lda_idp(0xb2, lda, regs.p.m),
|
||||
ora_idp(0x12, ora, regs.p.m),
|
||||
sbc_idp(0xf2, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
6:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_idpx(0x61, adc, regs.p.m),
|
||||
and_idpx(0x21, and, regs.p.m),
|
||||
cmp_idpx(0xc1, cmp, regs.p.m),
|
||||
eor_idpx(0x41, eor, regs.p.m),
|
||||
lda_idpx(0xa1, lda, regs.p.m),
|
||||
ora_idpx(0x01, ora, regs.p.m),
|
||||
sbc_idpx(0xe1, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:aa.l = op_readdp(dp + regs.x.w);
|
||||
5:aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
6:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_idpy(0x71, adc, regs.p.m),
|
||||
and_idpy(0x31, and, regs.p.m),
|
||||
cmp_idpy(0xd1, cmp, regs.p.m),
|
||||
eor_idpy(0x51, eor, regs.p.m),
|
||||
lda_idpy(0xb1, lda, regs.p.m),
|
||||
ora_idpy(0x11, ora, regs.p.m),
|
||||
sbc_idpy(0xf1, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
6:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_ildp(0x67, adc, regs.p.m),
|
||||
and_ildp(0x27, and, regs.p.m),
|
||||
cmp_ildp(0xc7, cmp, regs.p.m),
|
||||
eor_ildp(0x47, eor, regs.p.m),
|
||||
lda_ildp(0xa7, lda, regs.p.m),
|
||||
ora_ildp(0x07, ora, regs.p.m),
|
||||
sbc_ildp(0xe7, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:aa.b = op_readdp(dp + 2);
|
||||
6:if($2) last_cycle();
|
||||
rd.l = op_readlong(aa.d);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readlong(aa.d + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_ildpy(0x77, adc, regs.p.m),
|
||||
and_ildpy(0x37, and, regs.p.m),
|
||||
cmp_ildpy(0xd7, cmp, regs.p.m),
|
||||
eor_ildpy(0x57, eor, regs.p.m),
|
||||
lda_ildpy(0xb7, lda, regs.p.m),
|
||||
ora_ildpy(0x17, ora, regs.p.m),
|
||||
sbc_ildpy(0xf7, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:aa.b = op_readdp(dp + 2);
|
||||
6:if($2) last_cycle();
|
||||
rd.l = op_readlong(aa.d + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readlong(aa.d + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_sr(0x63, adc, regs.p.m),
|
||||
and_sr(0x23, and, regs.p.m),
|
||||
cmp_sr(0xc3, cmp, regs.p.m),
|
||||
eor_sr(0x43, eor, regs.p.m),
|
||||
lda_sr(0xa3, lda, regs.p.m),
|
||||
ora_sr(0x03, ora, regs.p.m),
|
||||
sbc_sr(0xe3, sbc, regs.p.m) {
|
||||
1:sp = op_readpc();
|
||||
2:op_io();
|
||||
3:if($2) last_cycle();
|
||||
rd.l = op_readsp(sp);
|
||||
if($2) { op_$1_b(); end; }
|
||||
4:last_cycle();
|
||||
rd.h = op_readsp(sp + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_isry(0x73, adc),
|
||||
and_isry(0x33, and),
|
||||
cmp_isry(0xd3, cmp),
|
||||
eor_isry(0x53, eor),
|
||||
lda_isry(0xb3, lda),
|
||||
ora_isry(0x13, ora),
|
||||
sbc_isry(0xf3, sbc) {
|
||||
1:sp = op_readpc();
|
||||
2:op_io();
|
||||
3:aa.l = op_readsp(sp);
|
||||
4:aa.h = op_readsp(sp + 1);
|
||||
5:op_io();
|
||||
6:if(regs.p.m) last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
if(regs.p.m) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
bit_const(0x89) {
|
||||
1:if(regs.p.m) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.m) {
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
end;
|
||||
}
|
||||
2:last_cycle();
|
||||
rd.h = op_readpc();
|
||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,181 @@
|
||||
inc(0x1a, regs.p.m, a),
|
||||
inx(0xe8, regs.p.x, x),
|
||||
iny(0xc8, regs.p.x, y) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if($1) {
|
||||
regs.$2.l++;
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
} else {
|
||||
regs.$2.w++;
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
dec(0x3a, regs.p.m, a),
|
||||
dex(0xca, regs.p.x, x),
|
||||
dey(0x88, regs.p.x, y) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if($1) {
|
||||
regs.$2.l--;
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
} else {
|
||||
regs.$2.w--;
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
asl(0x0a) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
lsr(0x4a) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
rol(0x2a) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
uint16 c = regs.p.c;
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
ror(0x6a) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
uint16 c;
|
||||
if(regs.p.m) {
|
||||
c = regs.p.c ? 0x80 : 0;
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
c = regs.p.c ? 0x8000 : 0;
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
inc_addr(0xee, inc),
|
||||
dec_addr(0xce, dec),
|
||||
asl_addr(0x0e, asl),
|
||||
lsr_addr(0x4e, lsr),
|
||||
rol_addr(0x2e, rol),
|
||||
ror_addr(0x6e, ror),
|
||||
trb_addr(0x1c, trb),
|
||||
tsb_addr(0x0c, tsb) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:rd.l = op_readdbr(aa.w);
|
||||
4:if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
5:op_io();
|
||||
if(regs.p.m) { op_$1_b(); }
|
||||
else { op_$1_w();
|
||||
6:op_writedbr(aa.w + 1, rd.h); }
|
||||
7:last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
}
|
||||
|
||||
inc_addrx(0xfe, inc),
|
||||
dec_addrx(0xde, dec),
|
||||
asl_addrx(0x1e, asl),
|
||||
lsr_addrx(0x5e, lsr),
|
||||
rol_addrx(0x3e, rol),
|
||||
ror_addrx(0x7e, ror) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
4:rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
5:if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
6:op_io();
|
||||
if(regs.p.m) { op_$1_b(); }
|
||||
else { op_$1_w();
|
||||
7:op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
8:last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
}
|
||||
|
||||
inc_dp(0xe6, inc),
|
||||
dec_dp(0xc6, dec),
|
||||
asl_dp(0x06, asl),
|
||||
lsr_dp(0x46, lsr),
|
||||
rol_dp(0x26, rol),
|
||||
ror_dp(0x66, ror),
|
||||
trb_dp(0x14, trb),
|
||||
tsb_dp(0x04, tsb) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:rd.l = op_readdp(dp);
|
||||
4:if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
5:op_io();
|
||||
if(regs.p.m) { op_$1_b(); }
|
||||
else { op_$1_w();
|
||||
6:op_writedp(dp + 1, rd.h); }
|
||||
7:last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
}
|
||||
|
||||
inc_dpx(0xf6, inc),
|
||||
dec_dpx(0xd6, dec),
|
||||
asl_dpx(0x16, asl),
|
||||
lsr_dpx(0x56, lsr),
|
||||
rol_dpx(0x36, rol),
|
||||
ror_dpx(0x76, ror) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:rd.l = op_readdp(dp + regs.x.w);
|
||||
5:if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
6:op_io();
|
||||
if(regs.p.m) { op_$1_b(); }
|
||||
else { op_$1_w();
|
||||
7:op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
8:last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
}
|
||||
@@ -0,0 +1,570 @@
|
||||
//inc
|
||||
case 0x1a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.a.l++;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w++;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//inx
|
||||
case 0xe8: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l++;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w++;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//iny
|
||||
case 0xc8: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.y.l++;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w++;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//dec
|
||||
case 0x3a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.a.l--;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w--;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//dex
|
||||
case 0xca: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l--;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w--;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//dey
|
||||
case 0x88: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.y.l--;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w--;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//asl
|
||||
case 0x0a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//lsr
|
||||
case 0x4a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//rol
|
||||
case 0x2a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
uint16 c = regs.p.c;
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//ror
|
||||
case 0x6a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
uint16 c;
|
||||
if(regs.p.m) {
|
||||
c = regs.p.c ? 0x80 : 0;
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
c = regs.p.c ? 0x8000 : 0;
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//inc_addr
|
||||
case 0xee: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_inc_b(); }
|
||||
else { op_inc_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
|
||||
//dec_addr
|
||||
case 0xce: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_dec_b(); }
|
||||
else { op_dec_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
|
||||
//asl_addr
|
||||
case 0x0e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_asl_b(); }
|
||||
else { op_asl_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
|
||||
//lsr_addr
|
||||
case 0x4e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_lsr_b(); }
|
||||
else { op_lsr_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
|
||||
//rol_addr
|
||||
case 0x2e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_rol_b(); }
|
||||
else { op_rol_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
|
||||
//ror_addr
|
||||
case 0x6e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_ror_b(); }
|
||||
else { op_ror_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
|
||||
//trb_addr
|
||||
case 0x1c: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_trb_b(); }
|
||||
else { op_trb_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
|
||||
//tsb_addr
|
||||
case 0x0c: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_tsb_b(); }
|
||||
else { op_tsb_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
|
||||
//inc_addrx
|
||||
case 0xfe: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_inc_b(); }
|
||||
else { op_inc_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//dec_addrx
|
||||
case 0xde: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_dec_b(); }
|
||||
else { op_dec_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//asl_addrx
|
||||
case 0x1e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_asl_b(); }
|
||||
else { op_asl_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//lsr_addrx
|
||||
case 0x5e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_lsr_b(); }
|
||||
else { op_lsr_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//rol_addrx
|
||||
case 0x3e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_rol_b(); }
|
||||
else { op_rol_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//ror_addrx
|
||||
case 0x7e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_ror_b(); }
|
||||
else { op_ror_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//inc_dp
|
||||
case 0xe6: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_inc_b(); }
|
||||
else { op_inc_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
|
||||
//dec_dp
|
||||
case 0xc6: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_dec_b(); }
|
||||
else { op_dec_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
|
||||
//asl_dp
|
||||
case 0x06: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_asl_b(); }
|
||||
else { op_asl_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
|
||||
//lsr_dp
|
||||
case 0x46: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_lsr_b(); }
|
||||
else { op_lsr_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
|
||||
//rol_dp
|
||||
case 0x26: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_rol_b(); }
|
||||
else { op_rol_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
|
||||
//ror_dp
|
||||
case 0x66: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_ror_b(); }
|
||||
else { op_ror_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
|
||||
//trb_dp
|
||||
case 0x14: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_trb_b(); }
|
||||
else { op_trb_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
|
||||
//tsb_dp
|
||||
case 0x04: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_tsb_b(); }
|
||||
else { op_tsb_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
|
||||
//inc_dpx
|
||||
case 0xf6: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_inc_b(); }
|
||||
else { op_inc_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//dec_dpx
|
||||
case 0xd6: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_dec_b(); }
|
||||
else { op_dec_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//asl_dpx
|
||||
case 0x16: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_asl_b(); }
|
||||
else { op_asl_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//lsr_dpx
|
||||
case 0x56: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_lsr_b(); }
|
||||
else { op_lsr_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//rol_dpx
|
||||
case 0x36: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_rol_b(); }
|
||||
else { op_rol_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
//ror_dpx
|
||||
case 0x76: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.p.m) { op_ror_b(); }
|
||||
else { op_ror_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
} break;
|
||||
|
||||
Loaded 100 of 521 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user