Compare commits

..
11 Commits
Author SHA1 Message Date
byuu 6f7cf1bd31 Update to bsnes v005a release.
[No changelog available]
2005-02-06 04:04:32 +00:00
byuu 8751bc433f Update to bsnes v005 release.
Released a new version of bsnes today. Version 0.0.005 is up on the main page now.
The changes since .004 wip10 include: DRAM timing fix (now occurs mid-opcode), memory address speed fix, added CPU cycle condition 4 to all opcodes that use it, and fixed a bug where DRAM refresh was not changing start positions every other scanline.
With the new version, Chrono Trigger should get a little further, and Final Fantasy 5 should get in-game now. The only problem FF5 seems to have is sprite corrution in the menus. I´m too busy with the CPU timing to mess around with the PPU right now, though. Also, the APU is not bridged to the CPU in this release, so compatibility is (still) really low.
After I get the APU working fairly well, I´ll (try and) start keeping a what´s new file so that people can know what all changed between public releases of the emulator without having to follow this page. Sorry for the inconvenience in the mean time.

[No archive available]
2005-02-05 00:00:00 +00:00
byuu afbee40bc0 Update to bsnes v004 release.
[No changelog available]

[No archive available]
2004-12-24 00:00:00 +00:00
byuu 81e9be64d2 Update to bsnes v003r01 release.
[No changelog available]

[No archive available]
2004-12-13 00:00:00 +00:00
byuu 0cd4972d11 Update to bsnes v002 ir11 release.
Doubled the width of sprites when the width of the screen is 512. The SNES Test Program now runs through all of the character test correctly. The windows are off-by-one though.
Added the very bizarre 00:4300-00:437f memory region that is unique from 7e:4300-7e:437f. Then I added read support from $2180. This allowed the SNES Test Program to not crash after failing the electronics test, and it also fixed the horrible graphics corruption in Der Langrisser.
The fonts were still failing, so I went in with my tracer and found out what was causing it. The following code:
	gx816->regs.pc += (signed char)(arg + 2);
This is the code used to increment the pc counter after relative branches. The problem is that I had parinthesis around the + 2 as well as arg. Therefore, if arg was 0x7e, 0x7f, 0xfe, or 0xff, it would change the sign. This would in turn make the program counter off by 256 bytes. Very bad. Fixing this fixed the font in Der Langrisser, and also fixed Super Mario World, when Yoshi spits a turtle out, the game will no longer crash.
Next, via the Der Langrisser world map, I realized that anomie´s description of the BG/mode7 register latches was reversed: the BG registers (may) share a common latch between all of them, but the mode7 registers do not. I removed the common latches from the mode7 regs, but I haven´t added the latch to the BG registers yet.
I also realized that clearing the entire screen on a BG mode change would probably not be a good thing for games that change video modes mid-frame. So I tried working on getting the weird single-frame garble that pops up every minute or so to go away, but to no avail. I´m having a difficult time tracking down the exact cause of the error, but I believe it to be a buffer overflow, or something along those lines.

[No archive available]
2004-12-11 00:00:00 +00:00
byuu 938609818f Update to bsnes v002 ir9 release.
[No changelog available]
2004-12-07 01:12:32 +00:00
byuu 487491e6f2 Update to bsnes v002 ir7 release.
The bug in the Bahamut Lagoon mode7 screens turned out to be that I never added the dividend result to $4216/$4217. It always returned the multiplication of $4202/$4203. This also fixed the sprites in battles for Dai Kaijuu Monogatari. I added a bunch of window stuff, including a double size windowed mode, and a fullscreen mode. Lots of fixes to the interface, as well as code cleanup. It's still pretty buggy, there's a lot of variables to keep up with in the GUI at present...
I also added better tile caching, I just cache all tiles when they are rendered, for all 3 color depths (4, 16, 256). Seems to help a little. A portion of the speed gain was lost by fixing the dividend result, though. Very strange, since I wouldn't think much work would go into a simple line of code that's called 20 times a frame probably at best... oh well.

[No archive available]
2004-12-05 00:00:00 +00:00
byuu a6ccc7e5d2 Update to unreleased version.
First, I fixed some issues with the mode7 / scroll regs thanks to info from anomie. Qwertie's mode7 demo runs without modification now. Next, I fixed a small glitch with tiles getting cut off on the right edge of the screen, fixes some flickering on the edges in Zelda 3. Finally, I added tile caching to all 4 BG layers. It didn't really increase speed by much (~10%), and upped the RAM requirements by 1.2mb... I left the old code in case I need to fall back on it. My only guess (hope) is that the bottleneck lies somewhere else...

[No archive available]
2004-12-04 00:00:00 +00:00
byuu 39dd39cc09 Update to unreleased version.
Had a small glitch in the OAM $2102/$2103 register settings, fixed that and now both Zelda 3 and Super Mario World always show sprites perfectly. The only error to my knowledge in the below screenshots is that the large version of the mario sprite in the third pic is not shown at the top left of the screen. Which could be because I have no mosaic support. But at any rate, both games should be completely playable now, albeit very slowly. I tried to speed up things by caching some stuff in the PPU, but I couldn't find a nice way to implement it that would result in a significant speed increase. Oh yeah, Zelda won't follow you in Zelda 3, but you can just go to the throne room and push the picture to the right yourself, and she'll appear when you reach the sanctuary.
I also updated the debugger, it uses a smaller font, which is a bit harder to read, but saves a lot of screen space. This will definately be needed when I add in more of the debugging windows in the future, so it's better to get used to it now than later.

[No archive available]
2004-11-27 00:00:00 +00:00
byuu 1a017ff697 Update to unreleased version.
Added SRAM support. It's compatible with other emulators. It maps both the LoROM SRAM between $700000-$7dffff, and HiROM SRAM between $3n6000-$3n7fff (where n = 0 - f).
Modified the screen to redraw at scanline 224, instead of 0. Fixes some flickering between screens in some games.
Moved the lighting adjustment code ($2100 bits 0-3) directly into the PPU, rather than outside in the platform-specific code. This is because games have the ability to adjust this value per scanline. Also allowed the games to control the background enable ($2100 bit 7) flag per scanline now. This allowed Bahamut Lagoon's dragon intro to work.
I then added mode2 support, so now all that's missing is modes 5 and 6 (interlaced).
I also created an easy #define to select between the public domain mode7 code I wrote, and the snes9x mode7 code. I'll go through one of these days and rewrite the snes9x code in a clean environment (e.g. without using the current mode7 file as a reference) to avoid the issue altogether, but for now... the snes9x code is twice as fast, and that's good enough for me.
Lastly, I also added in a trace checkbox to enable tracing. As such, the zip file of my work up now has debug mode enabled by default. I really need an overhaul of the gui implementation, and a configuration file. I have a very nice string library system (that I wrote myself) that I would love to take advantage of in this project.
Here's some screenshots of the dragon intro. Lots of HDMA here, showing that I pretty much have HDMA down, now. I remember zsnes used to have a problem with these screens, and had to do something with an HDMA hack to get around it. They figured out what the problem was, eventually. I was actually quite surprised my emulator does not suffer from this same problem. Lucky for me, as they never did mention what the problem was to begin with. The HDMA is technically drawing too soon (at the start of the scanline instead of the end) which probably messes things up a bit, and I'm guessing the scroll registers are screwing up in one or two of the below pics. No mosaic support either.

[No archive available]
2004-11-21 00:00:00 +00:00
byuu 591adfcb25 Update to unreleased version.
Initial release

[No archive available]
2004-10-14 00:00:00 +00:00
2267 changed files with 19155 additions and 212198 deletions

No files matched your search

-99
View File
@@ -1,99 +0,0 @@
linux-x86_64-binaries_task:
container:
image: ubuntu:latest
setup_script:
- apt-get update && apt-get -y install build-essential libgtk2.0-dev libpulse-dev mesa-common-dev libgtksourceview2.0-dev libcairo2-dev libsdl2-dev libxv-dev libao-dev libopenal-dev libudev-dev zip
compile_script:
- make -C higan target=higan local=false
- make -C icarus
- make -C genius
package_script:
- mkdir higan-nightly
- cp -a higan/out/higan higan-nightly/higan
- cp -a higan/System higan-nightly
- cp -a icarus/out/icarus higan-nightly/icarus
- cp -a icarus/Database higan-nightly
- cp -a icarus/Firmware higan-nightly
- cp -a genius/out/genius higan-nightly/genius
- cp -a GPLv3.txt higan-nightly
- zip -r higan-nightly.zip higan-nightly
higan-nightly_artifacts:
path: "higan-nightly.zip"
freebsd-x86_64-binaries_task:
freebsd_instance:
image: freebsd-12-0-release-amd64
setup_script:
- pkg install --yes gmake gdb gcc8 pkgconf sdl2 openal-soft gtksourceview2 libXv zip
compile_script:
- gmake -C higan target=higan local=false
- gmake -C icarus
- gmake -C genius
package_script:
- mkdir higan-nightly
- cp -a higan/out/higan higan-nightly/higan
- cp -a higan/System higan-nightly
- cp -a icarus/out/icarus higan-nightly/icarus
- cp -a icarus/Database higan-nightly
- cp -a icarus/Firmware higan-nightly
- cp -a genius/out/genius higan-nightly/genius
- cp -a GPLv3.txt higan-nightly
- zip -r higan-nightly.zip higan-nightly
higan-nightly_artifacts:
path: "higan-nightly.zip"
windows-x86_64-binaries_task:
container:
image: ubuntu:latest
setup_script:
- apt-get update && apt-get -y install build-essential mingw-w64 zip
compile_script:
- make -C higan target=higan local=false platform=windows compiler="x86_64-w64-mingw32-g++" windres="x86_64-w64-mingw32-windres"
- make -C icarus platform=windows compiler="x86_64-w64-mingw32-g++" windres="x86_64-w64-mingw32-windres"
package_script:
- mkdir higan-nightly
- cp -a higan/out/higan higan-nightly/higan.exe
- cp -a icarus/out/icarus higan-nightly/icarus.exe
- cp -a higan/System higan-nightly/Templates
- mkdir higan-nightly/Systems
- cp -a icarus/Database higan-nightly
- cp -a icarus/Firmware higan-nightly
- cp -a GPLv3.txt higan-nightly
- echo "templates: ./Templates/" >> higan-nightly/paths.bml
- echo "data: ./Systems/" >> higan-nightly/paths.bml
- zip -r higan-nightly.zip higan-nightly
higan-nightly_artifacts:
path: "higan-nightly.zip"
macOS-x86_64-binaries_task:
osx_instance:
image: mojave-base
compile_script:
- make -C higan target=higan local=false
- make -C icarus
package_script:
- mkdir higan-nightly
- cp -a higan/out/higan.app higan-nightly
- cp -a higan/System higan-nightly
- cp -a icarus/out/icarus.app higan-nightly
- cp -a icarus/Database higan-nightly
- cp -a icarus/Firmware higan-nightly
- cp -a GPLv3.txt higan-nightly
- zip -r higan-nightly.zip higan-nightly
higan-nightly_artifacts:
path: "higan-nightly.zip"
-2
View File
@@ -1,2 +0,0 @@
*.fs linguist-detectable=false
*.vs linguist-detectable=false
-1
View File
@@ -1 +0,0 @@
patreon: byuu
View File
Whitespace-only changes.
-89
View File
@@ -1,89 +0,0 @@
Contributing
============
Code contributions are most welcome and highly appreciated!
But first, please note that although higan is licensed under the GPLv3 license,
in order to be merged upstream, any code contributions must be provided under
the ISC source code license.
This is *not* a CLA (community license agreement), no legal contract needs to be
signed, and you will maintain full and exclusive copyright ownership over any
contributed source code.
There are two reasons for this requirement:
GPLv4+
------
higan is currently licensed under the GPLv3 license only. I do not license higan
under the GPLv3 or later license, because there is no way of knowing what the
GPLv4 and later licenses will change, and if they will be in the best interests
of emulator development and video game preservation.
Although I put a good deal of trust into the FSF, no one is an oracle that can
predict the future. Would *you* agree to a license before being able to read it?
However, the GPLv4 may prove beneficial, and close important holes in the GPLv3
license, just as the GPLv3 license closed the GPLv2's TiVoization loophole. And
so it is important that higan retains the option of relicensing to the GPLv4+ in
the future.
As a point of interest, there have been projects with similar concerns about
using a GPLv2 or later clause, that are now permanently stuck on the GPLv2
license. There have also been projects that did use a GPLv2 or later clause,
only to disagree with the changes introduced in the GPLv3.
ISC
---
The more important reason for this requirement is that it is my intention to
release the entirety of higan under the ISC license once official upstream
development has ceased.
The reason I would want to relicense higan to the ISC license upon its official
discontinuation is because once again, no one is an oracle, and I cannot predict
what future issues higan permanently remaining under the GPLv3 license may
cause.
For instance, imagine a world where a certain vendor took over the world, and
the only way to distribute applications was with their approval, and their store
rules forbade GPLv3 software. Or perhaps a world where the GPL was abandoned in
favor of the new OSSv1 license. But GPLv3 software was incompatible with the
OSSv1 license. Other open source developers would not be able to use higan in
that scenario.
It would be very disappointing if all of our work ended up unusable 50+ years
into the future because it was permanently bound to the GPLv3 license.
GPLv3
-----
The reason I use the GPLv3 license currently is because it is a balance between
altruism and self-interest. The GPLv3 allows other vendors to sell my own code
without sharing revenue with me, and indeed this has already happened. But the
GPLv3 also prevents other vendors from improving upon higan without sharing
their work with everyone else as I have.
While I am actively developing higan, I do not wish to compete against myself.
As such, I believe the GPLv3 is the best license during active development, and
the ISC is the best license once higan is officially discontinued.
Considerations
--------------
This is the part that should concern you as a contributor: I am not requesting
contributed source code to be released under the ISC so that I personally may
sell GPLv3 commercial license exemptions to your work, but in the future when
higan is released under the ISC license, that will open the door for anyone to
sell the work commercially in a closed source form.
If this is not acceptable to you, I wholly understand and I welcome you to
release your work under the GPLv3 in the form of a higan fork. And if your work
is not an essential part of the core emulation -- that is to say, it may be
optionally disabled -- then I am still willing to work with you in merging such
work upstream anyway under the full GPLv3 license, but please reach out to me
first before developing under the assumption your work will be merged upstream.
Thank you very much for reading and hopefully for your understanding.
-55
View File
@@ -1,55 +0,0 @@
higan was created and is maintained by byuu (Near), but many people have contributed to the project.
This software would not be where it is today without the help and support of the following individuals:
- Andreas Naive
- Ange Albertini
- anomie
- AWJ
- Bisqwit
- blargg
- Łukasz Krawczyk
- Danish
- DerKoun
- DMV27
- Dr. Decapitator
- endrift
- Fatbag
- FitzRoy
- gekkio
- GIGO
- Hendricks266
- hex_usr
- ikari_01
- jchadwick
- Jonas Quinn
- kode54
- krom
- Lioncash
- Lord Nightmare
- lowkey
- Matthew Callis
- Max833
- MerryMage
- mightymo
- Nach
- ncbncb
- neviksti
- OV2
- Overload
- p4plus2
- quequotion
- RedDwarf
- Richard Bannister
- Ryphecha
- segher
- Sintendo
- SuperMikeMan
- Talarubi
- tetsuo55
- TmEE
- TRAC
- wareya
- zones
If your contributions have been missed here, please reach out [here](https://byuu.org/contact) to have this corrected, thank you!
-674
View File
@@ -1,674 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
-45
View File
@@ -1,45 +0,0 @@
----------------------------------------------------------------------
higan - Suite of videogame emulators
icarus - Game library importer for higan
genius - Game database editor for higan
Copyright © 2004-2019 byuu
https://byuu.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, specifically version 3 of the License
and no other version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
----------------------------------------------------------------------
----------------------------------------------------------------------
libco - C cooperative threading library
nall - C++ template library
ruby - Hardware abstraction library
hiro - User interface library
Copyright © 2006-2019 byuu
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 MERCHANTABILITY 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.
----------------------------------------------------------------------
-60
View File
@@ -1,60 +0,0 @@
higan
=====
![higan logo © byuu](https://byuu.org/images/higan/github/byuu-higan-logo.png)
higan is a multi-system emulator from [byuu](https://byuu.org/about) with an
uncompromising focus on accuracy and code readability.
It is a research project meant to improve all emulators through open source
collaboration, and as such is not meant to be used as a standard emulator for
playing games (although it can be used as such with some patience.)
Testing is greatly appreciated so that the emulation quality can be improved.
Such improvements will migrate downstream to user-focused emulators such as
bsnes.
It currently emulates the following systems: Famicom, Famicom Disk System,
Super Famicom, Super Game Boy, Game Boy, Game Boy Color, Game Boy Advance,
Game Boy Player, SG-1000, SC-3000, Master System, Game Gear, Mega Drive,
Mega CD, PC Engine, SuperGrafx, MSX, MSX2, ColecoVision, Neo Geo Pocket,
Neo Geo Pocket Color, WonderSwan, WonderSwan Color, SwanCrystal,
Pocket Challenge V2.
Development
-----------
Git is used for the development of new releases, and represents a staging
environment. As higan is rather mature, things should generally be quite stable.
However, bugs will exist, regressions will occur, so proceed at your own risk.
If stability is required, please download the latest stable release from the
[official website.](https://byuu.org/higan)
Links
-----
- [Official website](https://byuu.org/higan)
- [Official git repository](https://github.com/byuu/higan)
- [Donations](https://patreon.com/byuu)
Release Builds
--------------
- [Windows binaries](https://byuu.itch.io/higan)
Nightly Builds
--------------
- [Download](https://cirrus-ci.com/github/byuu/higan/master)
- ![Build status](https://api.cirrus-ci.com/github/byuu/higan.svg?task=windows-x86_64-binaries)
- ![Build status](https://api.cirrus-ci.com/github/byuu/higan.svg?task=macOS-x86_64-binaries)
- ![Build status](https://api.cirrus-ci.com/github/byuu/higan.svg?task=linux-x86_64-binaries)
- ![Build status](https://api.cirrus-ci.com/github/byuu/higan.svg?task=freebsd-x86_64-binaries)
Preview
-------
![higan user interface © byuu](https://byuu.org/images/higan/github/byuu-higan-user-interface.png)
![higan running Bahamut Lagoon (SNES) © byuu](https://byuu.org/images/higan/github/byuu-higan-bahamut-lagoon.png)
![higan running Riviera (GBA) © byuu](https://byuu.org/images/higan/github/byuu-higan-riviera.png)
+43
View File
@@ -0,0 +1,43 @@
CC = cl
CFLAGS = /nologo /O2
OBJS = main.obj timing.obj g65816.obj d65816.obj spc700.obj dspc700.obj memory.obj mmio.obj bridge.obj gui.obj libstr.obj
LIBS = kernel32.lib user32.lib gdi32.lib comdlg32.lib ddraw.lib
all: $(OBJS)
$(CC) /Febsnes.exe $(CFLAGS) $(OBJS) $(LIBS)
clean:
del *.obj
main.obj: main.cpp main.h
$(CC) $(CFLAGS) /c main.cpp
timing.obj: timing/timing.cpp timing/timing.h
$(CC) $(CFLAGS) /c timing/timing.cpp
g65816.obj: cpu/g65816*.cpp cpu/g65816.h
$(CC) $(CFLAGS) /c cpu/g65816.cpp
d65816.obj: cpu/d65816.cpp
$(CC) $(CFLAGS) /c cpu/d65816.cpp
spc700.obj: apu/spc700*.cpp apu/spc700*.h
$(CC) $(CFLAGS) /c apu/spc700.cpp
dspc700.obj: apu/dspc700.cpp
$(CC) $(CFLAGS) /c apu/dspc700.cpp
memory.obj: mem/memory.cpp
$(CC) $(CFLAGS) /c mem/memory.cpp
mmio.obj: ppu/mmio.cpp ppu/ppu*.cpp
$(CC) $(CFLAGS) /c ppu/mmio.cpp
bridge.obj: bridge/bridge.cpp bridge/bridge.h
$(CC) $(CFLAGS) /c bridge/bridge.cpp
gui.obj: win/gui*.cpp win/render*.cpp
$(CC) $(CFLAGS) /c win/gui.cpp
libstr.obj: misc/libstr.cpp
$(CC) $(CFLAGS) /c misc/libstr.cpp
+314
View File
@@ -0,0 +1,314 @@
#include "../base.h"
#include "spc700.h"
extern sony_spc700 *spc700;
extern debugstate debugger;
char __disas_spc700_str[256];
word __disas_spc700_relb(byte arg, byte offset) {
word r = spc700->regs.pc + (signed char)arg;
r += offset;
return r;
}
void __disas_spc700_op(byte op, byte op0, byte op1) {
char *s = (char*)__disas_spc700_str;
word opw = (op1 << 8) | (op0);
switch(op) {
case 0x00:sprintf(s, "nop");break;
case 0x01:sprintf(s, "tcall 0");break;
case 0x02:sprintf(s, "set0 $%0.2x", op0);break;
case 0x03:sprintf(s, "bbs0 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0x04:sprintf(s, "or a,$%0.2x", op0);break;
case 0x05:sprintf(s, "or a,$%0.4x", opw);break;
case 0x06:sprintf(s, "or a,(x)");break;
case 0x07:sprintf(s, "or a,($%0.2x+x)", op0);break;
case 0x08:sprintf(s, "or a,#$%0.2x", op0);break;
case 0x09:sprintf(s, "or ($%0.2x),($%0.2x)", op1, op0);break;
case 0x0a:sprintf(s, "or1 c,$%0.4x,%d", opw & 0x1fff, opw >> 13);break;
case 0x0b:sprintf(s, "asl $%0.2x", op0);break;
case 0x0c:sprintf(s, "mov $%0.4x,y", opw);break;
case 0x0d:sprintf(s, "push psw");break;
case 0x0e:sprintf(s, "tset1 $%0.4x", opw);break;
case 0x0f:sprintf(s, "brk");break;
case 0x10:sprintf(s, "bpl $%0.4x", __disas_spc700_relb(op0, 2));break;
case 0x11:sprintf(s, "tcall 1");break;
case 0x12:sprintf(s, "clr0 $%0.2x", op0);break;
case 0x13:sprintf(s, "bbc0 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0x14:sprintf(s, "or a,$%0.2x+x", op0);break;
case 0x15:sprintf(s, "or a,$%0.4x+x", opw);break;
case 0x16:sprintf(s, "or a,$%0.4x+y", opw);break;
case 0x17:sprintf(s, "or a,($%0.2x)+y", op0);break;
case 0x18:sprintf(s, "or $%0.2x,#$%0.2x", op1, op0);break;
case 0x19:sprintf(s, "or (x),(y)");break;
case 0x1a:sprintf(s, "decw $%0.2x", op0);break;
case 0x1b:sprintf(s, "asl $%0.2x+x", op0);break;
case 0x1c:sprintf(s, "asl a");break;
case 0x1d:sprintf(s, "dec x");break;
case 0x1e:sprintf(s, "cmp x,$%0.4x", opw);break;
case 0x1f:sprintf(s, "jmp ($%0.4x+x)", opw);break;
case 0x20:sprintf(s, "clrp");break;
case 0x21:sprintf(s, "tcall 2");break;
case 0x22:sprintf(s, "set1 $%0.2x", op0);break;
case 0x23:sprintf(s, "bbs1 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0x24:sprintf(s, "and a,$%0.2x", op0);break;
case 0x25:sprintf(s, "and a,$%0.4x", opw);break;
case 0x26:sprintf(s, "and a,(x)", op0);break;
case 0x27:sprintf(s, "and a,($%0.2x+x)", op0);break;
case 0x28:sprintf(s, "and a,#$%0.2x", op0);break;
case 0x29:sprintf(s, "and ($%0.2x),($%0.2x)", op1, op0);break;
case 0x2a:sprintf(s, "or1 c,!$%0.4x,%d", opw & 0x1fff, opw >> 13);break;
case 0x2b:sprintf(s, "rol $%0.2x", op0);break;
case 0x2c:sprintf(s, "rol $%0.4x", opw);break;
case 0x2d:sprintf(s, "push a");break;
case 0x2e:sprintf(s, "cbne $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0x2f:sprintf(s, "bra $%0.4x", __disas_spc700_relb(op0, 2));break;
case 0x30:sprintf(s, "bmi $%0.4x", __disas_spc700_relb(op0, 2));break;
case 0x31:sprintf(s, "tcall 3");break;
case 0x32:sprintf(s, "clr1 $%0.2x", op0);break;
case 0x33:sprintf(s, "bbc1 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0x34:sprintf(s, "and a,$%0.2x+x", op0);break;
case 0x35:sprintf(s, "and a,$%0.4x+x", opw);break;
case 0x36:sprintf(s, "and a,$%0.4x+y", opw);break;
case 0x37:sprintf(s, "and a,($%0.2x)+y", op0);break;
case 0x38:sprintf(s, "and $%0.2x,#$%0.2x", op1, op0);break;
case 0x39:sprintf(s, "and (x),(y)");break;
case 0x3a:sprintf(s, "incw $%0.2x", op0);break;
case 0x3b:sprintf(s, "rol $%0.2x+x", op0);break;
case 0x3c:sprintf(s, "rol a");break;
case 0x3d:sprintf(s, "inc x");break;
case 0x3e:sprintf(s, "cmp x,$%0.2x", op0);break;
case 0x3f:sprintf(s, "call $%0.4x", opw);break;
case 0x40:sprintf(s, "setp");break;
case 0x41:sprintf(s, "tcall 4");break;
case 0x42:sprintf(s, "set2 $%0.2x", op0);break;
case 0x43:sprintf(s, "bbs2 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0x44:sprintf(s, "eor a,$%0.2x", op0);break;
case 0x45:sprintf(s, "eor a,$%0.4x", opw);break;
case 0x46:sprintf(s, "eor a,(x)");break;
case 0x47:sprintf(s, "eor a,($%0.2x+x)", op0);break;
case 0x48:sprintf(s, "eor a,#$%0.2x", op0);break;
case 0x49:sprintf(s, "eor ($%0.2x),($%0.2x)", op1, op0);break;
case 0x4a:sprintf(s, "and1 c,$%0.4x,%d", opw & 0x1fff, opw >> 13);break;
case 0x4b:sprintf(s, "lsr $%0.2x", op0);break;
case 0x4c:sprintf(s, "lsr $%0.4x", opw);break;
case 0x4d:sprintf(s, "push x");break;
case 0x4e:sprintf(s, "tclr1 $%0.4x", opw);break;
case 0x4f:sprintf(s, "pcall $%0.2x", op0);break;
case 0x50:sprintf(s, "bvc $%0.4x", __disas_spc700_relb(op0, 2));break;
case 0x51:sprintf(s, "tcall 5");break;
case 0x52:sprintf(s, "clr2 $%0.2x", op0);break;
case 0x53:sprintf(s, "bbc2 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0x54:sprintf(s, "eor a,$%0.2x+x", op0);break;
case 0x55:sprintf(s, "eor a,$%0.4x+x", opw);break;
case 0x56:sprintf(s, "eor a,$%0.4x+y", opw);break;
case 0x57:sprintf(s, "eor a,($%0.2x)+y", op0);break;
case 0x58:sprintf(s, "eor $%0.2x,#$%0.2x", op1, op0);break;
case 0x59:sprintf(s, "eor (x),(y)", op0);break;
case 0x5a:sprintf(s, "cmpw ya,$%0.2x", op0);break;
case 0x5b:sprintf(s, "lsr $%0.2x+x", op0);break;
case 0x5c:sprintf(s, "lsr a");break;
case 0x5d:sprintf(s, "mov x,a");break;
case 0x5e:sprintf(s, "cmp y,$%0.4x", opw);break;
case 0x5f:sprintf(s, "jmp $%0.4x", opw);break;
case 0x60:sprintf(s, "clrc");break;
case 0x61:sprintf(s, "tcall 6");break;
case 0x62:sprintf(s, "set3 $%0.2x", op0);break;
case 0x63:sprintf(s, "bbs3 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0x64:sprintf(s, "cmp a,$%0.2x", op0);break;
case 0x65:sprintf(s, "cmp a,$%0.4x", opw);break;
case 0x66:sprintf(s, "cmp a,(x)", op0);break;
case 0x67:sprintf(s, "cmp a,($%0.2x+x)", op0);break;
case 0x68:sprintf(s, "cmp a,#$%0.2x", op0);break;
case 0x69:sprintf(s, "cmp ($%0.2x),($%0.2x)", op1, op0);break;
case 0x6a:sprintf(s, "and1 c,!$%0.4x,%d", opw & 0x1fff, opw >> 13);break;
case 0x6b:sprintf(s, "ror $%0.2x", op0);break;
case 0x6c:sprintf(s, "ror $%0.4x", opw);break;
case 0x6d:sprintf(s, "push y");break;
case 0x6e:sprintf(s, "dbnz $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0x6f:sprintf(s, "ret");break;
case 0x70:sprintf(s, "bvs $%0.4x", __disas_spc700_relb(op0, 2));break;
case 0x71:sprintf(s, "tcall 7");break;
case 0x72:sprintf(s, "clr3 $%0.2x", op0);break;
case 0x73:sprintf(s, "bbc3 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0x74:sprintf(s, "cmp a,$%0.2x+x", op0);break;
case 0x75:sprintf(s, "cmp a,$%0.4x+x", opw);break;
case 0x76:sprintf(s, "cmp a,$%0.4x+y", opw);break;
case 0x77:sprintf(s, "cmp a,($%0.2x)+y", op0);break;
case 0x78:sprintf(s, "cmp $%0.2x,#$%0.2x", op1, op0);break;
case 0x79:sprintf(s, "cmp (x),(y)");break;
case 0x7a:sprintf(s, "addw ya,$%0.2x", op0);break;
case 0x7b:sprintf(s, "ror $%0.2x+x", op0);break;
case 0x7c:sprintf(s, "ror a");break;
case 0x7d:sprintf(s, "mov a,x");break;
case 0x7e:sprintf(s, "cmp y,$%0.2x", op0);break;
case 0x7f:sprintf(s, "reti");break;
case 0x80:sprintf(s, "setc");break;
case 0x81:sprintf(s, "tcall 8");break;
case 0x82:sprintf(s, "set4 $%0.2x", op0);break;
case 0x83:sprintf(s, "bbs4 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0x84:sprintf(s, "adc a,$%0.2x", op0);break;
case 0x85:sprintf(s, "adc a,$%0.4x", opw);break;
case 0x86:sprintf(s, "adc a,(x)", op0);break;
case 0x87:sprintf(s, "adc a,($%0.2x+x)", op0);break;
case 0x88:sprintf(s, "adc a,#$%0.2x", op0);break;
case 0x89:sprintf(s, "adc ($%0.2x),($%0.2x)", op1, op0);break;
case 0x8a:sprintf(s, "eor1 c,$%0.4x,%d", opw & 0x1fff, opw >> 13);break;
case 0x8b:sprintf(s, "dec $%0.2x", op0);break;
case 0x8c:sprintf(s, "dec $%0.4x", opw);break;
case 0x8d:sprintf(s, "mov y,#$%0.2x", op0);break;
case 0x8e:sprintf(s, "pop psw");break;
case 0x8f:sprintf(s, "mov $%0.2x,#$%0.2x", op1, op0);break;
case 0x90:sprintf(s, "bcc $%0.4x", __disas_spc700_relb(op0, 2));break;
case 0x91:sprintf(s, "tcall 9");break;
case 0x92:sprintf(s, "clr4 $%0.2x", op0);break;
case 0x93:sprintf(s, "bbc4 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0x94:sprintf(s, "adc a,$%0.2x+x", op0);break;
case 0x95:sprintf(s, "adc a,$%0.4x+x", opw);break;
case 0x96:sprintf(s, "adc a,$%0.4x+y", opw);break;
case 0x97:sprintf(s, "adc a,($%0.2x)+y", op0);break;
case 0x98:sprintf(s, "adc $%0.2x,#$%0.2x", op1, op0);break;
case 0x99:sprintf(s, "adc (x),(y)", op0);break;
case 0x9a:sprintf(s, "subw ya,$%0.2x", op0);break;
case 0x9b:sprintf(s, "dec $%0.2x+x", op0);break;
case 0x9c:sprintf(s, "dec a");break;
case 0x9d:sprintf(s, "mov x,sp");break;
case 0x9e:sprintf(s, "div ya,x");break;
case 0x9f:sprintf(s, "xcn a");break;
case 0xa0:sprintf(s, "ei");break;
case 0xa1:sprintf(s, "tcall 10");break;
case 0xa2:sprintf(s, "set5 $%0.2x", op0);break;
case 0xa3:sprintf(s, "bbs5 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0xa4:sprintf(s, "sbc a,$%0.2x", op0);break;
case 0xa5:sprintf(s, "sbc a,$%0.4x", opw);break;
case 0xa6:sprintf(s, "sbc a,(x)", op0);break;
case 0xa7:sprintf(s, "sbc a,($%0.2x+x)", op0);break;
case 0xa8:sprintf(s, "sbc a,#$%0.2x", op0);break;
case 0xa9:sprintf(s, "sbc ($%0.2x),($%0.2x)", op1, op0);break;
case 0xaa:sprintf(s, "mov1 c,$%0.4x,%d", opw & 0x1fff, opw >> 13);break;
case 0xab:sprintf(s, "inc $%0.2x", op0);break;
case 0xac:sprintf(s, "inc $%0.4x", opw);break;
case 0xad:sprintf(s, "cmp y,#$%0.2x", op0);break;
case 0xae:sprintf(s, "pop a");break;
case 0xaf:sprintf(s, "mov (x)+,a");break;
case 0xb0:sprintf(s, "bcs $%0.4x", __disas_spc700_relb(op0, 2));break;
case 0xb1:sprintf(s, "tcall 11");break;
case 0xb2:sprintf(s, "clr5 $%0.2x", op0);break;
case 0xb3:sprintf(s, "bbc5 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0xb4:sprintf(s, "sbc a,$%0.2x+x", op0);break;
case 0xb5:sprintf(s, "sbc a,$%0.4x+x", opw);break;
case 0xb6:sprintf(s, "sbc a,$%0.4x+y", opw);break;
case 0xb7:sprintf(s, "sbc a,($%0.2x)+y", op0);break;
case 0xb8:sprintf(s, "sbc $%0.2x,#$%0.2x", op1, op0);break;
case 0xb9:sprintf(s, "sbc (x),(y)", op0);break;
case 0xba:sprintf(s, "movw ya,$%0.2x", op0);break;
case 0xbb:sprintf(s, "inc $%0.2x+x", op0);break;
case 0xbc:sprintf(s, "inc a");break;
case 0xbd:sprintf(s, "mov sp,x");break;
case 0xbe:sprintf(s, "das a");break;
case 0xbf:sprintf(s, "mov a,(x)+");break;
case 0xc0:sprintf(s, "di");break;
case 0xc1:sprintf(s, "tcall 12");break;
case 0xc2:sprintf(s, "set6 $%0.2x", op0);break;
case 0xc3:sprintf(s, "bbs6 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0xc4:sprintf(s, "mov $%0.2x,a", op0);break;
case 0xc5:sprintf(s, "mov $%0.4x,a", opw);break;
case 0xc6:sprintf(s, "mov (x),a");break;
case 0xc7:sprintf(s, "mov ($%0.2x+x),a", op0);break;
case 0xc8:sprintf(s, "cmp x,#$%0.2x", op0);break;
case 0xc9:sprintf(s, "mov $%0.4x,x", opw);break;
case 0xca:sprintf(s, "mov1 $%0.4x,%d,c", opw & 0x1fff, opw >> 13);break;
case 0xcb:sprintf(s, "mov $%0.2x,y", op0);break;
case 0xcc:sprintf(s, "asl $%0.4x", opw);break;
case 0xcd:sprintf(s, "mov x,#$%0.2x", op0);break;
case 0xce:sprintf(s, "pop x");break;
case 0xcf:sprintf(s, "mul ya");break;
case 0xd0:sprintf(s, "bne $%0.4x", __disas_spc700_relb(op0, 2));break;
case 0xd1:sprintf(s, "tcall 13");break;
case 0xd2:sprintf(s, "clr6 $%0.2x", op0);break;
case 0xd3:sprintf(s, "bbc6 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0xd4:sprintf(s, "mov $%0.2x+x,a", op0);break;
case 0xd5:sprintf(s, "mov $%0.4x+x,a", opw);break;
case 0xd6:sprintf(s, "mov $%0.4x+y,a", opw);break;
case 0xd7:sprintf(s, "mov ($%0.2x)+y,a", op0);break;
case 0xd8:sprintf(s, "mov $%0.2x,x", op0);break;
case 0xd9:sprintf(s, "mov $%0.2x+y,x", op0);break;
case 0xda:sprintf(s, "movw $%0.2x,ya", op0);break;
case 0xdb:sprintf(s, "mov $%0.2x+x,y", op0);break;
case 0xdc:sprintf(s, "dec y");break;
case 0xdd:sprintf(s, "mov a,y");break;
case 0xde:sprintf(s, "cbne $%0.2x+x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0xdf:sprintf(s, "daa a");break;
case 0xe0:sprintf(s, "clrv");break;
case 0xe1:sprintf(s, "tcall 14");break;
case 0xe2:sprintf(s, "set7 $%0.2x", op0);break;
case 0xe3:sprintf(s, "bbs7 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0xe4:sprintf(s, "mov a,$%0.2x", op0);break;
case 0xe5:sprintf(s, "mov a,$%0.4x", opw);break;
case 0xe6:sprintf(s, "mov a,(x)");break;
case 0xe7:sprintf(s, "mov a,($%0.2x+x)", op0);break;
case 0xe8:sprintf(s, "mov a,#$%0.2x", op0);break;
case 0xe9:sprintf(s, "mov x,$%0.4x", opw);break;
case 0xea:sprintf(s, "not1 $%0.4x,%d", opw & 0x1fff, opw >> 13);break;
case 0xeb:sprintf(s, "mov y,$%0.2x", op0);break;
case 0xec:sprintf(s, "mov y,$%0.4x", opw);break;
case 0xed:sprintf(s, "notc");break;
case 0xee:sprintf(s, "pop y");break;
case 0xef:sprintf(s, "sleep");break;
case 0xf0:sprintf(s, "beq $%0.4x", __disas_spc700_relb(op0, 2));break;
case 0xf1:sprintf(s, "tcall 15");break;
case 0xf2:sprintf(s, "clr7 $%0.2x", op0);break;
case 0xf3:sprintf(s, "bbc7 $%0.2x,$%0.4x", op0, __disas_spc700_relb(op1, 3));break;
case 0xf4:sprintf(s, "mov a,$%0.2x+x", op0);break;
case 0xf5:sprintf(s, "mov a,$%0.4x+x", opw);break;
case 0xf6:sprintf(s, "mov a,$%0.4x+y", opw);break;
case 0xf7:sprintf(s, "mov a,($%0.2x)+y", op0);break;
case 0xf8:sprintf(s, "mov x,$%0.2x", op0);break;
case 0xf9:sprintf(s, "mov x,$%0.2x+y", op0);break;
case 0xfa:sprintf(s, "mov ($%0.2x),($%0.2x)", op1, op0);break;
case 0xfb:sprintf(s, "mov y,$%0.2x+x", op0);break;
case 0xfc:sprintf(s, "inc y");break;
case 0xfd:sprintf(s, "mov y,a");break;
case 0xfe:sprintf(s, "dbnz y,$%0.4x", __disas_spc700_relb(op0, 2));break;
case 0xff:sprintf(s, "stop");break;
}
}
void disas_spc700_op(void) {
byte op;
byte op0, op1;
word offset;
char flags[256];
char *s = (char*)__disas_spc700_str;
int i;
if(debug_write_status() == DEBUGWRITE_NONE)return;
//use offset instead of spc700->regs.pc + n to avoid going above 65535
offset = spc700->regs.pc;
op = spc700->ram[offset++];
op0 = spc700->ram[offset++];
op1 = spc700->ram[offset ];
strcpy(__disas_spc700_str, "???");
__disas_spc700_op(op, op0, op1);
i = strlen(s);
while(i < 23) {
s[i++] = ' ';
s[i] = 0;
}
sprintf(flags, "%c%c%c%c%c%c%c%c",
(spc700->regs.p & 0x80)?'N':'n',
(spc700->regs.p & 0x40)?'V':'v',
(spc700->regs.p & 0x20)?'P':'p',
(spc700->regs.p & 0x10)?'B':'b',
(spc700->regs.p & 0x08)?'H':'h',
(spc700->regs.p & 0x04)?'I':'i',
(spc700->regs.p & 0x02)?'Z':'z',
(spc700->regs.p & 0x01)?'C':'c');
dprintf(DEBUGMSG_APU, "--%0.4x %s A:%0.2x X:%0.2x Y:%0.2x SP:%0.2x YA:%0.4x %s",
spc700->regs.pc, __disas_spc700_str,
spc700->regs.a, spc700->regs.x, spc700->regs.y, spc700->regs.sp,
(spc700->regs.y << 8) | (spc700->regs.a), flags);
}
+49
View File
@@ -0,0 +1,49 @@
#include "../base.h"
#include "../timing/timing.h"
#include "../bridge/bridge.h"
#include "spc700_iplrom.h"
#include "spc700.h"
extern snes_timer *snes_time;
extern debugstate debugger;
extern port_bridge *cpu_apu_bridge;
sony_spc700 *spc700;
#include "spc700_ops.cpp"
void sony_spc700::Reset(void) {
memset(ram, 0, 65536);
memcpy(ram + 0xffc0, spc700_iplrom, 64);
regs.pc = 0xffc0;
regs.a = regs.x = regs.y = regs.sp = 0x00;
regs.p = 0x02;
regs.dp = 0x0000;
}
void sony_spc700::exec_op(void) {
byte op;
op = spc700->ram[spc700->regs.pc];
spc700_optbl[op]();
debugger.apu_op_executed = true;
debugger.disas_apu_op = true;
debug_test_bp(BPSRC_SPCRAM, BP_EXEC, spc700->regs.pc, 0);
}
void sony_spc700::Run(void) {
if(snes_time->bridge.cpu_cycles >= snes_time->bridge.apu_cycles) {
exec_op();
}
if(snes_time->bridge.cpu_cycles >= 65536 && snes_time->bridge.apu_cycles >= 65536) {
snes_time->bridge.cpu_cycles &= 65535;
snes_time->bridge.apu_cycles &= 65535;
}
}
sony_spc700::sony_spc700() {
ram = (byte*)malloc(65536);
}
sony_spc700::~sony_spc700() {
if(ram)free(ram);
}
+24
View File
@@ -0,0 +1,24 @@
class sony_spc700 {
public:
struct {
word pc;
byte a, x, y, sp, p;
word dp;
}regs;
byte *ram;
void Reset(void);
void Run(void);
void exec_op(void);
word convert_address(byte mode, word addr);
byte mem_getbyte(word addr);
void mem_putbyte(word addr, byte value);
word mem_read(byte mode, byte size, word addr);
void mem_write(byte mode, byte size, word addr, word value);
byte stack_read(void);
void stack_write(byte value);
sony_spc700();
~sony_spc700();
};
+35
View File
@@ -0,0 +1,35 @@
byte spc700_iplrom[64] = {
/*ffc0*/ 0xcd, 0xef, //mov x,#$ef
/*ffc2*/ 0xbd, //mov sp,x
/*ffc3*/ 0xe8, 0x00, //mov a,#$00
/*ffc5*/ 0xc6, //mov (x),a
/*ffc6*/ 0x1d, //dec x
/*ffc7*/ 0xd0, 0xfc, //bne $ffc5
/*ffc9*/ 0x8f, 0xaa, 0xf4, //mov $f4,#$aa
/*ffcc*/ 0x8f, 0xbb, 0xf5, //mov $f5,#$bb
/*ffcf*/ 0x78, 0xcc, 0xf4, //cmp $f4,#$cc
/*ffd2*/ 0xd0, 0xfb, //bne $ffcf
/*ffd4*/ 0x2f, 0x19, //bra $ffef
/*ffd6*/ 0xeb, 0xf4, //mov y,$f4
/*ffd8*/ 0xd0, 0xfc, //bne $ffd6
/*ffda*/ 0x7e, 0xf4, //cmp y,$f4
/*ffdc*/ 0xd0, 0x0b, //bne $ffe9
/*ffde*/ 0xe4, 0xf5, //mov a,$f5
/*ffe0*/ 0xcb, 0xf4, //mov $f4,y
/*ffe2*/ 0xd7, 0x00, //mov ($00)+y,a
/*ffe4*/ 0xfc, //inc y
/*ffe5*/ 0xd0, 0xf3, //bne $ffda
/*ffe7*/ 0xab, 0x01, //inc $01
/*ffe9*/ 0x10, 0xef, //bpl $ffda
/*ffeb*/ 0x7e, 0xf4, //cmp y,$f4
/*ffed*/ 0x10, 0xeb, //bpl $ffda
/*ffef*/ 0xba, 0xf6, //movw ya,$f6
/*fff1*/ 0xda, 0x00, //movw $00,ya
/*fff3*/ 0xba, 0xf4, //movw ya,$f4
/*fff5*/ 0xc4, 0xf4, //mov $f4,a
/*fff7*/ 0xdd, //mov a,y
/*fff8*/ 0x5d, //mov x,a
/*fff9*/ 0xd0, 0xdb, //bne $ffd6
/*fffb*/ 0x1f, 0x00, 0x00, //jmp ($0000+x)
/*fffe*/ 0xc0, 0xff //---reset vector location ($ffc0)
};
+194
View File
@@ -0,0 +1,194 @@
#define spc700_setn() spc700->regs.p |= SPF_N
#define spc700_clrn() spc700->regs.p &= ~SPF_N
#define spc700_setv() spc700->regs.p |= SPF_V
#define spc700_clrv() spc700->regs.p &= ~SPF_V
#define spc700_setp() spc700->regs.p |= SPF_P;spc700->regs.dp = 0x0100
#define spc700_clrp() spc700->regs.p &= ~SPF_P;spc700->regs.dp = 0x0000
#define spc700_setb() spc700->regs.p |= SPF_B
#define spc700_clrb() spc700->regs.p &= ~SPF_B
#define spc700_seth() spc700->regs.p |= SPF_H
#define spc700_clrh() spc700->regs.p &= ~SPF_H
#define spc700_seti() spc700->regs.p |= SPF_I
#define spc700_clri() spc700->regs.p &= ~SPF_I
#define spc700_setz() spc700->regs.p |= SPF_Z
#define spc700_clrz() spc700->regs.p &= ~SPF_Z
#define spc700_setc() spc700->regs.p |= SPF_C
#define spc700_clrc() spc700->regs.p &= ~SPF_C
#define spc700_testn(x) if(x)spc700_setn(); else spc700_clrn()
#define spc700_testv(x) if(x)spc700_setv(); else spc700_clrv()
#define spc700_testp(x) if(x)spc700_setp(); else spc700_clrp()
#define spc700_testb(x) if(x)spc700_setb(); else spc700_clrb()
#define spc700_testh(x) if(x)spc700_seth(); else spc700_clrh()
#define spc700_testi(x) if(x)spc700_seti(); else spc700_clri()
#define spc700_testz(x) if(x)spc700_setz(); else spc700_clrz()
#define spc700_testc(x) if(x)spc700_setc(); else spc700_clrc()
#define spc700_incpc(__n) spc700->regs.pc += __n
#define spc700_prefetchb() \
byte arg = spc700->ram[(spc700->regs.pc + 1) & 0xffff]
#define spc700_prefetch2b() \
byte arg0 = spc700->ram[(spc700->regs.pc + 1) & 0xffff]; \
byte arg1 = spc700->ram[(spc700->regs.pc + 2) & 0xffff]
#define spc700_prefetchw() \
word arg = spc700->ram[(spc700->regs.pc + 1) & 0xffff] | (spc700->ram[(spc700->regs.pc + 2) & 0xffff] << 8)
#define APUMODE_NONE 0
#define APUMODE_DP 1
#define APUMODE_DPX 2
#define APUMODE_DPY 3
#define APUMODE_IDP 4
#define APUMODE_ADDR 5
#define APUMODE_IX 6
#define APUMODE_ADDRX 7
#define APUMODE_ADDRY 8
#define APUMODE_IDPX 9
#define APUMODE_IDPY 10
#define APUMODE_IADDRX 11
#define APUMODE_IY 12
word sony_spc700::convert_address(byte mode, word addr) {
word r;
switch(mode) {
case APUMODE_NONE:
r = addr;
case APUMODE_DP:
r = spc700->regs.dp | (byte)addr;
break;
case APUMODE_DPX:
r = spc700->regs.dp | (byte)(addr + spc700->regs.x);
break;
case APUMODE_DPY:
r = spc700->regs.dp | (byte)(addr + spc700->regs.y);
break;
case APUMODE_IDP:
r = spc700->regs.dp | (byte)addr;
r = spc700->ram[r] | (spc700->ram[r + 1] << 8);
break;
case APUMODE_ADDR:
r = addr;
break;
case APUMODE_IX:
r = spc700->regs.dp | spc700->regs.x;
break;
case APUMODE_ADDRX:
r = addr + spc700->regs.x;
break;
case APUMODE_ADDRY:
r = addr + spc700->regs.y;
break;
case APUMODE_IDPX:
r = spc700->regs.dp | (byte)(addr + spc700->regs.x);
r = spc700->ram[r] | (spc700->ram[r + 1] << 8);
break;
case APUMODE_IDPY:
r = spc700->regs.dp | (byte)addr;
r = spc700->ram[r] | (spc700->ram[r + 1] << 8);
r += spc700->regs.y;
break;
case APUMODE_IADDRX:
r = (spc700->ram[(addr + spc700->regs.x )]) |
(spc700->ram[(addr + spc700->regs.x + 1)] << 8);
break;
case APUMODE_IY:
r = spc700->regs.dp | spc700->regs.y;
break;
}
return r;
}
byte sony_spc700::mem_getbyte(word addr) {
if(addr >= 0x00f4 && addr <= 0x00f7) {
return cpu_apu_bridge->apu_read(addr - 0x00f4);
} else {
return spc700->ram[addr];
}
}
void sony_spc700::mem_putbyte(word addr, byte value) {
if(addr >= 0x00f4 && addr <= 0x00f7) {
cpu_apu_bridge->apu_write(addr - 0x00f4, value);
} else if(addr < 0xffc0) {
spc700->ram[addr] = value;
}
}
word sony_spc700::mem_read(byte mode, byte size, word addr) {
word r;
addr = convert_address(mode, addr);
switch(size) {
case MEMSIZE_BYTE:
r = mem_getbyte(addr);
break;
case MEMSIZE_WORD:
r = mem_getbyte(addr) | (mem_getbyte(addr + 1) << 8);
break;
}
return r;
}
void sony_spc700::mem_write(byte mode, byte size, word addr, word value) {
addr = convert_address(mode, addr);
switch(size) {
case MEMSIZE_BYTE:
mem_putbyte(addr, value);
break;
case MEMSIZE_WORD:
mem_putbyte(addr , value);
mem_putbyte(addr + 1, value >> 8);
break;
}
}
byte sony_spc700::stack_read(void) {
word addr;
spc700->regs.sp++;
addr = 0x0100 | spc700->regs.sp;
return mem_getbyte(addr);
}
void sony_spc700::stack_write(byte value) {
word addr;
addr = 0x0100 | spc700->regs.sp;
spc700->regs.sp--;
mem_putbyte(addr, value);
}
#include "spc700_ops_adc.cpp"
#include "spc700_ops_and.cpp"
#include "spc700_ops_cmp.cpp"
#include "spc700_ops_eor.cpp"
#include "spc700_ops_flags.cpp"
#include "spc700_ops_incdec.cpp"
#include "spc700_ops_misc.cpp"
#include "spc700_ops_mov.cpp"
#include "spc700_ops_or.cpp"
#include "spc700_ops_pc.cpp"
#include "spc700_ops_sbc.cpp"
#include "spc700_ops_shift.cpp"
#include "spc700_ops_stack.cpp"
vfunc spc700_optbl[256] = {
// -----------------------------x0, -----------------------------x1, -----------------------------x2, -----------------------------x3, -------- -----------------------------x4, -----------------------------x5, -----------------------------x6, -----------------------------x7, -------- -----------------------------x8, -----------------------------x9, -----------------------------xa, -----------------------------xb, -------- -----------------------------xc, -----------------------------xd, -----------------------------xe, -----------------------------xf,
/* 0x */ spc700_op_nop, spc700_op_tcall_0, spc700_op_set0_dp, spc700_op_bbc0, /* 0x */ spc700_op_or_a_dp, spc700_op_or_a_addr, spc700_op_or_a_ix, spc700_op_or_a_idpx, /* 0x */ spc700_op_or_a_const, spc700_op_or_dp_dp, spc700_op_or1_bit, spc700_op_asl_dp, /* 0x */ spc700_op_mov_addr_y, spc700_op_push_p, spc700_op_tset1_addr, spc700_op_brk,
/* 1x */ spc700_op_bpl, spc700_op_tcall_1, spc700_op_clr0_dp, spc700_op_bbs0, /* 1x */ spc700_op_or_a_dpx, spc700_op_or_a_addrx, spc700_op_or_a_addry, spc700_op_or_a_idpy, /* 1x */ spc700_op_or_dp_imm, spc700_op_or_ix_iy, spc700_op_decw_dp, spc700_op_asl_dpx, /* 1x */ spc700_op_asl_a, spc700_op_dec_x, spc700_op_cmp_x_addr, spc700_op_jmp_iaddrx,
/* 2x */ spc700_op_clrp, spc700_op_tcall_2, spc700_op_set1_dp, spc700_op_bbc1, /* 2x */ spc700_op_and_a_dp, spc700_op_and_a_addr, spc700_op_and_a_ix, spc700_op_and_a_idpx, /* 2x */ spc700_op_and_a_const, spc700_op_and_dp_dp, spc700_op_or1_notbit, spc700_op_rol_dp, /* 2x */ spc700_op_rol_addr, spc700_op_push_a, spc700_op_cbne_dp, spc700_op_bra,
/* 3x */ spc700_op_bmi, spc700_op_tcall_3, spc700_op_clr1_dp, spc700_op_bbs1, /* 3x */ spc700_op_and_a_dpx, spc700_op_and_a_addrx, spc700_op_and_a_addry, spc700_op_and_a_idpy, /* 3x */ spc700_op_and_dp_imm, spc700_op_and_ix_iy, spc700_op_incw_dp, spc700_op_rol_dpx, /* 3x */ spc700_op_rol_a, spc700_op_inc_x, spc700_op_cmp_x_dp, spc700_op_call,
/* 4x */ spc700_op_setp, spc700_op_tcall_4, spc700_op_set2_dp, spc700_op_bbc2, /* 4x */ spc700_op_eor_a_dp, spc700_op_eor_a_addr, spc700_op_eor_a_ix, spc700_op_eor_a_idpx, /* 4x */ spc700_op_eor_a_const, spc700_op_eor_dp_dp, spc700_op_and1_bit, spc700_op_lsr_dp, /* 4x */ spc700_op_lsr_addr, spc700_op_push_x, spc700_op_tclr1_addr, spc700_op_pcall,
/* 5x */ spc700_op_bvc, spc700_op_tcall_5, spc700_op_clr2_dp, spc700_op_bbs2, /* 5x */ spc700_op_eor_a_dpx, spc700_op_eor_a_addrx, spc700_op_eor_a_addry, spc700_op_eor_a_idpy, /* 5x */ spc700_op_eor_dp_imm, spc700_op_eor_ix_iy, spc700_op_cmpw_ya_dp, spc700_op_lsr_dpx, /* 5x */ spc700_op_lsr_a, spc700_op_mov_x_a, spc700_op_cmp_y_addr, spc700_op_jmp_addr,
/* 6x */ spc700_op_clrc, spc700_op_tcall_6, spc700_op_set3_dp, spc700_op_bbc3, /* 6x */ spc700_op_cmp_a_dp, spc700_op_cmp_a_addr, spc700_op_cmp_a_ix, spc700_op_cmp_a_idpx, /* 6x */ spc700_op_cmp_a_const, spc700_op_cmp_dp_dp, spc700_op_and1_notbit, spc700_op_ror_dp, /* 6x */ spc700_op_ror_addr, spc700_op_push_y, spc700_op_dbnz_dp, spc700_op_ret,
/* 7x */ spc700_op_bvs, spc700_op_tcall_7, spc700_op_clr3_dp, spc700_op_bbs3, /* 7x */ spc700_op_cmp_a_dpx, spc700_op_cmp_a_addrx, spc700_op_cmp_a_addry, spc700_op_cmp_a_idpy, /* 7x */ spc700_op_cmp_dp_imm, spc700_op_cmp_ix_iy, spc700_op_addw_ya_dp, spc700_op_ror_dpx, /* 7x */ spc700_op_ror_a, spc700_op_mov_a_x, spc700_op_cmp_y_dp, spc700_op_reti,
/* 8x */ spc700_op_setc, spc700_op_tcall_8, spc700_op_set4_dp, spc700_op_bbc4, /* 8x */ spc700_op_adc_a_dp, spc700_op_adc_a_addr, spc700_op_adc_a_ix, spc700_op_adc_a_idpx, /* 8x */ spc700_op_adc_a_const, spc700_op_adc_dp_dp, spc700_op_eor1_bit, spc700_op_dec_dp, /* 8x */ spc700_op_dec_addr, spc700_op_mov_y_const, spc700_op_pop_p, spc700_op_mov_dp_imm,
/* 9x */ spc700_op_bcc, spc700_op_tcall_9, spc700_op_clr4_dp, spc700_op_bbs4, /* 9x */ spc700_op_adc_a_dpx, spc700_op_adc_a_addrx, spc700_op_adc_a_addry, spc700_op_adc_a_idpy, /* 9x */ spc700_op_adc_dp_imm, spc700_op_adc_ix_iy, spc700_op_subw_ya_dp, spc700_op_dec_dpx, /* 9x */ spc700_op_dec_a, spc700_op_mov_x_sp, spc700_op_div_ya_x, spc700_op_xcn_a,
/* ax */ spc700_op_ei, spc700_op_tcall_10, spc700_op_set5_dp, spc700_op_bbc5, /* ax */ spc700_op_sbc_a_dp, spc700_op_sbc_a_addr, spc700_op_sbc_a_ix, spc700_op_sbc_a_idpx, /* ax */ spc700_op_sbc_a_const, spc700_op_sbc_dp_dp, spc700_op_mov1_c_bit, spc700_op_inc_dp, /* ax */ spc700_op_inc_addr, spc700_op_cmp_y_const, spc700_op_pop_a, spc700_op_mov_ixinc_a,
/* bx */ spc700_op_bcs, spc700_op_tcall_11, spc700_op_clr5_dp, spc700_op_bbs5, /* bx */ spc700_op_sbc_a_dpx, spc700_op_sbc_a_addrx, spc700_op_sbc_a_addry, spc700_op_sbc_a_idpy, /* bx */ spc700_op_sbc_dp_imm, spc700_op_sbc_ix_iy, spc700_op_mov_ya_dp, spc700_op_inc_dpx, /* bx */ spc700_op_inc_a, spc700_op_mov_sp_x, spc700_op_das_a, spc700_op_mov_a_ixinc,
/* cx */ spc700_op_di, spc700_op_tcall_12, spc700_op_set6_dp, spc700_op_bbc6, /* cx */ spc700_op_mov_dp_a, spc700_op_mov_addr_a, spc700_op_mov_ix_a, spc700_op_mov_idpx_a, /* cx */ spc700_op_cmp_x_const, spc700_op_mov_addr_x, spc700_op_mov1_bit_c, spc700_op_mov_dp_y, /* cx */ spc700_op_asl_addr, spc700_op_mov_x_const, spc700_op_pop_x, spc700_op_mul_ya,
/* dx */ spc700_op_bne, spc700_op_tcall_13, spc700_op_clr6_dp, spc700_op_bbs6, /* dx */ spc700_op_mov_dpx_a, spc700_op_mov_addrx_a, spc700_op_mov_addry_a, spc700_op_mov_idpy_a, /* dx */ spc700_op_mov_dp_x, spc700_op_mov_dpy_x, spc700_op_mov_dp_ya, spc700_op_mov_dpx_y, /* dx */ spc700_op_dec_y, spc700_op_mov_a_y, spc700_op_cbne_dpx, spc700_op_daa_a,
/* ex */ spc700_op_clrv, spc700_op_tcall_14, spc700_op_set7_dp, spc700_op_bbc7, /* ex */ spc700_op_mov_a_dp, spc700_op_mov_a_addr, spc700_op_mov_a_ix, spc700_op_mov_a_idpx, /* ex */ spc700_op_mov_a_const, spc700_op_mov_x_addr, spc700_op_not1_bit, spc700_op_mov_y_dp, /* ex */ spc700_op_mov_y_addr, spc700_op_notc, spc700_op_pop_y, spc700_op_sleep,
/* fx */ spc700_op_beq, spc700_op_tcall_15, spc700_op_clr7_dp, spc700_op_bbs7, /* fx */ spc700_op_mov_a_dpx, spc700_op_mov_a_addrx, spc700_op_mov_a_addry, spc700_op_mov_a_idpy, /* fx */ spc700_op_mov_x_dp, spc700_op_mov_x_dpy, spc700_op_mov_dp_dp, spc700_op_mov_y_dpx, /* fx */ spc700_op_inc_y, spc700_op_mov_y_a, spc700_op_dbnz_y, spc700_op_stop
};
+114
View File
@@ -0,0 +1,114 @@
byte spc700_op_adc(byte x, byte y) {
word r = x + y + (spc700->regs.p & SPF_C);
spc700_testn(r & 0x80);
spc700_testv((~(x ^ y) & (y ^ (byte)r) & 0x80));
spc700_testh((x ^ y ^ (byte)r) & 0x10);
spc700_testz((byte)r == 0);
spc700_testc(r >= 0x100);
return (byte)r;
}
void spc700_op_adc_a_const(void) {
spc700_prefetchb();
spc700->regs.a = spc700_op_adc(spc700->regs.a, arg);
spc700_incpc(2);
add_apu_cycles(2);
}
void spc700_op_adc_a_ix(void) {
spc700->regs.a = spc700_op_adc(spc700->regs.a, spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0));
spc700_incpc(1);
add_apu_cycles(3);
}
void spc700_op_adc_a_dp(void) {
spc700_prefetchb();
spc700->regs.a = spc700_op_adc(spc700->regs.a, spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg));
spc700_incpc(2);
add_apu_cycles(3);
}
void spc700_op_adc_a_dpx(void) {
spc700_prefetchb();
spc700->regs.a = spc700_op_adc(spc700->regs.a, spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg));
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_adc_a_addr(void) {
spc700_prefetchw();
spc700->regs.a = spc700_op_adc(spc700->regs.a, spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg));
spc700_incpc(3);
add_apu_cycles(4);
}
void spc700_op_adc_a_addrx(void) {
spc700_prefetchw();
spc700->regs.a = spc700_op_adc(spc700->regs.a, spc700->mem_read(APUMODE_ADDRX, MEMSIZE_BYTE, arg));
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_adc_a_addry(void) {
spc700_prefetchw();
spc700->regs.a += spc700->mem_read(APUMODE_ADDRY, MEMSIZE_BYTE, arg);
spc700->regs.a += (spc700->regs.p & PF_C);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_adc_a_idpx(void) {
spc700_prefetchb();
word i;
spc700->regs.a = spc700_op_adc(spc700->regs.a, spc700->mem_read(APUMODE_IDPX, MEMSIZE_BYTE, arg));
spc700_incpc(2);
add_apu_cycles(6);
}
void spc700_op_adc_a_idpy(void) {
spc700_prefetchb();
spc700->regs.a = spc700_op_adc(spc700->regs.a, spc700->mem_read(APUMODE_IDPY, MEMSIZE_BYTE, arg));
spc700_incpc(2);
add_apu_cycles(6);
}
void spc700_op_adc_ix_iy(void) {
byte x = spc700_op_adc(spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0), spc700->mem_read(APUMODE_IY, MEMSIZE_BYTE, 0));
spc700->mem_write(APUMODE_IX, MEMSIZE_BYTE, 0, x);
spc700_incpc(1);
add_apu_cycles(5);
}
void spc700_op_adc_dp_dp(void) {
spc700_prefetch2b();
byte x = spc700_op_adc(spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1), spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0));
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x);
spc700_incpc(3);
add_apu_cycles(6);
}
void spc700_op_adc_dp_imm(void) {
spc700_prefetch2b();
byte x = spc700_op_adc(spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1), arg0);
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_addw_ya_dp(void) {
spc700_prefetchb();
word ya = (spc700->regs.y << 8) | spc700->regs.a;
word dp = spc700->mem_read(APUMODE_DP, MEMSIZE_WORD, arg);
ulong r = ya + dp;
spc700_testn(r & 0x8000);
spc700_testv(~(ya ^ dp) & (dp ^ (word)r) & 0x8000);
spc700_testh((ya ^ dp ^ (word)r) & 0x1000);
spc700_testz((word)r == 0);
spc700_testc(r >= 0x10000);
spc700->regs.a = r;
spc700->regs.y = r >> 8;
spc700_incpc(2);
add_apu_cycles(5);
}
+147
View File
@@ -0,0 +1,147 @@
void spc700_op_and_a_const(void) {
spc700_prefetchb();
spc700->regs.a &= arg;
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(2);
}
void spc700_op_and_a_ix(void) {
spc700->regs.a &= spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(1);
add_apu_cycles(3);
}
void spc700_op_and_a_dp(void) {
spc700_prefetchb();
spc700->regs.a &= spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(3);
}
void spc700_op_and_a_dpx(void) {
spc700_prefetchb();
spc700->regs.a &= spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_and_a_addr(void) {
spc700_prefetchw();
spc700->regs.a &= spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(3);
add_apu_cycles(4);
}
void spc700_op_and_a_addrx(void) {
spc700_prefetchw();
spc700->regs.a &= spc700->mem_read(APUMODE_ADDRX, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_and_a_addry(void) {
spc700_prefetchw();
spc700->regs.a &= spc700->mem_read(APUMODE_ADDRY, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_and_a_idpx(void) {
spc700_prefetchb();
word i;
spc700->regs.a &= spc700->mem_read(APUMODE_IDPX, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(6);
}
void spc700_op_and_a_idpy(void) {
spc700_prefetchb();
word i;
spc700->regs.a &= spc700->mem_read(APUMODE_IDPY, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(6);
}
void spc700_op_and_ix_iy(void) {
word i;
byte x;
x = spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0);
x &= spc700->mem_read(APUMODE_IY, MEMSIZE_BYTE, 0);
spc700->mem_write(APUMODE_IX, MEMSIZE_BYTE, 0, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(1);
add_apu_cycles(5);
}
void spc700_op_and_dp_dp(void) {
spc700_prefetch2b();
byte x;
x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1);
x &= spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0);
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(3);
add_apu_cycles(6);
}
void spc700_op_and_dp_imm(void) {
spc700_prefetch2b();
byte x;
x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1);
x &= arg0;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_and1_bit(void) {
spc700_prefetchw();
word addr = arg & 0x1fff;
byte bit = arg >> 13;
byte x;
if(spc700->regs.p & SPF_C) {
x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, addr);
if(!(x & (1 << bit))) {
spc700_clrc();
}
}
spc700_incpc(3);
add_apu_cycles(4);
}
void spc700_op_and1_notbit(void) {
spc700_prefetchw();
word addr = arg & 0x1fff;
byte bit = arg >> 13;
byte x;
if(spc700->regs.p & SPF_C) {
x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, addr);
if(x & (1 << bit)) {
spc700_clrc();
}
}
spc700_incpc(3);
add_apu_cycles(4);
}
+142
View File
@@ -0,0 +1,142 @@
void spc700_op_cmp(byte x, byte y) {
short r = (short)x - (short)y;
spc700_testn(r & 0x80);
spc700_testz((byte)r == 0);
spc700_testc(r >= 0);
}
void spc700_op_cmp_a_const(void) {
spc700_prefetchb();
spc700_op_cmp(spc700->regs.a, arg);
spc700_incpc(2);
add_apu_cycles(2);
}
void spc700_op_cmp_a_ix(void) {
spc700_op_cmp(spc700->regs.a, spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0));
spc700_incpc(1);
add_apu_cycles(3);
}
void spc700_op_cmp_a_dp(void) {
spc700_prefetchb();
spc700_op_cmp(spc700->regs.a, spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg));
spc700_incpc(2);
add_apu_cycles(3);
}
void spc700_op_cmp_a_dpx(void) {
spc700_prefetchb();
spc700_op_cmp(spc700->regs.a, spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg));
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_cmp_a_addr(void) {
spc700_prefetchw();
spc700_op_cmp(spc700->regs.a, spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg));
spc700_incpc(3);
add_apu_cycles(4);
}
void spc700_op_cmp_a_addrx(void) {
spc700_prefetchw();
spc700_op_cmp(spc700->regs.a, spc700->mem_read(APUMODE_ADDRX, MEMSIZE_BYTE, arg));
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_cmp_a_addry(void) {
spc700_prefetchw();
spc700_op_cmp(spc700->regs.a, spc700->mem_read(APUMODE_ADDRY, MEMSIZE_BYTE, arg));
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_cmp_a_idpx(void) {
spc700_prefetchb();
spc700_op_cmp(spc700->regs.a, spc700->mem_read(APUMODE_IDPX, MEMSIZE_BYTE, arg));
spc700_incpc(2);
add_apu_cycles(6);
}
void spc700_op_cmp_a_idpy(void) {
spc700_prefetchb();
spc700_op_cmp(spc700->regs.a, spc700->mem_read(APUMODE_IDPY, MEMSIZE_BYTE, arg));
spc700_incpc(2);
add_apu_cycles(6);
}
void spc700_op_cmp_ix_iy(void) {
spc700_op_cmp(spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0), spc700->mem_read(APUMODE_IY, MEMSIZE_BYTE, 0));
spc700_incpc(1);
add_apu_cycles(5);
}
void spc700_op_cmp_dp_dp(void) {
spc700_prefetch2b();
spc700_op_cmp(spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1), spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0));
spc700_incpc(3);
add_apu_cycles(6);
}
void spc700_op_cmp_dp_imm(void) {
spc700_prefetch2b();
spc700_op_cmp(spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1), arg0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_cmp_x_const(void) {
spc700_prefetchb();
spc700_op_cmp(spc700->regs.x, arg);
spc700_incpc(2);
add_apu_cycles(2);
}
void spc700_op_cmp_x_dp(void) {
spc700_prefetchb();
spc700_op_cmp(spc700->regs.x, spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg));
spc700_incpc(2);
add_apu_cycles(3);
}
void spc700_op_cmp_x_addr(void) {
spc700_prefetchw();
spc700_op_cmp(spc700->regs.x, spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg));
spc700_incpc(3);
add_apu_cycles(4);
}
void spc700_op_cmp_y_const(void) {
spc700_prefetchb();
spc700_op_cmp(spc700->regs.y, arg);
spc700_incpc(2);
add_apu_cycles(2);
}
void spc700_op_cmp_y_dp(void) {
spc700_prefetchb();
spc700_op_cmp(spc700->regs.y, spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg));
spc700_incpc(2);
add_apu_cycles(3);
}
void spc700_op_cmp_y_addr(void) {
spc700_prefetchw();
spc700_op_cmp(spc700->regs.y, spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg));
spc700_incpc(3);
add_apu_cycles(4);
}
void spc700_op_cmpw_ya_dp(void) {
spc700_prefetchb();
word ya = ((spc700->regs.y << 8) | spc700->regs.a);
word dp = spc700->mem_read(APUMODE_DP, MEMSIZE_WORD, arg);
long r = (long)ya - (long)dp;
spc700_testn(r & 0x8000);
spc700_testz((word)r == 0);
spc700_testc(r >= 0);
spc700_incpc(2);
add_apu_cycles(5);
}
+148
View File
@@ -0,0 +1,148 @@
void spc700_op_eor_a_const(void) {
spc700_prefetchb();
spc700->regs.a ^= arg;
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(2);
}
void spc700_op_eor_a_ix(void) {
spc700->regs.a ^= spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(1);
add_apu_cycles(3);
}
void spc700_op_eor_a_dp(void) {
spc700_prefetchb();
spc700->regs.a ^= spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(3);
}
void spc700_op_eor_a_dpx(void) {
spc700_prefetchb();
spc700->regs.a ^= spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_eor_a_addr(void) {
spc700_prefetchw();
spc700->regs.a ^= spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(3);
add_apu_cycles(4);
}
void spc700_op_eor_a_addrx(void) {
spc700_prefetchw();
spc700->regs.a ^= spc700->mem_read(APUMODE_ADDRX, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_eor_a_addry(void) {
spc700_prefetchw();
spc700->regs.a ^= spc700->mem_read(APUMODE_ADDRY, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_eor_a_idpx(void) {
spc700_prefetchb();
word i;
spc700->regs.a ^= spc700->mem_read(APUMODE_IDPX, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(6);
}
void spc700_op_eor_a_idpy(void) {
spc700_prefetchb();
word i;
spc700->regs.a ^= spc700->mem_read(APUMODE_IDPY, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(6);
}
void spc700_op_eor_ix_iy(void) {
word i;
byte x;
x = spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0);
x ^= spc700->mem_read(APUMODE_IY, MEMSIZE_BYTE, 0);
spc700->mem_write(APUMODE_IX, MEMSIZE_BYTE, 0, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(1);
add_apu_cycles(5);
}
void spc700_op_eor_dp_dp(void) {
spc700_prefetch2b();
byte x;
x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1);
x ^= spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0);
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(3);
add_apu_cycles(6);
}
void spc700_op_eor_dp_imm(void) {
spc700_prefetch2b();
byte x;
x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1);
x ^= arg0;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_eor1_bit(void) {
spc700_prefetchw();
word addr = arg & 0x1fff;
byte bit = arg >> 13;
byte x;
x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, addr);
if(spc700->regs.p & SPF_C) {
if(x & (1 << bit)) {
spc700_clrc();
}
} else {
if(x & (1 << bit)) {
spc700_setc();
}
}
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_not1_bit(void) {
spc700_prefetchw();
word addr = arg & 0x1fff;
byte bit = arg >> 13;
byte x;
x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, addr);
x ^= (1 << bit);
spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, addr, x);
spc700_incpc(3);
add_apu_cycles(5);
}
+48
View File
@@ -0,0 +1,48 @@
void spc700_op_clrc(void) {
spc700_clrc();
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_setc(void) {
spc700_setc();
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_notc(void) {
spc700->regs.p ^= SPF_C;
spc700_incpc(1);
add_apu_cycles(3);
}
void spc700_op_clrv(void) {
spc700_clrv();
spc700_clrh();
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_clrp(void) {
spc700_clrp();
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_setp(void) {
spc700_setp();
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_di(void) {
spc700_clri();
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_ei(void) {
spc700_seti();
spc700_incpc(1);
add_apu_cycles(2);
}
+135
View File
@@ -0,0 +1,135 @@
void spc700_op_inc_a(void) {
spc700->regs.a++;
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_inc_x(void) {
spc700->regs.x++;
spc700_testn(spc700->regs.x & 0x80);
spc700_testz(spc700->regs.x == 0);
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_inc_y(void) {
spc700->regs.y++;
spc700_testn(spc700->regs.y & 0x80);
spc700_testz(spc700->regs.y == 0);
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_inc_dp(void) {
spc700_prefetchb();
byte r;
r = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg) + 1;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, r);
spc700_testn(r & 0x80);
spc700_testz(r == 0);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_inc_dpx(void) {
spc700_prefetchb();
byte r;
r = spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg) + 1;
spc700->mem_write(APUMODE_DPX, MEMSIZE_BYTE, arg, r);
spc700_testn(r & 0x80);
spc700_testz(r == 0);
spc700_incpc(2);
add_apu_cycles(5);
}
void spc700_op_inc_addr(void) {
spc700_prefetchw();
byte r;
r = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg) + 1;
spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, r);
spc700_testn(r & 0x80);
spc700_testz(r == 0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_dec_a(void) {
spc700->regs.a--;
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_dec_x(void) {
spc700->regs.x--;
spc700_testn(spc700->regs.x & 0x80);
spc700_testz(spc700->regs.x == 0);
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_dec_y(void) {
spc700->regs.y--;
spc700_testn(spc700->regs.y & 0x80);
spc700_testz(spc700->regs.y == 0);
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_dec_dp(void) {
spc700_prefetchb();
byte r;
r = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg) - 1;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, r);
spc700_testn(r & 0x80);
spc700_testz(r == 0);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_dec_dpx(void) {
spc700_prefetchb();
byte r;
r = spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg) - 1;
spc700->mem_write(APUMODE_DPX, MEMSIZE_BYTE, arg, r);
spc700_testn(r & 0x80);
spc700_testz(r == 0);
spc700_incpc(2);
add_apu_cycles(5);
}
void spc700_op_dec_addr(void) {
spc700_prefetchw();
byte r;
r = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg) - 1;
spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, r);
spc700_testn(r & 0x80);
spc700_testz(r == 0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_incw_dp(void) {
spc700_prefetchb();
word r;
r = spc700->mem_read(APUMODE_DP, MEMSIZE_WORD, arg) + 1;
spc700->mem_write(APUMODE_DP, MEMSIZE_WORD, arg, r);
spc700_testn(r & 0x8000);
spc700_testz(r == 0);
spc700_incpc(2);
add_apu_cycles(6);
}
void spc700_op_decw_dp(void) {
spc700_prefetchb();
word r;
r = spc700->mem_read(APUMODE_DP, MEMSIZE_WORD, arg) - 1;
spc700->mem_write(APUMODE_DP, MEMSIZE_WORD, arg, r);
spc700_testn(r & 0x8000);
spc700_testz(r == 0);
spc700_incpc(2);
add_apu_cycles(6);
}
+241
View File
@@ -0,0 +1,241 @@
void spc700_op_nop(void) {
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_sleep(void) {
add_apu_cycles(3);
}
void spc700_op_stop(void) {
add_apu_cycles(3);
}
void spc700_op_xcn_a(void) {
spc700->regs.a = (spc700->regs.a >> 4) | (spc700->regs.a << 4);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(1);
add_apu_cycles(5);
}
void spc700_op_daa_a(void) {
int a = spc700->regs.a;
if(((a ) & 15) > 9)a += 6;
if(((a >> 4) & 15) > 9)a += 6 << 4;
spc700->regs.a = a;
spc700_testn(a & 0x80);
spc700_testz(a == 0);
spc700_testc(a >= 0x0100);
spc700_incpc(1);
add_apu_cycles(3);
}
void spc700_op_das_a(void) {
int a = spc700->regs.a;
if(((a ) & 15) > 9)a -= 6;
if(((a >> 4) & 15) > 9)a -= 6 << 4;
spc700->regs.a = a;
spc700_testn(a & 0x80);
spc700_testz(a == 0);
spc700_testc(a < 0);
spc700_incpc(1);
add_apu_cycles(3);
}
void spc700_op_set0_dp(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
x |= 0x01;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_clr0_dp(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
x &= ~0x01;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_set1_dp(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
x |= 0x02;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_clr1_dp(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
x &= ~0x02;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_set2_dp(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
x |= 0x04;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_clr2_dp(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
x &= ~0x04;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_set3_dp(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
x |= 0x08;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_clr3_dp(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
x &= ~0x08;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_set4_dp(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
x |= 0x10;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_clr4_dp(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
x &= ~0x10;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_set5_dp(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
x |= 0x20;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_clr5_dp(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
x &= ~0x20;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_set6_dp(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
x |= 0x40;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_clr6_dp(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
x &= ~0x40;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_set7_dp(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
x |= 0x80;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_clr7_dp(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
x &= ~0x80;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_tset1_addr(void) {
spc700_prefetchw();
byte x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg);
x |= spc700->regs.a;
spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(3);
add_apu_cycles(6);
}
void spc700_op_tclr1_addr(void) {
spc700_prefetchw();
byte x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg);
x &= ~spc700->regs.a;
spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(3);
add_apu_cycles(6);
}
void spc700_op_mul_ya(void) {
word ya;
ya = spc700->regs.y * spc700->regs.a;
spc700->regs.a = ya;
spc700->regs.y = ya >> 8;
spc700_testn(ya & 0x8000);
spc700_testz(ya == 0);
spc700_incpc(1);
add_apu_cycles(9);
}
/*
v/h flags not set, may have result backwards
(a and y may need to be swapped)
*/
void spc700_op_div_ya_x(void) {
word ya = (spc700->regs.y << 8) | spc700->regs.a;
if(spc700->regs.x == 0) {
spc700->regs.a = 0;
spc700->regs.y = 0;
} else {
spc700->regs.a = ya / spc700->regs.x;
spc700->regs.y = ya % spc700->regs.x;
}
ya = (spc700->regs.y << 8) | spc700->regs.a;
spc700_testn(ya & 0x8000);
spc700_testz(ya == 0);
spc700_incpc(1);
add_apu_cycles(12);
}
+377
View File
@@ -0,0 +1,377 @@
void spc700_op_mov_a_x(void) {
spc700->regs.a = spc700->regs.x;
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_mov_a_y(void) {
spc700->regs.a = spc700->regs.y;
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_mov_x_a(void) {
spc700->regs.x = spc700->regs.a;
spc700_testn(spc700->regs.x & 0x80);
spc700_testz(spc700->regs.x == 0);
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_mov_y_a(void) {
spc700->regs.y = spc700->regs.a;
spc700_testn(spc700->regs.y & 0x80);
spc700_testz(spc700->regs.y == 0);
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_mov_x_sp(void) {
spc700->regs.x = spc700->regs.sp;
spc700_testn(spc700->regs.x & 0x80);
spc700_testz(spc700->regs.x == 0);
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_mov_sp_x(void) {
spc700->regs.sp = spc700->regs.x;
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_mov_dp_dp(void) {
spc700_prefetch2b();
byte x;
x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0);
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_mov_dp_imm(void) {
spc700_prefetch2b();
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, arg0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_mov_a_const(void) {
spc700_prefetchb();
spc700->regs.a = arg;
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(2);
}
void spc700_op_mov_x_const(void) {
spc700_prefetchb();
spc700->regs.x = arg;
spc700_testn(spc700->regs.x & 0x80);
spc700_testz(spc700->regs.x == 0);
spc700_incpc(2);
add_apu_cycles(2);
}
void spc700_op_mov_y_const(void) {
spc700_prefetchb();
spc700->regs.y = arg;
spc700_testn(spc700->regs.y & 0x80);
spc700_testz(spc700->regs.y == 0);
spc700_incpc(2);
add_apu_cycles(2);
}
void spc700_op_mov_ix_a(void) {
spc700->mem_write(APUMODE_IX, MEMSIZE_BYTE, 0, spc700->regs.a);
spc700_incpc(1);
add_apu_cycles(4);
}
void spc700_op_mov_ixinc_a(void) {
spc700->mem_write(APUMODE_IX, MEMSIZE_BYTE, 0, spc700->regs.a);
spc700->regs.x++;
spc700_incpc(1);
add_apu_cycles(4);
}
void spc700_op_mov_dp_a(void) {
spc700_prefetchb();
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, spc700->regs.a);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_mov_dpx_a(void) {
spc700_prefetchb();
spc700->mem_write(APUMODE_DPX, MEMSIZE_BYTE, arg, spc700->regs.a);
spc700_incpc(2);
add_apu_cycles(5);
}
void spc700_op_mov_addr_a(void) {
spc700_prefetchw();
spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, spc700->regs.a);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_mov_addrx_a(void) {
spc700_prefetchw();
spc700->mem_write(APUMODE_ADDRX, MEMSIZE_BYTE, arg, spc700->regs.a);
spc700_incpc(3);
add_apu_cycles(6);
}
void spc700_op_mov_addry_a(void) {
spc700_prefetchw();
spc700->mem_write(APUMODE_ADDRY, MEMSIZE_BYTE, arg, spc700->regs.a);
spc700_incpc(3);
add_apu_cycles(6);
}
void spc700_op_mov_idpx_a(void) {
spc700_prefetchb();
word i;
spc700->mem_write(APUMODE_IDPX, MEMSIZE_BYTE, arg, spc700->regs.a);
spc700_incpc(2);
add_apu_cycles(7);
}
void spc700_op_mov_idpy_a(void) {
spc700_prefetchb();
word i;
spc700->mem_write(APUMODE_IDPY, MEMSIZE_BYTE, arg, spc700->regs.a);
spc700_incpc(2);
add_apu_cycles(7);
}
void spc700_op_mov_dp_x(void) {
spc700_prefetchb();
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, spc700->regs.x);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_mov_dpy_x(void) {
spc700_prefetchb();
spc700->mem_write(APUMODE_DPY, MEMSIZE_BYTE, arg, spc700->regs.x);
spc700_incpc(2);
add_apu_cycles(5);
}
void spc700_op_mov_addr_x(void) {
spc700_prefetchw();
spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, spc700->regs.x);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_mov_dp_y(void) {
spc700_prefetchb();
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, spc700->regs.y);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_mov_dpx_y(void) {
spc700_prefetchb();
spc700->mem_write(APUMODE_DPX, MEMSIZE_BYTE, arg, spc700->regs.y);
spc700_incpc(2);
add_apu_cycles(5);
}
void spc700_op_mov_addr_y(void) {
spc700_prefetchw();
spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, spc700->regs.y);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_mov_a_ix(void) {
spc700->regs.a = spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(1);
add_apu_cycles(3);
}
void spc700_op_mov_a_ixinc(void) {
spc700->regs.a = spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0);
spc700->regs.x++;
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(1);
add_apu_cycles(4);
}
void spc700_op_mov_a_dp(void) {
spc700_prefetchb();
spc700->regs.a = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(3);
}
void spc700_op_mov_a_dpx(void) {
spc700_prefetchb();
spc700->regs.a = spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_mov_a_addr(void) {
spc700_prefetchw();
spc700->regs.a = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(3);
add_apu_cycles(4);
}
void spc700_op_mov_a_addrx(void) {
spc700_prefetchw();
spc700->regs.a = spc700->mem_read(APUMODE_ADDRX, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_mov_a_addry(void) {
spc700_prefetchw();
spc700->regs.a = spc700->mem_read(APUMODE_ADDRY, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_mov_a_idpx(void) {
spc700_prefetchb();
word i;
spc700->regs.a = spc700->mem_read(APUMODE_IDPX, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(6);
}
void spc700_op_mov_a_idpy(void) {
spc700_prefetchb();
word i;
spc700->regs.a = spc700->mem_read(APUMODE_IDPY, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(6);
}
void spc700_op_mov_x_dp(void) {
spc700_prefetchb();
spc700->regs.x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.x & 0x80);
spc700_testz(spc700->regs.x == 0);
spc700_incpc(2);
add_apu_cycles(3);
}
void spc700_op_mov_x_dpy(void) {
spc700_prefetchb();
spc700->regs.x = spc700->mem_read(APUMODE_DPY, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.x & 0x80);
spc700_testz(spc700->regs.x == 0);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_mov_x_addr(void) {
spc700_prefetchw();
spc700->regs.x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.x & 0x80);
spc700_testz(spc700->regs.x == 0);
spc700_incpc(3);
add_apu_cycles(4);
}
void spc700_op_mov_y_dp(void) {
spc700_prefetchb();
spc700->regs.y = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.y & 0x80);
spc700_testz(spc700->regs.y == 0);
spc700_incpc(2);
add_apu_cycles(3);
}
void spc700_op_mov_y_dpx(void) {
spc700_prefetchb();
spc700->regs.y = spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.y & 0x80);
spc700_testz(spc700->regs.y == 0);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_mov_y_addr(void) {
spc700_prefetchw();
spc700->regs.y = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.y & 0x80);
spc700_testz(spc700->regs.y == 0);
spc700_incpc(3);
add_apu_cycles(4);
}
void spc700_op_mov_ya_dp(void) {
spc700_prefetchb();
word ya;
ya = spc700->mem_read(APUMODE_DP, MEMSIZE_WORD, arg);
spc700->regs.a = ya;
spc700->regs.y = ya >> 8;
spc700_testn(ya & 0x8000);
spc700_testz(ya == 0);
spc700_incpc(2);
add_apu_cycles(5);
}
void spc700_op_mov_dp_ya(void) {
spc700_prefetchb();
word ya = (spc700->regs.y << 8) | spc700->regs.a;
spc700->mem_write(APUMODE_DP, MEMSIZE_WORD, arg, ya);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_mov1_c_bit(void) {
spc700_prefetchw();
word addr = arg & 0x1fff;
byte bit = arg >> 13;
byte x;
x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, addr);
spc700_testc(x & (1 << bit));
spc700_incpc(3);
add_apu_cycles(4);
}
void spc700_op_mov1_bit_c(void) {
spc700_prefetchw();
word addr = arg & 0x1fff;
byte bit = arg >> 13;
byte x;
x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, addr);
if(spc700->regs.p & SPF_C) {
x |= (1 << bit);
} else {
x &= ~(1 << bit);
}
spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, addr, x);
spc700_incpc(3);
add_apu_cycles(5);
}
+147
View File
@@ -0,0 +1,147 @@
void spc700_op_or_a_const(void) {
spc700_prefetchb();
spc700->regs.a |= arg;
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(2);
}
void spc700_op_or_a_ix(void) {
spc700->regs.a |= spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(1);
add_apu_cycles(3);
}
void spc700_op_or_a_dp(void) {
spc700_prefetchb();
spc700->regs.a |= spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(3);
}
void spc700_op_or_a_dpx(void) {
spc700_prefetchb();
spc700->regs.a |= spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_or_a_addr(void) {
spc700_prefetchw();
spc700->regs.a |= spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(3);
add_apu_cycles(4);
}
void spc700_op_or_a_addrx(void) {
spc700_prefetchw();
spc700->regs.a |= spc700->mem_read(APUMODE_ADDRX, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_or_a_addry(void) {
spc700_prefetchw();
spc700->regs.a |= spc700->mem_read(APUMODE_ADDRY, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_or_a_idpx(void) {
spc700_prefetchb();
word i;
spc700->regs.a |= spc700->mem_read(APUMODE_IDPX, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(6);
}
void spc700_op_or_a_idpy(void) {
spc700_prefetchb();
word i;
spc700->regs.a |= spc700->mem_read(APUMODE_IDPY, MEMSIZE_BYTE, arg);
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(2);
add_apu_cycles(6);
}
void spc700_op_or_ix_iy(void) {
word i;
byte x;
x = spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0);
x |= spc700->mem_read(APUMODE_IY, MEMSIZE_BYTE, 0);
spc700->mem_write(APUMODE_IX, MEMSIZE_BYTE, 0, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(1);
add_apu_cycles(5);
}
void spc700_op_or_dp_dp(void) {
spc700_prefetch2b();
byte x;
x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1);
x |= spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0);
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(3);
add_apu_cycles(6);
}
void spc700_op_or_dp_imm(void) {
spc700_prefetch2b();
byte x;
x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1);
x |= arg0;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_or1_bit(void) {
spc700_prefetchw();
word addr = arg & 0x1fff;
byte bit = arg >> 13;
byte x;
if(!(spc700->regs.p & SPF_C)) {
x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, addr);
if(x & (1 << bit)) {
spc700_setc();
}
}
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_or1_notbit(void) {
spc700_prefetchw();
word addr = arg & 0x1fff;
byte bit = arg >> 13;
byte x;
if(!(spc700->regs.p & SPF_C)) {
x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, addr);
if(!(x & (1 << bit))) {
spc700_setc();
}
}
spc700_incpc(3);
add_apu_cycles(5);
}
+342
View File
@@ -0,0 +1,342 @@
void spc700_op_bra(void) {
spc700_prefetchb();
spc700->regs.pc += (signed char)arg;
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_bcc(void) {
spc700_prefetchb();
if(!(spc700->regs.p & SPF_C)) {
spc700->regs.pc += (signed char)arg;
add_apu_cycles(4);
} else {
add_apu_cycles(2);
}
spc700_incpc(2);
}
void spc700_op_bcs(void) {
spc700_prefetchb();
if((spc700->regs.p & SPF_C)) {
spc700->regs.pc += (signed char)arg;
add_apu_cycles(4);
} else {
add_apu_cycles(2);
}
spc700_incpc(2);
}
void spc700_op_beq(void) {
spc700_prefetchb();
if((spc700->regs.p & SPF_Z)) {
spc700->regs.pc += (signed char)arg;
add_apu_cycles(4);
} else {
add_apu_cycles(2);
}
spc700_incpc(2);
}
void spc700_op_bmi(void) {
spc700_prefetchb();
if((spc700->regs.p & SPF_N)) {
spc700->regs.pc += (signed char)arg;
add_apu_cycles(4);
} else {
add_apu_cycles(2);
}
spc700_incpc(2);
}
void spc700_op_bne(void) {
spc700_prefetchb();
if(!(spc700->regs.p & SPF_Z)) {
spc700->regs.pc += (signed char)arg;
add_apu_cycles(4);
} else {
add_apu_cycles(2);
}
spc700_incpc(2);
}
void spc700_op_bpl(void) {
spc700_prefetchb();
if(!(spc700->regs.p & SPF_N)) {
spc700->regs.pc += (signed char)arg;
add_apu_cycles(4);
} else {
add_apu_cycles(2);
}
spc700_incpc(2);
}
void spc700_op_bvc(void) {
spc700_prefetchb();
if(!(spc700->regs.p & SPF_V)) {
spc700->regs.pc += (signed char)arg;
add_apu_cycles(4);
} else {
add_apu_cycles(2);
}
spc700_incpc(2);
}
void spc700_op_bvs(void) {
spc700_prefetchb();
if((spc700->regs.p & SPF_V)) {
spc700->regs.pc += (signed char)arg;
add_apu_cycles(4);
} else {
add_apu_cycles(2);
}
spc700_incpc(2);
}
#define spc700_op_bbc(__n) \
void spc700_op_bbc##__n##(void) { \
spc700_prefetch2b(); \
byte r; \
r = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0); \
if(!(r & (1 << __n))) { \
spc700->regs.pc += (signed char)arg1; \
add_apu_cycles(7); \
} else { \
add_apu_cycles(5); \
} \
spc700_incpc(3); \
}
#define spc700_op_bbs(__n) \
void spc700_op_bbs##__n##(void) { \
spc700_prefetch2b(); \
byte r; \
r = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0); \
if(r & (1 << __n)) { \
spc700->regs.pc += (signed char)arg1; \
add_apu_cycles(7); \
} else { \
add_apu_cycles(5); \
} \
spc700_incpc(3); \
}
spc700_op_bbc(0)
spc700_op_bbc(1)
spc700_op_bbc(2)
spc700_op_bbc(3)
spc700_op_bbc(4)
spc700_op_bbc(5)
spc700_op_bbc(6)
spc700_op_bbc(7)
spc700_op_bbs(0)
spc700_op_bbs(1)
spc700_op_bbs(2)
spc700_op_bbs(3)
spc700_op_bbs(4)
spc700_op_bbs(5)
spc700_op_bbs(6)
spc700_op_bbs(7)
void spc700_op_cbne_dp(void) {
spc700_prefetch2b();
byte r;
r = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0);
if(r != spc700->regs.a) {
spc700->regs.pc += (signed char)arg1;
add_apu_cycles(7);
} else {
add_apu_cycles(5);
}
spc700_incpc(3);
}
void spc700_op_cbne_dpx(void) {
spc700_prefetch2b();
byte r;
r = spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg0);
if(r != spc700->regs.a) {
spc700->regs.pc += (signed char)arg1;
add_apu_cycles(8);
} else {
add_apu_cycles(6);
}
spc700_incpc(3);
}
void spc700_op_dbnz_dp(void) {
spc700_prefetch2b();
byte r;
r = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0) - 1;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg0, r);
if(r != 0) {
spc700->regs.pc += (signed char)arg1;
add_apu_cycles(7);
} else {
add_apu_cycles(5);
}
spc700_incpc(3);
}
void spc700_op_dbnz_y(void) {
spc700_prefetchb();
spc700->regs.y--;
if(spc700->regs.y != 0) {
spc700->regs.pc += (signed char)arg;
add_apu_cycles(6);
} else {
add_apu_cycles(4);
}
spc700_incpc(2);
}
void spc700_op_jmp_addr(void) {
spc700_prefetchw();
spc700->regs.pc = arg;
add_apu_cycles(3);
}
void spc700_op_jmp_iaddrx(void) {
spc700_prefetchw();
spc700->regs.pc = spc700->mem_read(APUMODE_IADDRX, MEMSIZE_WORD, arg);
add_apu_cycles(3);
}
void spc700_op_call(void) {
spc700_prefetchw();
word r = spc700->regs.pc + 3;
spc700_incpc(3);
spc700->stack_write(r);
spc700->stack_write(r >> 8);
spc700->regs.pc = arg;
add_apu_cycles(8);
}
void spc700_op_pcall(void) {
spc700_prefetchb();
word r = spc700->regs.pc + 2;
spc700->stack_write(r);
spc700->stack_write(r >> 8);
spc700->regs.pc = 0xff00 | arg;
add_apu_cycles(6);
}
void spc700_op_tcall_0(void) {
dprintf("* spc700 opcode tcall 0 not implemented");
spc700_incpc(1);
add_apu_cycles(8);
}
void spc700_op_tcall_1(void) {
dprintf("* spc700 opcode tcall 1 not implemented");
spc700_incpc(1);
add_apu_cycles(8);
}
void spc700_op_tcall_2(void) {
dprintf("* spc700 opcode tcall 2 not implemented");
spc700_incpc(1);
add_apu_cycles(8);
}
void spc700_op_tcall_3(void) {
dprintf("* spc700 opcode tcall 3 not implemented");
spc700_incpc(1);
add_apu_cycles(8);
}
void spc700_op_tcall_4(void) {
dprintf("* spc700 opcode tcall 4 not implemented");
spc700_incpc(1);
add_apu_cycles(8);
}
void spc700_op_tcall_5(void) {
dprintf("* spc700 opcode tcall 5 not implemented");
spc700_incpc(1);
add_apu_cycles(8);
}
void spc700_op_tcall_6(void) {
dprintf("* spc700 opcode tcall 6 not implemented");
spc700_incpc(1);
add_apu_cycles(8);
}
void spc700_op_tcall_7(void) {
dprintf("* spc700 opcode tcall 7 not implemented");
spc700_incpc(1);
add_apu_cycles(8);
}
void spc700_op_tcall_8(void) {
dprintf("* spc700 opcode tcall 8 not implemented");
spc700_incpc(1);
add_apu_cycles(8);
}
void spc700_op_tcall_9(void) {
dprintf("* spc700 opcode tcall 9 not implemented");
spc700_incpc(1);
add_apu_cycles(8);
}
void spc700_op_tcall_10(void) {
dprintf("* spc700 opcode tcall 10 not implemented");
spc700_incpc(1);
add_apu_cycles(8);
}
void spc700_op_tcall_11(void) {
dprintf("* spc700 opcode tcall 11 not implemented");
spc700_incpc(1);
add_apu_cycles(8);
}
void spc700_op_tcall_12(void) {
dprintf("* spc700 opcode tcall 12 not implemented");
spc700_incpc(1);
add_apu_cycles(8);
}
void spc700_op_tcall_13(void) {
dprintf("* spc700 opcode tcall 13 not implemented");
spc700_incpc(1);
add_apu_cycles(8);
}
void spc700_op_tcall_14(void) {
dprintf("* spc700 opcode tcall 14 not implemented");
spc700_incpc(1);
add_apu_cycles(8);
}
void spc700_op_tcall_15(void) {
dprintf("* spc700 opcode tcall 15 not implemented");
spc700_incpc(1);
add_apu_cycles(8);
}
void spc700_op_brk(void) {
dprintf("* spc700 opcode brk not implemented");
spc700_incpc(1);
add_apu_cycles(8);
}
void spc700_op_ret(void) {
word r;
r = spc700->stack_read();
r |= spc700->stack_read() << 8;
spc700->regs.pc = r;
add_apu_cycles(5);
}
void spc700_op_reti(void) {
word r;
spc700->regs.p = spc700->stack_read();
r = spc700->stack_read();
r |= spc700->stack_read() << 8;
spc700->regs.pc = r;
add_apu_cycles(6);
}
+111
View File
@@ -0,0 +1,111 @@
byte spc700_op_sbc(byte x, byte y) {
short r = (short)x - (short)y - (short)(!(spc700->regs.p & SPF_C));
spc700_testn(r & 0x80);
spc700_testv(((x ^ y) & 0x80) && ((x ^ (byte)r) & 0x80));
spc700_testh(((x ^ y ^ (byte)r) & 0x10) == 0);
spc700_testz((byte)r == 0);
spc700_testc(r >= 0);
return (byte)r;
}
void spc700_op_sbc_a_const(void) {
spc700_prefetchb();
spc700->regs.a = spc700_op_sbc(spc700->regs.a, arg);
spc700_incpc(2);
add_apu_cycles(2);
}
void spc700_op_sbc_a_ix(void) {
spc700->regs.a = spc700_op_sbc(spc700->regs.a, spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0));
spc700_incpc(1);
add_apu_cycles(3);
}
void spc700_op_sbc_a_dp(void) {
spc700_prefetchb();
spc700->regs.a = spc700_op_sbc(spc700->regs.a, spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg));
spc700_incpc(2);
add_apu_cycles(3);
}
void spc700_op_sbc_a_dpx(void) {
spc700_prefetchb();
spc700->regs.a = spc700_op_sbc(spc700->regs.a, spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg));
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_sbc_a_addr(void) {
spc700_prefetchw();
spc700->regs.a = spc700_op_sbc(spc700->regs.a, spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg));
spc700_incpc(3);
add_apu_cycles(4);
}
void spc700_op_sbc_a_addrx(void) {
spc700_prefetchw();
spc700->regs.a = spc700_op_sbc(spc700->regs.a, spc700->mem_read(APUMODE_ADDRX, MEMSIZE_BYTE, arg));
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_sbc_a_addry(void) {
spc700_prefetchw();
spc700->regs.a = spc700_op_sbc(spc700->regs.a, spc700->mem_read(APUMODE_ADDRY, MEMSIZE_BYTE, arg));
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_sbc_a_idpx(void) {
spc700_prefetchb();
spc700->regs.a = spc700_op_sbc(spc700->regs.a, spc700->mem_read(APUMODE_IDPX, MEMSIZE_BYTE, arg));
spc700_incpc(2);
add_apu_cycles(6);
}
void spc700_op_sbc_a_idpy(void) {
spc700_prefetchb();
word i;
spc700->regs.a = spc700_op_sbc(spc700->regs.a, spc700->mem_read(APUMODE_IDPY, MEMSIZE_BYTE, arg));
spc700_incpc(2);
add_apu_cycles(6);
}
void spc700_op_sbc_ix_iy(void) {
byte x = spc700_op_sbc(spc700->mem_read(APUMODE_IX, MEMSIZE_BYTE, 0), spc700->mem_read(APUMODE_IY, MEMSIZE_BYTE, 0));
spc700->mem_write(APUMODE_IX, MEMSIZE_BYTE, 0, x);
spc700_incpc(1);
add_apu_cycles(5);
}
void spc700_op_sbc_dp_dp(void) {
spc700_prefetch2b();
byte x = spc700_op_sbc(spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1), spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg0));
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x);
spc700_incpc(3);
add_apu_cycles(6);
}
void spc700_op_sbc_dp_imm(void) {
spc700_prefetch2b();
byte x = spc700_op_sbc(spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg1), arg0);
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg1, x);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_subw_ya_dp(void) {
spc700_prefetchb();
word ya = (spc700->regs.y << 8) | spc700->regs.a;
word dp = spc700->mem_read(APUMODE_DP, MEMSIZE_WORD, arg);
long r = (long)ya - (long)dp;
spc700_testn(r & 0x8000);
spc700_testv(((ya ^ dp) & 0x8000) && ((ya ^ (word)r) & 0x8000));
spc700_testh(((ya ^ dp ^ (word)r) & 0x1000) == 0);
spc700_testz((word)r == 0);
spc700_testc(r >= 0);
spc700->regs.a = r;
spc700->regs.y = r >> 8;
spc700_incpc(2);
add_apu_cycles(5);
}
+195
View File
@@ -0,0 +1,195 @@
void spc700_op_asl_a(void) {
spc700_testc(spc700->regs.a & 0x80);
spc700->regs.a <<= 1;
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_asl_dp(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
spc700_testc(x & 0x80);
x <<= 1;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_asl_dpx(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg);
spc700_testc(x & 0x80);
x <<= 1;
spc700->mem_write(APUMODE_DPX, MEMSIZE_BYTE, arg, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(2);
add_apu_cycles(5);
}
void spc700_op_asl_addr(void) {
spc700_prefetchw();
byte x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg);
spc700_testc(x & 0x80);
x <<= 1;
spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_lsr_a(void) {
spc700_testc(spc700->regs.a & 0x01);
spc700->regs.a >>= 1;
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_lsr_dp(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
spc700_testc(x & 0x01);
x >>= 1;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_lsr_dpx(void) {
spc700_prefetchb();
byte x = spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg);
spc700_testc(x & 0x01);
x >>= 1;
spc700->mem_write(APUMODE_DPX, MEMSIZE_BYTE, arg, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(2);
add_apu_cycles(5);
}
void spc700_op_lsr_addr(void) {
spc700_prefetchw();
byte x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg);
spc700_testc(x & 0x01);
x >>= 1;
spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_rol_a(void) {
byte c = (spc700->regs.p & SPF_C)?0x80:0x00;
spc700_testc(spc700->regs.a & 0x80);
spc700->regs.a <<= 1;
spc700->regs.a |= c;
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_rol_dp(void) {
spc700_prefetchb();
byte c = (spc700->regs.p & SPF_C)?0x80:0x00;
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
spc700_testc(x & 0x80);
x <<= 1;
x |= c;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_rol_dpx(void) {
spc700_prefetchb();
byte c = (spc700->regs.p & SPF_C)?0x80:0x00;
byte x = spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg);
spc700_testc(x & 0x80);
x <<= 1;
x |= c;
spc700->mem_write(APUMODE_DPX, MEMSIZE_BYTE, arg, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(2);
add_apu_cycles(5);
}
void spc700_op_rol_addr(void) {
spc700_prefetchw();
byte c = (spc700->regs.p & SPF_C)?0x80:0x00;
byte x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg);
spc700_testc(x & 0x80);
x <<= 1;
x |= c;
spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(3);
add_apu_cycles(5);
}
void spc700_op_ror_a(void) {
byte c = (spc700->regs.p & SPF_C)?0x01:0x00;
spc700_testc(spc700->regs.a & 0x01);
spc700->regs.a >>= 1;
spc700->regs.a |= c;
spc700_testn(spc700->regs.a & 0x80);
spc700_testz(spc700->regs.a == 0);
spc700_incpc(1);
add_apu_cycles(2);
}
void spc700_op_ror_dp(void) {
spc700_prefetchb();
byte c = (spc700->regs.p & SPF_C)?0x01:0x00;
byte x = spc700->mem_read(APUMODE_DP, MEMSIZE_BYTE, arg);
spc700_testc(x & 0x01);
x >>= 1;
x |= c;
spc700->mem_write(APUMODE_DP, MEMSIZE_BYTE, arg, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(2);
add_apu_cycles(4);
}
void spc700_op_ror_dpx(void) {
spc700_prefetchb();
byte c = (spc700->regs.p & SPF_C)?0x01:0x00;
byte x = spc700->mem_read(APUMODE_DPX, MEMSIZE_BYTE, arg);
spc700_testc(x & 0x01);
x >>= 1;
x |= c;
spc700->mem_write(APUMODE_DPX, MEMSIZE_BYTE, arg, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(2);
add_apu_cycles(5);
}
void spc700_op_ror_addr(void) {
spc700_prefetchw();
byte c = (spc700->regs.p & SPF_C)?0x01:0x00;
byte x = spc700->mem_read(APUMODE_ADDR, MEMSIZE_BYTE, arg);
spc700_testc(x & 0x01);
x >>= 1;
x |= c;
spc700->mem_write(APUMODE_ADDR, MEMSIZE_BYTE, arg, x);
spc700_testn(x & 0x80);
spc700_testz(x == 0);
spc700_incpc(3);
add_apu_cycles(5);
}
+48
View File
@@ -0,0 +1,48 @@
void spc700_op_push_a(void) {
spc700->stack_write(spc700->regs.a);
spc700_incpc(1);
add_apu_cycles(4);
}
void spc700_op_push_x(void) {
spc700->stack_write(spc700->regs.x);
spc700_incpc(1);
add_apu_cycles(4);
}
void spc700_op_push_y(void) {
spc700->stack_write(spc700->regs.y);
spc700_incpc(1);
add_apu_cycles(4);
}
void spc700_op_push_p(void) {
spc700->stack_write(spc700->regs.p);
spc700_incpc(1);
add_apu_cycles(4);
}
void spc700_op_pop_a(void) {
spc700->regs.a = spc700->stack_read();
spc700_incpc(1);
add_apu_cycles(4);
}
void spc700_op_pop_x(void) {
spc700->regs.x = spc700->stack_read();
spc700_incpc(1);
add_apu_cycles(4);
}
void spc700_op_pop_y(void) {
spc700->regs.y = spc700->stack_read();
spc700_incpc(1);
add_apu_cycles(4);
}
void spc700_op_pop_p(void) {
spc700->regs.p = spc700->stack_read();
spc700_incpc(1);
add_apu_cycles(4);
spc700->regs.dp = (spc700->regs.p & SPF_P)?0x0100:0x0000;
}
+424
View File
@@ -0,0 +1,424 @@
#define NO_SPC700
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#define null 0xffffffff
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long ulong;
typedef void (*vfunc)(void);
#define SH_2 1
#define SH_4 2
#define SH_8 3
#define SH_16 4
#define SH_32 5
#define SH_64 6
#define SH_128 7
#define SH_256 8
#define SH_512 9
#define SH_1024 10
#define SH_2048 11
#define SH_4096 12
/*************************
*** general functions ***
************************/
void alert(char *s, ...);
/************************
*** joypad functions ***
***********************/
void UpdateJoypad(void);
typedef struct {
byte a, b, x, y;
byte l, r;
byte select, start;
byte up, down, left, right;
byte read_pos;
}joypad_state;
/******************
*** deprecated ***
*****************/
typedef struct {
bool rom_loaded;
ulong sram_save_tick_count;
char rom_name[4096], sram_name[4096];
}emustate;
/***********************
*** video functions ***
**********************/
void video_setmode(bool fullscreen, word width, word height);
void video_setsnesmode(void);
#define LINE_DOUBLEWIDTH 1
#define LINE_DOUBLEHEIGHT 2
//global export: render
typedef struct {
word display_width, display_height;
word snes_width, snes_height;
bool fullscreen;
bool show_menu;
byte frame_skip;
byte frame_count;
bool bg1_enabled[3], bg2_enabled[3], bg3_enabled[3], bg4_enabled[3], oam_enabled[5];
byte line[239];
}videostate;
/***************************
*** debugging functions ***
**************************/
#define DEBUGMSG_INFO 0
#define DEBUGMSG_CPU 1
#define DEBUGMSG_APU 2
#define DEBUGWRITE_NONE 0
#define DEBUGWRITE_CONSOLE 1
#define DEBUGWRITE_TRACE 2
enum {
DEBUGMODE_DISABLED = 0,
DEBUGMODE_WAIT,
DEBUGMODE_RUN,
DEBUGMODE_CPUSTEP,
DEBUGMODE_APUSTEP,
DEBUGMODE_PROCEED
};
#define DEBUG_BGENABLED_ALL 0
#define DEBUG_BGENABLED_PRI0 1
#define DEBUG_BGENABLED_PRI1 2
#define DEBUG_BGENABLED_PRI2 3
#define DEBUG_BGENABLED_PRI3 4
#define BP_OFF 0
#define BP_READ 1
#define BP_WRITE 2
#define BP_EXEC 4
#define BP_VAL 8
#define BPSRC_MEM 0
#define BPSRC_VRAM 1
#define BPSRC_CGRAM 2
#define BPSRC_OAM 3
#define BPSRC_SPCRAM 4
void debug_test_breakpoint(byte source, byte flag, ulong offset, byte value);
#define debug_get_state() debugger.mode
#define debugger_enabled() ((debugger.mode == DEBUGMODE_DISABLED)?false:true)
#define debug_test_bp(__source, __flag, __offset, __value) \
if(debug_get_state() != DEBUGMODE_DISABLED) { \
debug_test_breakpoint(__source, __flag, __offset, __value); \
}
void debug_set_state(byte state);
void dprintf(char *s, ...);
void dprintf(ulong msg_type, char *s, ...);
void debug_refresh_mem(void);
void debug_refresh_bp(void);
void debug_update_status(void);
ulong debug_write_status(void);
typedef struct {
byte mode;
ulong mem_ptr; //position of wram ptr for debug window
bool disas_cpu_op, disas_apu_op;
bool refresh_mem;
bool refresh_bp;
bool refresh_status;
bool cpu_op_executed;
bool apu_op_executed;
bool output_cpu_instrs;
bool output_apu_instrs;
bool output_debug_info;
bool trace_enabled;
bool trace_output_enabled;
bool lock_up, lock_down, lock_left, lock_right;
bool lock_a, lock_b, lock_x, lock_y;
bool lock_l, lock_r, lock_select, lock_start;
struct {
ulong offset;
byte flags;
byte source;
byte value;
ulong hit_count;
}bp_list[16];
FILE *trace_fp;
}debugstate;
/*********************
*** ppu functions ***
********************/
#define BG1 0x00
#define BG2 0x01
#define BG3 0x02
#define BG4 0x03
#define OAM 0x04
#define SS_BG1 0x80
#define SS_BG2 0x81
#define SS_BG3 0x82
#define SS_BG4 0x83
#define SS_OAM 0x84
#define BACK 0x05
#define CLIPMODE_IN 0
#define CLIPMODE_OUT 1
#define WINDOWMASK_OR 0
#define WINDOWMASK_AND 1
#define WINDOWMASK_XOR 2
#define WINDOWMASK_XNOR 3
#define COLORMODE_ADD 0
#define COLORMODE_SUB 1
typedef struct {
word *screen; //internal buffer used to render 512x448 screen
byte *vram; //65536 bytes
byte *cgram; //512 bytes
byte *oam; //544 bytes mirrored as 1024 bytes (512-543 are mirrored to 544-1023)
word *light_table; //16 * 32768 -- applies display_brightness to bgr555 color data
//ppu.mosaic_table[ppu.mosaic_size][x] == (x / (ppu.mosaic_size + 1)) * (ppu.mosaic_size + 1)
word *mosaic_table[16];
ulong ppu_cycles, ppu_prev_cycles; //used in ppu_update_scanline()
bool display_disable; //$2100 bit 7
byte display_brightness; //$2100 bits 0-3
bool overscan;
byte visible_scanlines;
bool sprite_halve;
bool interlace, toggle_interlace;
byte interlace_frame; //0 or 1, used to alternate between scanlines rendered
bool bg_enabled[5];
bool ss_bg_enabled[5];
byte mosaic_size;
bool mosaic_enabled[4];
word bg_tilemap_loc[4];
byte bg_tile_size[4];
byte bg_tilemap_size[4];
word bg_tiledata_loc[4];
word oam_tiledata_loc;
byte bg_priority_mode;
byte oam_base_size;
byte oam_name_sel;
byte bg_mode;
word hline_pos; //0-255: inside vblank, 256-339: outside vblank
word vline_pos; //0-223: inside vblank, 224-261: outside vblank, 180 cycles/scanline
bool irq_triggered; //for $4211 read
bool virq_triggered; //prevent recursive calling
bool hirq_triggered; //prevent recursive calling
word vram_write_pos; //holds value at $2116
word vram_write_buffer;
word vram_read_buffer;
word vram_remap_mode;
word vram_inc_size; //amount to increment vram_write_pos by
byte vram_inc_reg; //increment on 2118 (0) or 2119 (1)
word cgram_write_pos; //holds value at $2121 (multiplied by 2)
word oam_write_pos; //holds value at $2102/$2103 (multiplied by 2)
ulong wram_write_pos; //holds value at $2181-$2183
word bg_hscroll_pos[4]; //$210d-$2114
word bg_vscroll_pos[4];
word m7hofs, m7vofs;
byte mul_a, mul_b;
word div_a;
byte div_b;
word r_4214, r_4216;
ulong r_2134;
bool bg_window1_enabled[5];
bool bg_window2_enabled[5];
byte bg_window1_clipmode[5];
byte bg_window2_clipmode[5];
byte window1_left, window1_right;
byte window2_left, window2_right;
bool bg_windowing_enabled[5];
bool ss_bg_windowing_enabled[5];
byte bg_window_mask[5];
bool color_window1_enabled, color_window2_enabled;
bool color_window1_clipmode, color_window2_clipmode;
byte color_window_mask;
byte color_mask, ss_color_mask;
byte addsub_mode;
byte color_mode, color_halve;
bool bg_color_enabled[6];
byte color_r, color_g, color_b;
byte active_hdma_channels;
word hdma_scanlines_remaining[8];
word hdma_index_pointer[8];
bool hdma_completed[8];
bool vcounter_enabled, hcounter_enabled;
word hirq_pos, virq_pos;
bool auto_joypad_read;
byte joypad_strobe_value;
byte latch_toggle;
word latch_vpos, latch_hpos;
word m7a, m7b, m7c, m7d, m7x, m7y;
byte mode7_repeat;
bool mode7_extbg;
bool mode7_vflip, mode7_hflip;
byte io4201;
bool counter_latched;
byte mmio_mem_43xx[0x80];
}ppustate;
/*********************
*** cpu functions ***
********************/
#define CPUSTATE_RUN 0
#define CPUSTATE_DMA 1
#define CPUSTATE_STP 2
#define MEMSPEED_SLOWROM 0
#define MEMSPEED_FASTROM 1
void add_apu_cycles(int n);
//g65816 cpu flags
#define PF_N 0x80
#define PF_V 0x40
#define PF_M 0x20
#define PF_X 0x10
#define PF_D 0x08
#define PF_I 0x04
#define PF_Z 0x02
#define PF_C 0x01
//spc700 cpu flags
#define SPF_N 0x80
#define SPF_V 0x40
#define SPF_P 0x20
#define SPF_B 0x10
#define SPF_H 0x08
#define SPF_I 0x04
#define SPF_Z 0x02
#define SPF_C 0x01
/************************
*** memory functions ***
***********************/
#define MEMSPEED_FAST 6
#define MEMSPEED_SLOW 8
#define MEMSPEED_XSLOW 12
#define MEMMAP_HIROM 0x01
#define MEMMAP_LOROM 0x02
#define MEMACCESS_NORMAL 0
#define MEMACCESS_CPU 1
#define MEMACCESS_DEBUGGER 1
enum {
MEMMODE_NONE = 0, //(no address translation)
MEMMODE_DP, //dp
MEMMODE_DPX, //dp,x
MEMMODE_DPY, //dp,y
MEMMODE_IDP, //(dp)
MEMMODE_IDPX, //(dp,x)
MEMMODE_IDPY, //(dp),y
MEMMODE_ILDP, //[dp]
MEMMODE_ILDPY, //[dp],y
MEMMODE_ADDR, //addr
MEMMODE_ADDRX, //addr,x
MEMMODE_ADDRY, //addr,y
MEMMODE_IADDRX, //(addr,x)
MEMMODE_ILADDR, //[addr]
MEMMODE_LONG, //long
MEMMODE_LONGX, //long, x
MEMMODE_SR, //sr,s
MEMMODE_ISRY, //(sr,s),y
//exchanges pbr for dbr, disables address mirroring
MEMMODE_ADDR_PC, //addr
MEMMODE_IADDR_PC, //(addr)
MEMMODE_IADDRX_PC, //(addr,x)
MEMMODE_ILADDR_PC, //[addr]
//opcode memory access types
OPMODE_DBR,
OPMODE_PBR,
OPMODE_LONG,
OPMODE_DP,
OPMODE_SP,
OPMODE_ADDR
};
#define MEMSIZE_BYTE 1
#define MEMSIZE_WORD 2
#define MEMSIZE_LONG 3
/***********************
*** misc. functions ***
**********************/
//main.cpp
void InitSNES(void);
void RunSNES(void);
void ResetSNES(void);
//cpu/g65816_ops_stack.cpp
//ulong g65816_stackread(byte size);
//void g65816_stackwrite(byte size, ulong value);
//cpu/d65816.cpp
void disas_g65816_op(void);
//apu/dspc700.cpp
void disas_spc700_op(void);
//ppu/mmio.cpp
byte mmio_read(word addr);
void mmio_write(word addr, byte value);
//ppu/ppu.cpp
void ppu_render_scanline(void);
void ppu_update_scanline(void);
byte oam_read(word addr);
void oam_write(word addr, byte value);
void PPUInit(byte first_time);
void ppu_update_dma(void);
//win/render.cpp
void UpdateDisplay(void);
//misc/libstr.cpp
ulong strhex(char *str);
ulong strdec(char *str);
+26
View File
@@ -0,0 +1,26 @@
#include "../base.h"
#include "bridge.h"
port_bridge *cpu_apu_bridge;
port_bridge::port_bridge() {
cputoapu_port[0] = cputoapu_port[1] =
cputoapu_port[2] = cputoapu_port[3] =
aputocpu_port[0] = aputocpu_port[1] =
aputocpu_port[2] = aputocpu_port[3] = 0;
}
byte port_bridge::cpu_read(byte port) {
return aputocpu_port[port & 3];
}
byte port_bridge::apu_read(byte port) {
return cputoapu_port[port & 3];
}
void port_bridge::cpu_write(byte port, byte value) {
cputoapu_port[port & 3] = value;
}
void port_bridge::apu_write(byte port, byte value) {
aputocpu_port[port & 3] = value;
}
+11
View File
@@ -0,0 +1,11 @@
class port_bridge {
public:
byte cputoapu_port[4]; //holds values written to CPU at $2140-$2143
byte aputocpu_port[4]; //holds values written to APU at $f4-$f7
port_bridge();
byte cpu_read(byte port);
byte apu_read(byte port);
void cpu_write(byte port, byte value);
void apu_write(byte port, byte value);
};
BIN
View File
Binary file not shown.
+2
View File
@@ -0,0 +1,2 @@
@nmake /NOLOGO
@pause
+1
View File
@@ -0,0 +1 @@
@nmake /NOLOGO clean
+339
View File
@@ -0,0 +1,339 @@
#include "../base.h"
#include "g65816.h"
extern g65816 *gx816;
extern debugstate debugger;
ulong _disas_relb(byte addr) {
return gx816->regs.pc + (signed char)(addr + 2);
}
ulong _disas_relw(word addr) {
return gx816->regs.pc + (signed short)(addr + 3);
}
char __disas_op_str[256];
void __disas_op(byte op, byte op0, byte op1, byte op2) {
char *s = (char*)__disas_op_str;
switch(op) {
case 0x00:sprintf(s, "brk #$%0.2x ", op0);break;
case 0x01:sprintf(s, "ora ($%0.2x,x) [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDPX, op0));break;
case 0x02:sprintf(s, "cop #$%0.2x ", op0);break;
case 0x03:sprintf(s, "ora $%0.2x,s [$%0.6x]", op0, gx816->convert_offset(MEMMODE_SR, op0));break;
case 0x04:sprintf(s, "tsb $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0x05:sprintf(s, "ora $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0x06:sprintf(s, "asl $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0x07:sprintf(s, "ora [$%0.2x] [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ILDP, op0));break;
case 0x08:sprintf(s, "php ");break;
case 0x09:
if(gx816->regs.e == true || (gx816->regs.e == false && (gx816->regs.p & 0x20)))sprintf(s, "ora #$%0.2x ", op0);
else sprintf(s, "ora #$%0.4x ", op0|op1<<8);break;
case 0x0a:sprintf(s, "asl a ");break;
case 0x0b:sprintf(s, "phd ");break;
case 0x0c:sprintf(s, "tsb $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0x0d:sprintf(s, "ora $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0x0e:sprintf(s, "asl $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0x0f:sprintf(s, "ora $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, gx816->convert_offset(MEMMODE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x10:sprintf(s, "bpl $%0.4x [$%0.6x]", _disas_relb(op0)&0xffff, _disas_relb(op0)&0xffffff);break;
case 0x11:sprintf(s, "ora ($%0.2x),y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDPY, op0));break;
case 0x12:sprintf(s, "ora ($%0.2x) [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDP, op0));break;
case 0x13:sprintf(s, "ora ($%0.2x,s),y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ISRY, op0));break;
case 0x14:sprintf(s, "trb $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0x15:sprintf(s, "ora $%0.2x,x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPX, op0));break;
case 0x16:sprintf(s, "asl $%0.2x,x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPX, op0));break;
case 0x17:sprintf(s, "ora [$%0.2x],y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ILDPY, op0));break;
case 0x18:sprintf(s, "clc ");break;
case 0x19:sprintf(s, "ora $%0.4x,y [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRY, (op0|op1<<8)));break;
case 0x1a:sprintf(s, "inc ");break;
case 0x1b:sprintf(s, "tcs ");break;
case 0x1c:sprintf(s, "trb $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0x1d:sprintf(s, "ora $%0.4x,x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRX, (op0|op1<<8)));break;
case 0x1e:sprintf(s, "asl $%0.4x,x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRX, (op0|op1<<8)));break;
case 0x1f:sprintf(s, "ora $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, gx816->convert_offset(MEMMODE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0x20:sprintf(s, "jsr $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR_PC, (op0|op1<<8)));break;
case 0x21:sprintf(s, "and ($%0.2x,x) [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDPX, op0));break;
case 0x22:sprintf(s, "jsl $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, gx816->convert_offset(MEMMODE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x23:sprintf(s, "and $%0.2x,s [$%0.6x]", op0, gx816->convert_offset(MEMMODE_SR, op0));break;
case 0x24:sprintf(s, "bit $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0x25:sprintf(s, "and $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0x26:sprintf(s, "rol $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0x27:sprintf(s, "and [$%0.2x] [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ILDP, op0));break;
case 0x28:sprintf(s, "plp ");break;
case 0x29:
if(gx816->regs.e == true || (gx816->regs.e == false && (gx816->regs.p & 0x20)))sprintf(s, "and #$%0.2x ", op0);
else sprintf(s, "and #$%0.4x ", op0|op1<<8);break;
case 0x2a:sprintf(s, "rol a ");break;
case 0x2b:sprintf(s, "pld ");break;
case 0x2c:sprintf(s, "bit $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0x2d:sprintf(s, "and $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0x2e:sprintf(s, "rol $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0x2f:sprintf(s, "and $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, gx816->convert_offset(MEMMODE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x30:sprintf(s, "bmi $%0.4x [$%0.6x]", _disas_relb(op0)&0xffff, _disas_relb(op0)&0xffffff);break;
case 0x31:sprintf(s, "and ($%0.2x),y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDPY, op0));break;
case 0x32:sprintf(s, "and ($%0.2x) [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDP, op0));break;
case 0x33:sprintf(s, "and ($%0.2x,s),y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ISRY, op0));break;
case 0x34:sprintf(s, "bit $%0.2x,x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPX, op0));break;
case 0x35:sprintf(s, "and $%0.2x,x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPX, op0));break;
case 0x36:sprintf(s, "rol $%0.2x,x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPX, op0));break;
case 0x37:sprintf(s, "and [$%0.2x],y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ILDPY, op0));break;
case 0x38:sprintf(s, "sec ");break;
case 0x39:sprintf(s, "and $%0.4x,y [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRY, (op0|op1<<8)));break;
case 0x3a:sprintf(s, "dec ");break;
case 0x3b:sprintf(s, "tsc ");break;
case 0x3c:sprintf(s, "bit $%0.4x,x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRX, (op0|op1<<8)));break;
case 0x3d:sprintf(s, "and $%0.4x,x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRX, (op0|op1<<8)));break;
case 0x3e:sprintf(s, "rol $%0.4x,x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRX, (op0|op1<<8)));break;
case 0x3f:sprintf(s, "and $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, gx816->convert_offset(MEMMODE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0x40:sprintf(s, "rti ");break;
case 0x41:sprintf(s, "eor ($%0.2x,x) [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDPX, op0));break;
case 0x42:sprintf(s, "wdm ");break;
case 0x43:sprintf(s, "eor $%0.2x,s [$%0.6x]", op0, gx816->convert_offset(MEMMODE_SR, op0));break;
case 0x44:sprintf(s, "mvp $%0.2x,$%0.2x ", op1, op0);break;
case 0x45:sprintf(s, "eor $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0x46:sprintf(s, "lsr $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0x47:sprintf(s, "eor [$%0.2x] [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ILDP, op0));break;
case 0x48:sprintf(s, "pha ");break;
case 0x49:
if(gx816->regs.e == true || (gx816->regs.e == false && (gx816->regs.p & 0x20)))sprintf(s, "eor #$%0.2x ", op0);
else sprintf(s, "eor #$%0.4x ", op0|op1<<8);break;
case 0x4a:sprintf(s, "lsr a ");break;
case 0x4b:sprintf(s, "phk ");break;
case 0x4c:sprintf(s, "jmp $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR_PC, (op0|op1<<8)));break;
case 0x4d:sprintf(s, "eor $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0x4e:sprintf(s, "lsr $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0x4f:sprintf(s, "eor $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, gx816->convert_offset(MEMMODE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x50:sprintf(s, "bvc $%0.4x [$%0.6x]", _disas_relb(op0)&0xffff, _disas_relb(op0)&0xffffff);break;
case 0x51:sprintf(s, "eor ($%0.2x),y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDPY, op0));break;
case 0x52:sprintf(s, "eor ($%0.2x) [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDP, op0));break;
case 0x53:sprintf(s, "eor ($%0.2x,s),y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ISRY, op0));break;
case 0x54:sprintf(s, "mvn $%0.2x,$%0.2x ", op1, op0);break;
case 0x55:sprintf(s, "eor $%0.2x,x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPX, op0));break;
case 0x56:sprintf(s, "lsr $%0.2x,x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPX, op0));break;
case 0x57:sprintf(s, "eor [$%0.2x],y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ILDPY, op0));break;
case 0x58:sprintf(s, "cli ");break;
case 0x59:sprintf(s, "eor $%0.4x,y [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRY, (op0|op1<<8)));break;
case 0x5a:sprintf(s, "phy ");break;
case 0x5b:sprintf(s, "tcd ");break;
case 0x5c:sprintf(s, "jml $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, gx816->convert_offset(MEMMODE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x5d:sprintf(s, "eor $%0.4x,x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRX, (op0|op1<<8)));break;
case 0x5e:sprintf(s, "lsr $%0.4x,x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRX, (op0|op1<<8)));break;
case 0x5f:sprintf(s, "eor $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, gx816->convert_offset(MEMMODE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0x60:sprintf(s, "rts ");break;
case 0x61:sprintf(s, "adc ($%0.2x,x) [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDPX, op0));break;
case 0x62:sprintf(s, "per $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0x63:sprintf(s, "adc $%0.2x,s [$%0.6x]", op0, gx816->convert_offset(MEMMODE_SR, op0));break;
case 0x64:sprintf(s, "stz $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0x65:sprintf(s, "adc $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0x66:sprintf(s, "ror $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0x67:sprintf(s, "adc [$%0.2x] [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ILDP, op0));break;
case 0x68:sprintf(s, "pla ");break;
case 0x69:
if(gx816->regs.e == true || (gx816->regs.e == false && (gx816->regs.p & 0x20)))sprintf(s, "adc #$%0.2x ", op0);
else sprintf(s, "adc #$%0.4x ", op0|op1<<8);break;
case 0x6a:sprintf(s, "ror a ");break;
case 0x6b:sprintf(s, "rtl ");break;
case 0x6c:sprintf(s, "jmp ($%0.4x) [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_IADDR_PC, (op0|op1<<8)));break;
case 0x6d:sprintf(s, "adc $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0x6e:sprintf(s, "ror $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0x6f:sprintf(s, "adc $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, gx816->convert_offset(MEMMODE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x70:sprintf(s, "bvs $%0.4x [$%0.6x]", _disas_relb(op0)&0xffff, _disas_relb(op0)&0xffffff);break;
case 0x71:sprintf(s, "adc ($%0.2x),y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDPY, op0));break;
case 0x72:sprintf(s, "adc ($%0.2x) [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDP, op0));break;
case 0x73:sprintf(s, "adc ($%0.2x,s),y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ISRY, op0));break;
case 0x74:sprintf(s, "stz $%0.2x,x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPX, op0));break;
case 0x75:sprintf(s, "adc $%0.2x,x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPX, op0));break;
case 0x76:sprintf(s, "ror $%0.2x,x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPX, op0));break;
case 0x77:sprintf(s, "adc [$%0.2x],y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ILDPY, op0));break;
case 0x78:sprintf(s, "sei ");break;
case 0x79:sprintf(s, "adc $%0.4x,y [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRY, (op0|op1<<8)));break;
case 0x7a:sprintf(s, "ply ");break;
case 0x7b:sprintf(s, "tdc ");break;
case 0x7c:sprintf(s, "jmp ($%0.4x,x) [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_IADDRX_PC, (op0|op1<<8)));break;
case 0x7d:sprintf(s, "adc $%0.4x,x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRX, (op0|op1<<8)));break;
case 0x7e:sprintf(s, "ror $%0.4x,x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRX, (op0|op1<<8)));break;
case 0x7f:sprintf(s, "adc $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, gx816->convert_offset(MEMMODE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0x80:sprintf(s, "bra $%0.4x [$%0.6x]", _disas_relb(op0)&0xffff, _disas_relb(op0)&0xffffff);break;
case 0x81:sprintf(s, "sta ($%0.2x,x) [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDPX, op0));break;
case 0x82:sprintf(s, "brl $%0.4x [$%0.6x]", _disas_relw(op0|op1<<8)&0xffff, _disas_relw(op0|op1<<8)&0xffffff);break;
case 0x83:sprintf(s, "sta $%0.2x,s [$%0.6x]", op0, gx816->convert_offset(MEMMODE_SR, op0));break;
case 0x84:sprintf(s, "sty $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0x85:sprintf(s, "sta $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0x86:sprintf(s, "stx $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0x87:sprintf(s, "sta [$%0.2x] [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ILDP, op0));break;
case 0x88:sprintf(s, "dey ");break;
case 0x89:
if(gx816->regs.e == true || (gx816->regs.e == false && (gx816->regs.p & 0x20)))sprintf(s, "bit #$%0.2x ", op0);
else sprintf(s, "bit #$%0.4x ", op0|op1<<8);break;
case 0x8a:sprintf(s, "txa ");break;
case 0x8b:sprintf(s, "phb ");break;
case 0x8c:sprintf(s, "sty $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0x8d:sprintf(s, "sta $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0x8e:sprintf(s, "stx $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0x8f:sprintf(s, "sta $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, gx816->convert_offset(MEMMODE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x90:sprintf(s, "bcc $%0.4x [$%0.6x]", _disas_relb(op0)&0xffff, _disas_relb(op0)&0xffffff);break;
case 0x91:sprintf(s, "sta ($%0.2x),y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDPY, op0));break;
case 0x92:sprintf(s, "sta ($%0.2x) [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDP, op0));break;
case 0x93:sprintf(s, "sta ($%0.2x,s),y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ISRY, op0));break;
case 0x94:sprintf(s, "sty $%0.2x,x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPX, op0));break;
case 0x95:sprintf(s, "sta $%0.2x,x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPX, op0));break;
case 0x96:sprintf(s, "stx $%0.2x,y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPY, op0));break;
case 0x97:sprintf(s, "sta [$%0.2x],y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ILDPY, op0));break;
case 0x98:sprintf(s, "tya ");break;
case 0x99:sprintf(s, "sta $%0.4x,y [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRY, (op0|op1<<8)));break;
case 0x9a:sprintf(s, "txs ");break;
case 0x9b:sprintf(s, "txy ");break;
case 0x9c:sprintf(s, "stz $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0x9d:sprintf(s, "sta $%0.4x,x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRX, (op0|op1<<8)));break;
case 0x9e:sprintf(s, "stz $%0.4x,x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRX, (op0|op1<<8)));break;
case 0x9f:sprintf(s, "sta $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, gx816->convert_offset(MEMMODE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0xa0:
if(gx816->regs.e == true || (gx816->regs.e == false && (gx816->regs.p & PF_X)))sprintf(s, "ldy #$%0.2x ", op0);
else sprintf(s, "ldy #$%0.4x ", op0|op1<<8);break;
case 0xa1:sprintf(s, "lda ($%0.2x,x) [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDPX, op0));break;
case 0xa2:
if(gx816->regs.e == true || (gx816->regs.e == false && (gx816->regs.p & PF_X)))sprintf(s, "ldx #$%0.2x ", op0);
else sprintf(s, "ldx #$%0.4x ", op0|op1<<8);break;
case 0xa3:sprintf(s, "lda $%0.2x,s [$%0.6x]", op0, gx816->convert_offset(MEMMODE_SR, op0));break;
case 0xa4:sprintf(s, "ldy $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0xa5:sprintf(s, "lda $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0xa6:sprintf(s, "ldx $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0xa7:sprintf(s, "lda [$%0.2x] [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ILDP, op0));break;
case 0xa8:sprintf(s, "tay ");break;
case 0xa9:
if(gx816->regs.e == true || (gx816->regs.e == false && (gx816->regs.p & 0x20)))sprintf(s, "lda #$%0.2x ", op0);
else sprintf(s, "lda #$%0.4x ", op0|op1<<8);break;
case 0xaa:sprintf(s, "tax ");break;
case 0xab:sprintf(s, "plb ");break;
case 0xac:sprintf(s, "ldy $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0xad:sprintf(s, "lda $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0xae:sprintf(s, "ldx $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0xaf:sprintf(s, "lda $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, gx816->convert_offset(MEMMODE_LONG, (op0|op1<<8|op2<<16)));break;
case 0xb0:sprintf(s, "bcs $%0.4x [$%0.6x]", _disas_relb(op0)&0xffff, _disas_relb(op0)&0xffffff);break;
case 0xb1:sprintf(s, "lda ($%0.2x),y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDPY, op0));break;
case 0xb2:sprintf(s, "lda ($%0.2x) [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDP, op0));break;
case 0xb3:sprintf(s, "lda ($%0.2x,s),y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ISRY, op0));break;
case 0xb4:sprintf(s, "ldy $%0.2x,x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPX, op0));break;
case 0xb5:sprintf(s, "lda $%0.2x,x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPX, op0));break;
case 0xb6:sprintf(s, "ldx $%0.2x,y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPY, op0));break;
case 0xb7:sprintf(s, "lda [$%0.2x],y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ILDPY, op0));break;
case 0xb8:sprintf(s, "clv ");break;
case 0xb9:sprintf(s, "lda $%0.4x,y [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRY, (op0|op1<<8)));break;
case 0xba:sprintf(s, "tsx ");break;
case 0xbb:sprintf(s, "tyx ");break;
case 0xbc:sprintf(s, "ldy $%0.4x,x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRX, (op0|op1<<8)));break;
case 0xbd:sprintf(s, "lda $%0.4x,x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRX, (op0|op1<<8)));break;
case 0xbe:sprintf(s, "ldx $%0.4x,y [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRY, (op0|op1<<8)));break;
case 0xbf:sprintf(s, "lda $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, gx816->convert_offset(MEMMODE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0xc0:
if(gx816->regs.e == true || (gx816->regs.e == false && (gx816->regs.p & PF_X)))sprintf(s, "cpy #$%0.2x ", op0);
else sprintf(s, "cpy #$%0.4x ", op0|op1<<8);break;
case 0xc1:sprintf(s, "cmp ($%0.2x,x) [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDPX, op0));break;
case 0xc2:sprintf(s, "rep #$%0.2x ", op0);break;
case 0xc3:sprintf(s, "cmp $%0.2x,s [$%0.6x]", op0, gx816->convert_offset(MEMMODE_SR, op0));break;
case 0xc4:sprintf(s, "cpy $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0xc5:sprintf(s, "cmp $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0xc6:sprintf(s, "dec $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0xc7:sprintf(s, "cmp [$%0.2x] [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ILDP, op0));break;
case 0xc8:sprintf(s, "iny ");break;
case 0xc9:
if(gx816->regs.e == true || (gx816->regs.e == false && (gx816->regs.p & 0x20)))sprintf(s, "cmp #$%0.2x ", op0);
else sprintf(s, "cmp #$%0.4x ", op0|op1<<8);break;
case 0xca:sprintf(s, "dex ");break;
case 0xcb:sprintf(s, "wai ");break;
case 0xcc:sprintf(s, "cpy $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0xcd:sprintf(s, "cmp $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0xce:sprintf(s, "dec $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0xcf:sprintf(s, "cmp $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, gx816->convert_offset(MEMMODE_LONG, (op0|op1<<8|op2<<16)));break;
case 0xd0:sprintf(s, "bne $%0.4x [$%0.6x]", _disas_relb(op0)&0xffff, _disas_relb(op0)&0xffffff);break;
case 0xd1:sprintf(s, "cmp ($%0.2x),y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDPY, op0));break;
case 0xd2:sprintf(s, "cmp ($%0.2x) [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDP, op0));break;
case 0xd3:sprintf(s, "cmp ($%0.2x,s),y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ISRY, op0));break;
case 0xd4:sprintf(s, "pei ($%0.2x) [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDP, op0));break;
case 0xd5:sprintf(s, "cmp $%0.2x,x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPX, op0));break;
case 0xd6:sprintf(s, "dec $%0.2x,x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPX, op0));break;
case 0xd7:sprintf(s, "cmp [$%0.2x],y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ILDPY, op0));break;
case 0xd8:sprintf(s, "cld ");break;
case 0xd9:sprintf(s, "cmp $%0.4x,y [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRY, (op0|op1<<8)));break;
case 0xda:sprintf(s, "phx ");break;
case 0xdb:sprintf(s, "stp ");break;
case 0xdc:sprintf(s, "jmp [$%0.4x] [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ILADDR_PC, (op0|op1<<8)));break;
case 0xdd:sprintf(s, "cmp $%0.4x,x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRX, (op0|op1<<8)));break;
case 0xde:sprintf(s, "dec $%0.4x,x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRX, (op0|op1<<8)));break;
case 0xdf:sprintf(s, "cmp $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, gx816->convert_offset(MEMMODE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0xe0:
if(gx816->regs.e == true || (gx816->regs.e == false && (gx816->regs.p & PF_X)))sprintf(s, "cpx #$%0.2x ", op0);
else sprintf(s, "cpx #$%0.4x ", op0|op1<<8);break;
case 0xe1:sprintf(s, "sbc ($%0.2x,x) [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDPX, op0));break;
case 0xe2:sprintf(s, "sep #$%0.2x ", op0);break;
case 0xe3:sprintf(s, "sbc $%0.2x,s [$%0.6x]", op0, gx816->convert_offset(MEMMODE_SR, op0));break;
case 0xe4:sprintf(s, "cpx $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0xe5:sprintf(s, "sbc $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0xe6:sprintf(s, "inc $%0.2x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DP, op0));break;
case 0xe7:sprintf(s, "sbc [$%0.2x] [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ILDP, op0));break;
case 0xe8:sprintf(s, "inx ");break;
case 0xe9:
if(gx816->regs.e == true || (gx816->regs.e == false && (gx816->regs.p & 0x20)))sprintf(s, "sbc #$%0.2x ", op0);
else sprintf(s, "sbc #$%0.4x ", op0|op1<<8);break;
case 0xea:sprintf(s, "nop ");break;
case 0xeb:sprintf(s, "xba ");break;
case 0xec:sprintf(s, "cpx $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0xed:sprintf(s, "sbc $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0xee:sprintf(s, "inc $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0xef:sprintf(s, "sbc $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, gx816->convert_offset(MEMMODE_LONG, (op0|op1<<8|op2<<16)));break;
case 0xf0:sprintf(s, "beq $%0.4x [$%0.6x]", _disas_relb(op0)&0xffff, _disas_relb(op0)&0xffffff);break;
case 0xf1:sprintf(s, "sbc ($%0.2x),y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDPY, op0));break;
case 0xf2:sprintf(s, "sbc ($%0.2x) [$%0.6x]", op0, gx816->convert_offset(MEMMODE_IDP, op0));break;
case 0xf3:sprintf(s, "sbc ($%0.2x,s),y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ISRY, op0));break;
case 0xf4:sprintf(s, "pea $%0.4x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDR, (op0|op1<<8)));break;
case 0xf5:sprintf(s, "sbc $%0.2x,x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPX, op0));break;
case 0xf6:sprintf(s, "inc $%0.2x,x [$%0.6x]", op0, gx816->convert_offset(MEMMODE_DPX, op0));break;
case 0xf7:sprintf(s, "sbc [$%0.2x],y [$%0.6x]", op0, gx816->convert_offset(MEMMODE_ILDPY, op0));break;
case 0xf8:sprintf(s, "sed ");break;
case 0xf9:sprintf(s, "sbc $%0.4x,y [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRY, (op0|op1<<8)));break;
case 0xfa:sprintf(s, "plx ");break;
case 0xfb:sprintf(s, "xce ");break;
case 0xfc:sprintf(s, "jsr ($%0.4x,x) [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_IADDRX_PC, (op0|op1<<8)));break;
case 0xfd:sprintf(s, "sbc $%0.4x,x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRX, (op0|op1<<8)));break;
case 0xfe:sprintf(s, "inc $%0.4x,x [$%0.6x]", op0|op1<<8, gx816->convert_offset(MEMMODE_ADDRX, (op0|op1<<8)));break;
case 0xff:sprintf(s, "sbc $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, gx816->convert_offset(MEMMODE_LONGX, (op0|op1<<8|op2<<16)));break;
}
}
void disas_g65816_op(void) {
byte op, op0, op1, op2;
char str0[256], str1[256], str2[256];
if(debug_write_status() == DEBUGWRITE_NONE)return;
op = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, gx816->regs.pc, MEMACCESS_DEBUGGER);
op0 = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, gx816->regs.pc + 1, MEMACCESS_DEBUGGER);
op1 = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, gx816->regs.pc + 2, MEMACCESS_DEBUGGER);
op2 = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, gx816->regs.pc + 3, MEMACCESS_DEBUGGER);
strcpy(__disas_op_str, "??? ");
__disas_op(op, op0, op1, op2);
if(gx816->regs.e == true) {
sprintf(str1, "%c%c%c%c%c%c%c%c E",
(gx816->regs.p & 0x80)?'N':'n',
(gx816->regs.p & 0x40)?'V':'v',
(gx816->regs.p & 0x20)?'1':'0',
(gx816->regs.p & 0x10)?'B':'b',
(gx816->regs.p & 0x08)?'D':'d',
(gx816->regs.p & 0x04)?'I':'i',
(gx816->regs.p & 0x02)?'Z':'z',
(gx816->regs.p & 0x01)?'C':'c');
} else {
sprintf(str1, "%c%c%c%c%c%c%c%c N",
(gx816->regs.p & 0x80)?'N':'n',
(gx816->regs.p & 0x40)?'V':'v',
(gx816->regs.p & 0x20)?'M':'m',
(gx816->regs.p & 0x10)?'X':'x',
(gx816->regs.p & 0x08)?'D':'d',
(gx816->regs.p & 0x04)?'I':'i',
(gx816->regs.p & 0x02)?'Z':'z',
(gx816->regs.p & 0x01)?'C':'c');
}
dprintf(DEBUGMSG_CPU, "%0.6x %s A:%0.4x X:%0.4x Y:%0.4x S:%0.4x D:%0.4x DB:%0.2x %s", gx816->regs.pc, __disas_op_str,
gx816->regs.a.w, gx816->regs.x, gx816->regs.y, gx816->regs.s,
gx816->regs.d, gx816->regs.db, str1);
}
+240
View File
@@ -0,0 +1,240 @@
#include "../base.h"
#include "../timing/timing.h"
#include "g65816.h"
extern emustate emu_state;
extern debugstate debugger;
extern ppustate ppu;
extern snes_timer *snes_time;
g65816 *gx816;
#include "g65816_ops.cpp"
void g65816::LoadROM(void) {
FILE *fp;
ulong fsize;
word header_offset = 0;
word cksum, icksum;
byte t;
int i;
dprintf("* Loading [%s]...", emu_state.rom_name);
fp = fopen(emu_state.rom_name, "rb");
if(!fp)return;
fseek(fp, 0, SEEK_END);
fsize = ftell(fp);
fseek(fp, 0, SEEK_SET);
map = MEMMAP_LOROM;
if((fsize & 0x000fff) == 0x000200)header_offset = 512;
fseek(fp, 0x7fdc + header_offset, SEEK_SET);
cksum = fgetc(fp) | fgetc(fp) << 8;
icksum = fgetc(fp) | fgetc(fp) << 8;
if(cksum + icksum == 0xffff)map = MEMMAP_LOROM;
fseek(fp, 0xffdc + header_offset, SEEK_SET);
cksum = fgetc(fp) | fgetc(fp) << 8;
icksum = fgetc(fp) | fgetc(fp) << 8;
if(cksum + icksum == 0xffff)map = MEMMAP_HIROM;
fseek(fp, 0 + header_offset, SEEK_SET);
fsize -= header_offset;
dprintf("* ROM detected as: %s", (map == MEMMAP_LOROM)?"LoROM":"HiROM");
InitializeROM(map);
fread(rom, 1, fsize, fp);
t = (mem_read(MEMMODE_NONE, MEMSIZE_BYTE, 0x00ffd8) & 7);
switch(t) {
case 0: sram_size = 0; break;
case 1: sram_size = 2 * 1024;break;
case 2: sram_size = 4 * 1024;break;
case 3: sram_size = 8 * 1024;break;
case 4: sram_size = 16 * 1024;break;
case 5: sram_size = 32 * 1024;break;
case 6: sram_size = 64 * 1024;break;
case 7: sram_size = 128 * 1024;break;
default:sram_size = 0; break;
}
dprintf("* SRAM Size: %dkb", sram_size / 1024);
//pbr is loaded with 00, and 16-bit pc is loaded with reset vector at 0xfffc
//upon power on and at first reset
regs.pc = mem_read(MEMMODE_LONG, MEMSIZE_WORD, 0x00fffc);
fclose(fp);
if(sram_size != 0) {
fp = fopen(emu_state.sram_name, "rb");
//create sram file if it does not exist
if(!fp) {
fp = fopen(emu_state.sram_name, "wb");
for(i=0;i<sram_size;i++) {
fputc(0, fp);
}
fclose(fp);
fp = fopen(emu_state.sram_name, "rb");
}
fseek(fp, 0, SEEK_END);
fsize = ftell(fp);
//fix sram size if it is smaller than actual size
if(fsize < sram_size) {
fclose(fp);
fp = fopen(emu_state.sram_name, "rb+wb");
fseek(fp, 0, SEEK_END);
while(fsize < sram_size) {
fputc(0, fp);
fsize++;
}
fclose(fp);
fp = fopen(emu_state.sram_name, "rb");
}
//read file into sram
fseek(fp, 0, SEEK_SET);
fread(sram, 1, sram_size, fp);
fclose(fp);
}
}
void g65816::PowerOn(byte first_time) {
//default register states
regs.a.w = regs.x = regs.y = 0x0000;
regs.d = 0x0000;
regs.s = 0x01ff;
regs.db = 0x00;
regs.p = 0x34;
regs.e = true;
snes_time->master_cycles = 0;
memory_speed = MEMSPEED_SLOWROM;
wai_interrupt_occurred = false;
InitializeWRAM(0x00);
PPUInit(first_time);
UpdateDisplay();
snes_time->set_speed_map(MEMSPEED_SLOWROM);
cpu_state = CPUSTATE_RUN;
}
void g65816::Reset(void) {
regs.x &= 0xff;
regs.y &= 0xff;
regs.s = 0x0100 | (regs.s & 0xff);
regs.d = 0x0000;
regs.db = 0x00;
regs.p = 0x34;
regs.e = true;
regs.pc = mem_read(MEMMODE_LONG, MEMSIZE_WORD, 0x00fffc);
snes_time->master_cycles = 0;
memory_speed = MEMSPEED_SLOWROM;
wai_interrupt_occurred = false;
PPUInit(0); //0 blocks reallocating memory for vram, cgram, etc.
UpdateDisplay();
snes_time->set_speed_map(MEMSPEED_SLOWROM);
cpu_state = CPUSTATE_RUN;
}
/***********
*** 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 g65816::InvokeIRQ(word addr) {
snes_time->add_cpu_icycles(2); //1,2 [i/o]
gx816->stack_write(gx816->regs.pc >> 16); //3 [write pbr]
gx816->stack_write(gx816->regs.pc >> 8); //4 [write pch]
gx816->stack_write(gx816->regs.pc); //5 [write pcl]
gx816->stack_write(gx816->regs.p); //6 [write p]
gx816->op.r.p.l = gx816->op_read(OPMODE_ADDR, addr); //7 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_ADDR, addr + 1); //8 [read high]
gx816->regs.pc = gx816->op.r.w;
gx816->regs.p |= PF_I;
wai_interrupt_occurred = true;
snes_time->update_timer();
}
void g65816::exec_op(void) {
FILE *fp;
byte op;
int i;
static ulong sram_save_tick = 0;
if(cpu_state == CPUSTATE_RUN || cpu_state == CPUSTATE_STP) {
op = mem_read(MEMMODE_NONE, MEMSIZE_BYTE, gx816->regs.pc);
if(regs.e == true)g65816_optbl_e[op]();
else switch((regs.p & 0x30)) {
case 0x30:g65816_optbl_MX[op]();break;
case 0x20:g65816_optbl_Mx[op]();break;
case 0x10:g65816_optbl_mX[op]();break;
case 0x00:g65816_optbl_mx[op]();break;
}
debugger.cpu_op_executed = true;
debugger.disas_cpu_op = true;
snes_time->update_timer();
} else if(cpu_state == CPUSTATE_DMA) {
ppu_update_dma();
snes_time->update_timer();
}
snes_time->update_timer_events();
ppu_update_scanline();
//see if we need to backup sram to a file yet...
if(sram_size != 0) {
sram_save_tick++;
if(sram_save_tick >= emu_state.sram_save_tick_count) {
sram_save_tick = 0;
fp = fopen(emu_state.sram_name, "wb");
fwrite(sram, 1, sram_size, fp);
fclose(fp);
}
}
debug_test_bp(BPSRC_MEM, BP_EXEC, gx816->regs.pc, 0);
}
void g65816::Run(void) {
if(snes_time->bridge.apu_cycles >= snes_time->bridge.cpu_cycles) {
exec_op();
}
if(snes_time->bridge.cpu_cycles >= 65536 && snes_time->bridge.apu_cycles >= 65536) {
snes_time->bridge.cpu_cycles &= 65535;
snes_time->bridge.apu_cycles &= 65535;
}
}
g65816::g65816() {
int i;
rom = (byte*)malloc(0x600000);
wram = (byte*)malloc(0x020000);
sram = (byte*)malloc(0x0e0000);
nmi_enabled = false;
nmi_pin = 0;
op.dp = op.sp = 0x00;
op.r.l = 0x000000;
op.aa.l = 0x000000;
}
g65816::~g65816() {
if(rom)free(rom);
if(wram)free(wram);
if(sram)free(sram);
}
+87
View File
@@ -0,0 +1,87 @@
/*
regs.dc is not a real register. it is used to store the data counter
for reading from / writing to memory locations. it is also needed
to emulate slowrom / fastrom, as the speed varies depending on the
location where the memory was accessed.
*/
class g65816 {
public:
//cpu declarations
byte cpu_state;
struct {
ulong pc;
union {
byte b;
word w;
struct { byte l, h; }p;
}a;
word x, y, d, s;
byte db, p;
bool e;
}regs;
struct {
byte dp, sp;
union {
byte b;
word w;
ulong l;
struct { byte l, h, b; }p;
}r;
union {
word w;
ulong l;
struct { byte l, h, b; }p;
}aa;
ulong addr, iaddr;
bool c2, c4;
}op;
byte memory_speed;
byte nmi_pin;
bool nmi_enabled;
bool wai_interrupt_occurred;
//memory declarations
byte *wram, *sram, *rom;
ulong map;
ulong sram_size;
//cpu functions (cpu/g65816.cpp)
void Run(void);
void LoadROM(void);
void PowerOn(byte first_time);
void Reset(void);
void InvokeIRQ(word addr);
//memory functions (mem/memory.cpp)
void exec_op(void);
void InitializeROM(byte memory_map);
void InitializeWRAM(byte value);
ulong mirror_offset(ulong offset);
ulong convert_offset(byte read_mode, ulong addr, bool mirror = true);
//ulong adjust_base_offset(byte read_mode, ulong addr);
//ulong read_indirect_address(byte read_mode, ulong addr);
//ulong get_dc(byte read_mode, ulong addr);
byte mem_getbyte_direct(ulong addr, byte access_mode = MEMACCESS_NORMAL);
byte mem_getbyte(ulong addr, byte access_mode = MEMACCESS_NORMAL);
void mem_putbyte_direct(ulong addr, byte value, byte access_mode = MEMACCESS_NORMAL);
void mem_putbyte(ulong addr, byte value, byte access_mode = MEMACCESS_NORMAL);
ulong mem_read(byte read_mode, byte read_size, ulong addr, byte access_mode = MEMACCESS_NORMAL);
void mem_write(byte write_mode, byte write_size, ulong addr, ulong value, byte access_mode = MEMACCESS_NORMAL);
ulong read_operand(byte size);
byte op_read(byte mode, ulong addr);
void op_write(byte mode, ulong addr, byte value);
byte stack_read(void);
void stack_write(byte value);
void op_cond(byte c, ulong n0 = 0, ulong n1 = 0);
ulong rom_read(ulong addr, byte read_size);
void rom_write(ulong addr, ulong v, byte write_size);
g65816();
~g65816();
};
+162
View File
@@ -0,0 +1,162 @@
#define g65816_setn() gx816->regs.p |= PF_N
#define g65816_clrn() gx816->regs.p &= ~PF_N
#define g65816_setv() gx816->regs.p |= PF_V
#define g65816_clrv() gx816->regs.p &= ~PF_V
#define g65816_setm() gx816->regs.p |= PF_M
#define g65816_clrm() gx816->regs.p &= ~PF_M
#define g65816_setx() gx816->regs.p |= PF_X
#define g65816_clrx() gx816->regs.p &= ~PF_X
#define g65816_setd() gx816->regs.p |= PF_D
#define g65816_clrd() gx816->regs.p &= ~PF_D
#define g65816_seti() gx816->regs.p |= PF_I
#define g65816_clri() gx816->regs.p &= ~PF_I
#define g65816_setz() gx816->regs.p |= PF_Z
#define g65816_clrz() gx816->regs.p &= ~PF_Z
#define g65816_setc() gx816->regs.p |= PF_C
#define g65816_clrc() gx816->regs.p &= ~PF_C
#define g65816_testn(x) if(x)g65816_setn(); else g65816_clrn()
#define g65816_testv(x) if(x)g65816_setv(); else g65816_clrv()
#define g65816_testd(x) if(x)g65816_setd(); else g65816_clrd()
#define g65816_testi(x) if(x)g65816_seti(); else g65816_clri()
#define g65816_testz(x) if(x)g65816_setz(); else g65816_clrz()
#define g65816_testc(x) if(x)g65816_setc(); else g65816_clrc()
//increment program counter, wrap around pbr
#define g65816_incpc(__n) gx816->regs.pc = (gx816->regs.pc & 0xff0000) | (word)(gx816->regs.pc + __n)
/*
vpa = 1, vda = 1 -> add_cpu_pcycles (opcode fetch)
vpa = 1, vda = 0 -> add_cpu_pcycles (operand fetch)
vpa = 0, vda = 1 -> add_cpu_dcycles (memory fetch)
vpa = 0, vda = 0 -> add_cpu_icycles (internal operation)
*/
//opcode functions
#include "g65816_ops_adc.cpp"
#include "g65816_ops_and.cpp"
#include "g65816_ops_cmp.cpp"
#include "g65816_ops_eor.cpp"
#include "g65816_ops_lda.cpp"
#include "g65816_ops_ora.cpp"
#include "g65816_ops_sbc.cpp"
#include "g65816_ops_sta.cpp"
#include "g65816_ops_incdec.cpp"
#include "g65816_ops_shift.cpp"
#include "g65816_ops_stack.cpp"
#include "g65816_ops_pc.cpp"
#include "g65816_ops_misc.cpp"
vfunc g65816_optbl_e[256] = { // g65816_optbl_e, g65816_optbl_e, g65816_optbl_e,
// ----------------------x0, ----------------------x1, ----------------------x2, ----------------------x3, -------- ----------------------x4, ----------------------x5, ----------------------x6, ----------------------x7, -------- ----------------------x8, ----------------------x9, ----------------------xa, ----------------------xb, -------- ----------------------xc, ----------------------xd, ----------------------xe, ----------------------xf,
/* 0x */ g65816_op_brk, g65816_op_ora_idpxb, g65816_op_cop, g65816_op_ora_srb, /* 0x */ g65816_op_tsb_dpb, g65816_op_ora_dpb, g65816_op_asl_dpb, g65816_op_ora_ildpb, /* 0x */ g65816_op_php, g65816_op_ora_constb, g65816_op_aslb, g65816_op_phd, /* 0x */ g65816_op_tsb_addrb, g65816_op_ora_addrb, g65816_op_asl_addrb, g65816_op_ora_longb,
/* 1x */ g65816_op_bpl, g65816_op_ora_idpyb, g65816_op_ora_idpb, g65816_op_ora_isryb, /* 1x */ g65816_op_trb_dpb, g65816_op_ora_dpxb, g65816_op_asl_dpxb, g65816_op_ora_ildpyb, /* 1x */ g65816_op_clc, g65816_op_ora_addryb, g65816_op_incb, g65816_op_tcse, /* 1x */ g65816_op_trb_addrb, g65816_op_ora_addrxb, g65816_op_asl_addrxb, g65816_op_ora_longxb,
/* 2x */ g65816_op_jsr_addr, g65816_op_and_idpxb, g65816_op_jsr_long, g65816_op_and_srb, /* 2x */ g65816_op_bit_dpb, g65816_op_and_dpb, g65816_op_rol_dpb, g65816_op_and_ildpb, /* 2x */ g65816_op_plp, g65816_op_and_constb, g65816_op_rolb, g65816_op_pld, /* 2x */ g65816_op_bit_addrb, g65816_op_and_addrb, g65816_op_rol_addrb, g65816_op_and_longb,
/* 3x */ g65816_op_bmi, g65816_op_and_idpyb, g65816_op_and_idpb, g65816_op_and_isryb, /* 3x */ g65816_op_bit_dpxb, g65816_op_and_dpxb, g65816_op_rol_dpxb, g65816_op_and_ildpyb, /* 3x */ g65816_op_sec, g65816_op_and_addryb, g65816_op_decb, g65816_op_tsce, /* 3x */ g65816_op_bit_addrxb, g65816_op_and_addrxb, g65816_op_rol_addrxb, g65816_op_and_longxb,
/* 4x */ g65816_op_rtie, g65816_op_eor_idpxb, g65816_op_wdm, g65816_op_eor_srb, /* 4x */ g65816_op_mvp, g65816_op_eor_dpb, g65816_op_lsr_dpb, g65816_op_eor_ildpb, /* 4x */ g65816_op_phab, g65816_op_eor_constb, g65816_op_lsrb, g65816_op_phk, /* 4x */ g65816_op_jmp_addr, g65816_op_eor_addrb, g65816_op_lsr_addrb, g65816_op_eor_longb,
/* 5x */ g65816_op_bvc, g65816_op_eor_idpyb, g65816_op_eor_idpb, g65816_op_eor_isryb, /* 5x */ g65816_op_mvn, g65816_op_eor_dpxb, g65816_op_lsr_dpxb, g65816_op_eor_ildpyb, /* 5x */ g65816_op_cli, g65816_op_eor_addryb, g65816_op_phyb, g65816_op_tcd, /* 5x */ g65816_op_jmp_long, g65816_op_eor_addrxb, g65816_op_lsr_addrxb, g65816_op_eor_longxb,
/* 6x */ g65816_op_rts, g65816_op_adc_idpxb, g65816_op_per, g65816_op_adc_srb, /* 6x */ g65816_op_stz_dpb, g65816_op_adc_dpb, g65816_op_ror_dpb, g65816_op_adc_ildpb, /* 6x */ g65816_op_plab, g65816_op_adc_constb, g65816_op_rorb, g65816_op_rtl, /* 6x */ g65816_op_jmp_iaddr, g65816_op_adc_addrb, g65816_op_ror_addrb, g65816_op_adc_longb,
/* 7x */ g65816_op_bvs, g65816_op_adc_idpyb, g65816_op_adc_idpb, g65816_op_adc_isryb, /* 7x */ g65816_op_stz_dpxb, g65816_op_adc_dpxb, g65816_op_ror_dpxb, g65816_op_adc_ildpyb, /* 7x */ g65816_op_sei, g65816_op_adc_addryb, g65816_op_plyb, g65816_tdc, /* 7x */ g65816_op_jmp_iaddrx, g65816_op_adc_addrxb, g65816_op_ror_addrxb, g65816_op_adc_longxb,
/* 8x */ g65816_op_bra, g65816_op_sta_idpxb, g65816_op_brl, g65816_op_sta_srb, /* 8x */ g65816_op_sty_dpb, g65816_op_sta_dpb, g65816_op_stx_dpb, g65816_op_sta_ildpb, /* 8x */ g65816_op_deyb, g65816_op_bit_constb, g65816_op_txab, g65816_op_phb, /* 8x */ g65816_op_sty_addrb, g65816_op_sta_addrb, g65816_op_stx_addrb, g65816_op_sta_longb,
/* 9x */ g65816_op_bcc, g65816_op_sta_idpyb, g65816_op_sta_idpb, g65816_op_sta_isryb, /* 9x */ g65816_op_sty_dpxb, g65816_op_sta_dpxb, g65816_op_stx_dpyb, g65816_op_sta_ildpyb, /* 9x */ g65816_op_tyab, g65816_op_sta_addryb, g65816_op_txsb, g65816_op_txyb, /* 9x */ g65816_op_stz_addrb, g65816_op_sta_addrxb, g65816_op_stz_addrxb, g65816_op_sta_longxb,
/* ax */ g65816_op_ldy_constb, g65816_op_lda_idpxb, g65816_op_ldx_constb, g65816_op_lda_srb, /* ax */ g65816_op_ldy_dpb, g65816_op_lda_dpb, g65816_op_ldx_dpb, g65816_op_lda_ildpb, /* ax */ g65816_op_tayb, g65816_op_lda_constb, g65816_op_taxb, g65816_op_plb, /* ax */ g65816_op_ldy_addrb, g65816_op_lda_addrb, g65816_op_ldx_addrb, g65816_op_lda_longb,
/* bx */ g65816_op_bcs, g65816_op_lda_idpyb, g65816_op_lda_idpb, g65816_op_lda_isryb, /* bx */ g65816_op_ldy_dpxb, g65816_op_lda_dpxb, g65816_op_ldx_dpyb, g65816_op_lda_ildpyb, /* bx */ g65816_op_clv, g65816_op_lda_addryb, g65816_op_tsxb, g65816_op_tyxb, /* bx */ g65816_op_ldy_addrxb, g65816_op_lda_addrxb, g65816_op_ldx_addryb, g65816_op_lda_longxb,
/* cx */ g65816_op_cpy_constb, g65816_op_cmp_idpxb, g65816_op_rep, g65816_op_cmp_srb, /* cx */ g65816_op_cpy_dpb, g65816_op_cmp_dpb, g65816_op_dec_dpb, g65816_op_cmp_ildpb, /* cx */ g65816_op_inyb, g65816_op_cmp_constb, g65816_op_dexb, g65816_op_wai, /* cx */ g65816_op_cpy_addrb, g65816_op_cmp_addrb, g65816_op_dec_addrb, g65816_op_cmp_longb,
/* dx */ g65816_op_bne, g65816_op_cmp_idpyb, g65816_op_cmp_idpb, g65816_op_cmp_isryb, /* dx */ g65816_op_pei, g65816_op_cmp_dpxb, g65816_op_dec_dpxb, g65816_op_cmp_ildpyb, /* dx */ g65816_op_cld, g65816_op_cmp_addryb, g65816_op_phxb, g65816_op_stp, /* dx */ g65816_op_jmp_iladdr, g65816_op_cmp_addrxb, g65816_op_dec_addrxb, g65816_op_cmp_longxb,
/* ex */ g65816_op_cpx_constb, g65816_op_sbc_idpxb, g65816_op_sep, g65816_op_sbc_srb, /* ex */ g65816_op_cpx_dpb, g65816_op_sbc_dpb, g65816_op_inc_dpb, g65816_op_sbc_ildpb, /* ex */ g65816_op_inxb, g65816_op_sbc_constb, g65816_op_nop, g65816_op_xba, /* ex */ g65816_op_cpx_addrb, g65816_op_sbc_addrb, g65816_op_inc_addrb, g65816_op_sbc_longb,
/* fx */ g65816_op_beq, g65816_op_sbc_idpyb, g65816_op_sbc_idpb, g65816_op_sbc_isryb, /* fx */ g65816_op_pea, g65816_op_sbc_dpxb, g65816_op_inc_dpxb, g65816_op_sbc_ildpyb, /* fx */ g65816_op_sed, g65816_op_sbc_addryb, g65816_op_plxb, g65816_op_xce, /* fx */ g65816_op_jsr_iaddrx, g65816_op_sbc_addrxb, g65816_op_inc_addrxb, g65816_op_sbc_longxb
};
vfunc g65816_optbl_MX[256] = { // g65816_optbl_MX, g65816_optbl_MX, g65816_optbl_MX,
// ----------------------x0, ----------------------x1, ----------------------x2, ----------------------x3, -------- ----------------------x4, ----------------------x5, ----------------------x6, ----------------------x7, -------- ----------------------x8, ----------------------x9, ----------------------xa, ----------------------xb, -------- ----------------------xc, ----------------------xd, ----------------------xe, ----------------------xf,
/* 0x */ g65816_op_brk, g65816_op_ora_idpxb, g65816_op_cop, g65816_op_ora_srb, /* 0x */ g65816_op_tsb_dpb, g65816_op_ora_dpb, g65816_op_asl_dpb, g65816_op_ora_ildpb, /* 0x */ g65816_op_php, g65816_op_ora_constb, g65816_op_aslb, g65816_op_phd, /* 0x */ g65816_op_tsb_addrb, g65816_op_ora_addrb, g65816_op_asl_addrb, g65816_op_ora_longb,
/* 1x */ g65816_op_bpl, g65816_op_ora_idpyb, g65816_op_ora_idpb, g65816_op_ora_isryb, /* 1x */ g65816_op_trb_dpb, g65816_op_ora_dpxb, g65816_op_asl_dpxb, g65816_op_ora_ildpyb, /* 1x */ g65816_op_clc, g65816_op_ora_addryb, g65816_op_incb, g65816_op_tcsn, /* 1x */ g65816_op_trb_addrb, g65816_op_ora_addrxb, g65816_op_asl_addrxb, g65816_op_ora_longxb,
/* 2x */ g65816_op_jsr_addr, g65816_op_and_idpxb, g65816_op_jsr_long, g65816_op_and_srb, /* 2x */ g65816_op_bit_dpb, g65816_op_and_dpb, g65816_op_rol_dpb, g65816_op_and_ildpb, /* 2x */ g65816_op_plp, g65816_op_and_constb, g65816_op_rolb, g65816_op_pld, /* 2x */ g65816_op_bit_addrb, g65816_op_and_addrb, g65816_op_rol_addrb, g65816_op_and_longb,
/* 3x */ g65816_op_bmi, g65816_op_and_idpyb, g65816_op_and_idpb, g65816_op_and_isryb, /* 3x */ g65816_op_bit_dpxb, g65816_op_and_dpxb, g65816_op_rol_dpxb, g65816_op_and_ildpyb, /* 3x */ g65816_op_sec, g65816_op_and_addryb, g65816_op_decb, g65816_op_tscn, /* 3x */ g65816_op_bit_addrxb, g65816_op_and_addrxb, g65816_op_rol_addrxb, g65816_op_and_longxb,
/* 4x */ g65816_op_rtin, g65816_op_eor_idpxb, g65816_op_wdm, g65816_op_eor_srb, /* 4x */ g65816_op_mvp, g65816_op_eor_dpb, g65816_op_lsr_dpb, g65816_op_eor_ildpb, /* 4x */ g65816_op_phab, g65816_op_eor_constb, g65816_op_lsrb, g65816_op_phk, /* 4x */ g65816_op_jmp_addr, g65816_op_eor_addrb, g65816_op_lsr_addrb, g65816_op_eor_longb,
/* 5x */ g65816_op_bvc, g65816_op_eor_idpyb, g65816_op_eor_idpb, g65816_op_eor_isryb, /* 5x */ g65816_op_mvn, g65816_op_eor_dpxb, g65816_op_lsr_dpxb, g65816_op_eor_ildpyb, /* 5x */ g65816_op_cli, g65816_op_eor_addryb, g65816_op_phyb, g65816_op_tcd, /* 5x */ g65816_op_jmp_long, g65816_op_eor_addrxb, g65816_op_lsr_addrxb, g65816_op_eor_longxb,
/* 6x */ g65816_op_rts, g65816_op_adc_idpxb, g65816_op_per, g65816_op_adc_srb, /* 6x */ g65816_op_stz_dpb, g65816_op_adc_dpb, g65816_op_ror_dpb, g65816_op_adc_ildpb, /* 6x */ g65816_op_plab, g65816_op_adc_constb, g65816_op_rorb, g65816_op_rtl, /* 6x */ g65816_op_jmp_iaddr, g65816_op_adc_addrb, g65816_op_ror_addrb, g65816_op_adc_longb,
/* 7x */ g65816_op_bvs, g65816_op_adc_idpyb, g65816_op_adc_idpb, g65816_op_adc_isryb, /* 7x */ g65816_op_stz_dpxb, g65816_op_adc_dpxb, g65816_op_ror_dpxb, g65816_op_adc_ildpyb, /* 7x */ g65816_op_sei, g65816_op_adc_addryb, g65816_op_plyb, g65816_tdc, /* 7x */ g65816_op_jmp_iaddrx, g65816_op_adc_addrxb, g65816_op_ror_addrxb, g65816_op_adc_longxb,
/* 8x */ g65816_op_bra, g65816_op_sta_idpxb, g65816_op_brl, g65816_op_sta_srb, /* 8x */ g65816_op_sty_dpb, g65816_op_sta_dpb, g65816_op_stx_dpb, g65816_op_sta_ildpb, /* 8x */ g65816_op_deyb, g65816_op_bit_constb, g65816_op_txab, g65816_op_phb, /* 8x */ g65816_op_sty_addrb, g65816_op_sta_addrb, g65816_op_stx_addrb, g65816_op_sta_longb,
/* 9x */ g65816_op_bcc, g65816_op_sta_idpyb, g65816_op_sta_idpb, g65816_op_sta_isryb, /* 9x */ g65816_op_sty_dpxb, g65816_op_sta_dpxb, g65816_op_stx_dpyb, g65816_op_sta_ildpyb, /* 9x */ g65816_op_tyab, g65816_op_sta_addryb, g65816_op_txsb, g65816_op_txyb, /* 9x */ g65816_op_stz_addrb, g65816_op_sta_addrxb, g65816_op_stz_addrxb, g65816_op_sta_longxb,
/* ax */ g65816_op_ldy_constb, g65816_op_lda_idpxb, g65816_op_ldx_constb, g65816_op_lda_srb, /* ax */ g65816_op_ldy_dpb, g65816_op_lda_dpb, g65816_op_ldx_dpb, g65816_op_lda_ildpb, /* ax */ g65816_op_tayb, g65816_op_lda_constb, g65816_op_taxb, g65816_op_plb, /* ax */ g65816_op_ldy_addrb, g65816_op_lda_addrb, g65816_op_ldx_addrb, g65816_op_lda_longb,
/* bx */ g65816_op_bcs, g65816_op_lda_idpyb, g65816_op_lda_idpb, g65816_op_lda_isryb, /* bx */ g65816_op_ldy_dpxb, g65816_op_lda_dpxb, g65816_op_ldx_dpyb, g65816_op_lda_ildpyb, /* bx */ g65816_op_clv, g65816_op_lda_addryb, g65816_op_tsxb, g65816_op_tyxb, /* bx */ g65816_op_ldy_addrxb, g65816_op_lda_addrxb, g65816_op_ldx_addryb, g65816_op_lda_longxb,
/* cx */ g65816_op_cpy_constb, g65816_op_cmp_idpxb, g65816_op_rep, g65816_op_cmp_srb, /* cx */ g65816_op_cpy_dpb, g65816_op_cmp_dpb, g65816_op_dec_dpb, g65816_op_cmp_ildpb, /* cx */ g65816_op_inyb, g65816_op_cmp_constb, g65816_op_dexb, g65816_op_wai, /* cx */ g65816_op_cpy_addrb, g65816_op_cmp_addrb, g65816_op_dec_addrb, g65816_op_cmp_longb,
/* dx */ g65816_op_bne, g65816_op_cmp_idpyb, g65816_op_cmp_idpb, g65816_op_cmp_isryb, /* dx */ g65816_op_pei, g65816_op_cmp_dpxb, g65816_op_dec_dpxb, g65816_op_cmp_ildpyb, /* dx */ g65816_op_cld, g65816_op_cmp_addryb, g65816_op_phxb, g65816_op_stp, /* dx */ g65816_op_jmp_iladdr, g65816_op_cmp_addrxb, g65816_op_dec_addrxb, g65816_op_cmp_longxb,
/* ex */ g65816_op_cpx_constb, g65816_op_sbc_idpxb, g65816_op_sep, g65816_op_sbc_srb, /* ex */ g65816_op_cpx_dpb, g65816_op_sbc_dpb, g65816_op_inc_dpb, g65816_op_sbc_ildpb, /* ex */ g65816_op_inxb, g65816_op_sbc_constb, g65816_op_nop, g65816_op_xba, /* ex */ g65816_op_cpx_addrb, g65816_op_sbc_addrb, g65816_op_inc_addrb, g65816_op_sbc_longb,
/* fx */ g65816_op_beq, g65816_op_sbc_idpyb, g65816_op_sbc_idpb, g65816_op_sbc_isryb, /* fx */ g65816_op_pea, g65816_op_sbc_dpxb, g65816_op_inc_dpxb, g65816_op_sbc_ildpyb, /* fx */ g65816_op_sed, g65816_op_sbc_addryb, g65816_op_plxb, g65816_op_xce, /* fx */ g65816_op_jsr_iaddrx, g65816_op_sbc_addrxb, g65816_op_inc_addrxb, g65816_op_sbc_longxb
};
vfunc g65816_optbl_Mx[256] = { // g65816_optbl_Mx, g65816_optbl_Mx, g65816_optbl_Mx,
// ----------------------x0, ----------------------x1, ----------------------x2, ----------------------x3, -------- ----------------------x4, ----------------------x5, ----------------------x6, ----------------------x7, -------- ----------------------x8, ----------------------x9, ----------------------xa, ----------------------xb, -------- ----------------------xc, ----------------------xd, ----------------------xe, ----------------------xf,
/* 0x */ g65816_op_brk, g65816_op_ora_idpxb, g65816_op_cop, g65816_op_ora_srb, /* 0x */ g65816_op_tsb_dpb, g65816_op_ora_dpb, g65816_op_asl_dpb, g65816_op_ora_ildpb, /* 0x */ g65816_op_php, g65816_op_ora_constb, g65816_op_aslb, g65816_op_phd, /* 0x */ g65816_op_tsb_addrb, g65816_op_ora_addrb, g65816_op_asl_addrb, g65816_op_ora_longb,
/* 1x */ g65816_op_bpl, g65816_op_ora_idpyb, g65816_op_ora_idpb, g65816_op_ora_isryb, /* 1x */ g65816_op_trb_dpb, g65816_op_ora_dpxb, g65816_op_asl_dpxb, g65816_op_ora_ildpyb, /* 1x */ g65816_op_clc, g65816_op_ora_addryb, g65816_op_incb, g65816_op_tcsn, /* 1x */ g65816_op_trb_addrb, g65816_op_ora_addrxb, g65816_op_asl_addrxb, g65816_op_ora_longxb,
/* 2x */ g65816_op_jsr_addr, g65816_op_and_idpxb, g65816_op_jsr_long, g65816_op_and_srb, /* 2x */ g65816_op_bit_dpb, g65816_op_and_dpb, g65816_op_rol_dpb, g65816_op_and_ildpb, /* 2x */ g65816_op_plp, g65816_op_and_constb, g65816_op_rolb, g65816_op_pld, /* 2x */ g65816_op_bit_addrb, g65816_op_and_addrb, g65816_op_rol_addrb, g65816_op_and_longb,
/* 3x */ g65816_op_bmi, g65816_op_and_idpyb, g65816_op_and_idpb, g65816_op_and_isryb, /* 3x */ g65816_op_bit_dpxb, g65816_op_and_dpxb, g65816_op_rol_dpxb, g65816_op_and_ildpyb, /* 3x */ g65816_op_sec, g65816_op_and_addryb, g65816_op_decb, g65816_op_tscn, /* 3x */ g65816_op_bit_addrxb, g65816_op_and_addrxb, g65816_op_rol_addrxb, g65816_op_and_longxb,
/* 4x */ g65816_op_rtin, g65816_op_eor_idpxb, g65816_op_wdm, g65816_op_eor_srb, /* 4x */ g65816_op_mvp, g65816_op_eor_dpb, g65816_op_lsr_dpb, g65816_op_eor_ildpb, /* 4x */ g65816_op_phab, g65816_op_eor_constb, g65816_op_lsrb, g65816_op_phk, /* 4x */ g65816_op_jmp_addr, g65816_op_eor_addrb, g65816_op_lsr_addrb, g65816_op_eor_longb,
/* 5x */ g65816_op_bvc, g65816_op_eor_idpyb, g65816_op_eor_idpb, g65816_op_eor_isryb, /* 5x */ g65816_op_mvn, g65816_op_eor_dpxb, g65816_op_lsr_dpxb, g65816_op_eor_ildpyb, /* 5x */ g65816_op_cli, g65816_op_eor_addryb, g65816_op_phyw, g65816_op_tcd, /* 5x */ g65816_op_jmp_long, g65816_op_eor_addrxb, g65816_op_lsr_addrxb, g65816_op_eor_longxb,
/* 6x */ g65816_op_rts, g65816_op_adc_idpxb, g65816_op_per, g65816_op_adc_srb, /* 6x */ g65816_op_stz_dpb, g65816_op_adc_dpb, g65816_op_ror_dpb, g65816_op_adc_ildpb, /* 6x */ g65816_op_plab, g65816_op_adc_constb, g65816_op_rorb, g65816_op_rtl, /* 6x */ g65816_op_jmp_iaddr, g65816_op_adc_addrb, g65816_op_ror_addrb, g65816_op_adc_longb,
/* 7x */ g65816_op_bvs, g65816_op_adc_idpyb, g65816_op_adc_idpb, g65816_op_adc_isryb, /* 7x */ g65816_op_stz_dpxb, g65816_op_adc_dpxb, g65816_op_ror_dpxb, g65816_op_adc_ildpyb, /* 7x */ g65816_op_sei, g65816_op_adc_addryb, g65816_op_plyw, g65816_tdc, /* 7x */ g65816_op_jmp_iaddrx, g65816_op_adc_addrxb, g65816_op_ror_addrxb, g65816_op_adc_longxb,
/* 8x */ g65816_op_bra, g65816_op_sta_idpxb, g65816_op_brl, g65816_op_sta_srb, /* 8x */ g65816_op_sty_dpw, g65816_op_sta_dpb, g65816_op_stx_dpw, g65816_op_sta_ildpb, /* 8x */ g65816_op_deyw, g65816_op_bit_constb, g65816_op_txab, g65816_op_phb, /* 8x */ g65816_op_sty_addrw, g65816_op_sta_addrb, g65816_op_stx_addrw, g65816_op_sta_longb,
/* 9x */ g65816_op_bcc, g65816_op_sta_idpyb, g65816_op_sta_idpb, g65816_op_sta_isryb, /* 9x */ g65816_op_sty_dpxw, g65816_op_sta_dpxb, g65816_op_stx_dpyw, g65816_op_sta_ildpyb, /* 9x */ g65816_op_tyab, g65816_op_sta_addryb, g65816_op_txsw, g65816_op_txyw, /* 9x */ g65816_op_stz_addrb, g65816_op_sta_addrxb, g65816_op_stz_addrxb, g65816_op_sta_longxb,
/* ax */ g65816_op_ldy_constw, g65816_op_lda_idpxb, g65816_op_ldx_constw, g65816_op_lda_srb, /* ax */ g65816_op_ldy_dpw, g65816_op_lda_dpb, g65816_op_ldx_dpw, g65816_op_lda_ildpb, /* ax */ g65816_op_tayw, g65816_op_lda_constb, g65816_op_taxw, g65816_op_plb, /* ax */ g65816_op_ldy_addrw, g65816_op_lda_addrb, g65816_op_ldx_addrw, g65816_op_lda_longb,
/* bx */ g65816_op_bcs, g65816_op_lda_idpyb, g65816_op_lda_idpb, g65816_op_lda_isryb, /* bx */ g65816_op_ldy_dpxw, g65816_op_lda_dpxb, g65816_op_ldx_dpyw, g65816_op_lda_ildpyb, /* bx */ g65816_op_clv, g65816_op_lda_addryb, g65816_op_tsxw, g65816_op_tyxw, /* bx */ g65816_op_ldy_addrxw, g65816_op_lda_addrxb, g65816_op_ldx_addryw, g65816_op_lda_longxb,
/* cx */ g65816_op_cpy_constw, g65816_op_cmp_idpxb, g65816_op_rep, g65816_op_cmp_srb, /* cx */ g65816_op_cpy_dpw, g65816_op_cmp_dpb, g65816_op_dec_dpb, g65816_op_cmp_ildpb, /* cx */ g65816_op_inyw, g65816_op_cmp_constb, g65816_op_dexw, g65816_op_wai, /* cx */ g65816_op_cpy_addrw, g65816_op_cmp_addrb, g65816_op_dec_addrb, g65816_op_cmp_longb,
/* dx */ g65816_op_bne, g65816_op_cmp_idpyb, g65816_op_cmp_idpb, g65816_op_cmp_isryb, /* dx */ g65816_op_pei, g65816_op_cmp_dpxb, g65816_op_dec_dpxb, g65816_op_cmp_ildpyb, /* dx */ g65816_op_cld, g65816_op_cmp_addryb, g65816_op_phxw, g65816_op_stp, /* dx */ g65816_op_jmp_iladdr, g65816_op_cmp_addrxb, g65816_op_dec_addrxb, g65816_op_cmp_longxb,
/* ex */ g65816_op_cpx_constw, g65816_op_sbc_idpxb, g65816_op_sep, g65816_op_sbc_srb, /* ex */ g65816_op_cpx_dpw, g65816_op_sbc_dpb, g65816_op_inc_dpb, g65816_op_sbc_ildpb, /* ex */ g65816_op_inxw, g65816_op_sbc_constb, g65816_op_nop, g65816_op_xba, /* ex */ g65816_op_cpx_addrw, g65816_op_sbc_addrb, g65816_op_inc_addrb, g65816_op_sbc_longb,
/* fx */ g65816_op_beq, g65816_op_sbc_idpyb, g65816_op_sbc_idpb, g65816_op_sbc_isryb, /* fx */ g65816_op_pea, g65816_op_sbc_dpxb, g65816_op_inc_dpxb, g65816_op_sbc_ildpyb, /* fx */ g65816_op_sed, g65816_op_sbc_addryb, g65816_op_plxw, g65816_op_xce, /* fx */ g65816_op_jsr_iaddrx, g65816_op_sbc_addrxb, g65816_op_inc_addrxb, g65816_op_sbc_longxb
};
vfunc g65816_optbl_mX[256] = { // g65816_optbl_mX, g65816_optbl_mX, g65816_optbl_mX,
// ----------------------x0, ----------------------x1, ----------------------x2, ----------------------x3, -------- ----------------------x4, ----------------------x5, ----------------------x6, ----------------------x7, -------- ----------------------x8, ----------------------x9, ----------------------xa, ----------------------xb, -------- ----------------------xc, ----------------------xd, ----------------------xe, ----------------------xf,
/* 0x */ g65816_op_brk, g65816_op_ora_idpxw, g65816_op_cop, g65816_op_ora_srw, /* 0x */ g65816_op_tsb_dpw, g65816_op_ora_dpw, g65816_op_asl_dpw, g65816_op_ora_ildpw, /* 0x */ g65816_op_php, g65816_op_ora_constw, g65816_op_aslw, g65816_op_phd, /* 0x */ g65816_op_tsb_addrw, g65816_op_ora_addrw, g65816_op_asl_addrw, g65816_op_ora_longw,
/* 1x */ g65816_op_bpl, g65816_op_ora_idpyw, g65816_op_ora_idpw, g65816_op_ora_isryw, /* 1x */ g65816_op_trb_dpw, g65816_op_ora_dpxw, g65816_op_asl_dpxw, g65816_op_ora_ildpyw, /* 1x */ g65816_op_clc, g65816_op_ora_addryw, g65816_op_incw, g65816_op_tcsn, /* 1x */ g65816_op_trb_addrw, g65816_op_ora_addrxw, g65816_op_asl_addrxw, g65816_op_ora_longxw,
/* 2x */ g65816_op_jsr_addr, g65816_op_and_idpxw, g65816_op_jsr_long, g65816_op_and_srw, /* 2x */ g65816_op_bit_dpw, g65816_op_and_dpw, g65816_op_rol_dpw, g65816_op_and_ildpw, /* 2x */ g65816_op_plp, g65816_op_and_constw, g65816_op_rolw, g65816_op_pld, /* 2x */ g65816_op_bit_addrw, g65816_op_and_addrw, g65816_op_rol_addrw, g65816_op_and_longw,
/* 3x */ g65816_op_bmi, g65816_op_and_idpyw, g65816_op_and_idpw, g65816_op_and_isryw, /* 3x */ g65816_op_bit_dpxw, g65816_op_and_dpxw, g65816_op_rol_dpxw, g65816_op_and_ildpyw, /* 3x */ g65816_op_sec, g65816_op_and_addryw, g65816_op_decw, g65816_op_tscn, /* 3x */ g65816_op_bit_addrxw, g65816_op_and_addrxw, g65816_op_rol_addrxw, g65816_op_and_longxw,
/* 4x */ g65816_op_rtin, g65816_op_eor_idpxw, g65816_op_wdm, g65816_op_eor_srw, /* 4x */ g65816_op_mvp, g65816_op_eor_dpw, g65816_op_lsr_dpw, g65816_op_eor_ildpw, /* 4x */ g65816_op_phaw, g65816_op_eor_constw, g65816_op_lsrw, g65816_op_phk, /* 4x */ g65816_op_jmp_addr, g65816_op_eor_addrw, g65816_op_lsr_addrw, g65816_op_eor_longw,
/* 5x */ g65816_op_bvc, g65816_op_eor_idpyw, g65816_op_eor_idpw, g65816_op_eor_isryw, /* 5x */ g65816_op_mvn, g65816_op_eor_dpxw, g65816_op_lsr_dpxw, g65816_op_eor_ildpyw, /* 5x */ g65816_op_cli, g65816_op_eor_addryw, g65816_op_phyb, g65816_op_tcd, /* 5x */ g65816_op_jmp_long, g65816_op_eor_addrxw, g65816_op_lsr_addrxw, g65816_op_eor_longxw,
/* 6x */ g65816_op_rts, g65816_op_adc_idpxw, g65816_op_per, g65816_op_adc_srw, /* 6x */ g65816_op_stz_dpw, g65816_op_adc_dpw, g65816_op_ror_dpw, g65816_op_adc_ildpw, /* 6x */ g65816_op_plaw, g65816_op_adc_constw, g65816_op_rorw, g65816_op_rtl, /* 6x */ g65816_op_jmp_iaddr, g65816_op_adc_addrw, g65816_op_ror_addrw, g65816_op_adc_longw,
/* 7x */ g65816_op_bvs, g65816_op_adc_idpyw, g65816_op_adc_idpw, g65816_op_adc_isryw, /* 7x */ g65816_op_stz_dpxw, g65816_op_adc_dpxw, g65816_op_ror_dpxw, g65816_op_adc_ildpyw, /* 7x */ g65816_op_sei, g65816_op_adc_addryw, g65816_op_plyb, g65816_tdc, /* 7x */ g65816_op_jmp_iaddrx, g65816_op_adc_addrxw, g65816_op_ror_addrxw, g65816_op_adc_longxw,
/* 8x */ g65816_op_bra, g65816_op_sta_idpxw, g65816_op_brl, g65816_op_sta_srw, /* 8x */ g65816_op_sty_dpb, g65816_op_sta_dpw, g65816_op_stx_dpb, g65816_op_sta_ildpw, /* 8x */ g65816_op_deyb, g65816_op_bit_constw, g65816_op_txaw, g65816_op_phb, /* 8x */ g65816_op_sty_addrb, g65816_op_sta_addrw, g65816_op_stx_addrb, g65816_op_sta_longw,
/* 9x */ g65816_op_bcc, g65816_op_sta_idpyw, g65816_op_sta_idpw, g65816_op_sta_isryw, /* 9x */ g65816_op_sty_dpxb, g65816_op_sta_dpxw, g65816_op_stx_dpyb, g65816_op_sta_ildpyw, /* 9x */ g65816_op_tyaw, g65816_op_sta_addryw, g65816_op_txsb, g65816_op_txyb, /* 9x */ g65816_op_stz_addrw, g65816_op_sta_addrxw, g65816_op_stz_addrxw, g65816_op_sta_longxw,
/* ax */ g65816_op_ldy_constb, g65816_op_lda_idpxw, g65816_op_ldx_constb, g65816_op_lda_srw, /* ax */ g65816_op_ldy_dpb, g65816_op_lda_dpw, g65816_op_ldx_dpb, g65816_op_lda_ildpw, /* ax */ g65816_op_tayb, g65816_op_lda_constw, g65816_op_taxb, g65816_op_plb, /* ax */ g65816_op_ldy_addrb, g65816_op_lda_addrw, g65816_op_ldx_addrb, g65816_op_lda_longw,
/* bx */ g65816_op_bcs, g65816_op_lda_idpyw, g65816_op_lda_idpw, g65816_op_lda_isryw, /* bx */ g65816_op_ldy_dpxb, g65816_op_lda_dpxw, g65816_op_ldx_dpyb, g65816_op_lda_ildpyw, /* bx */ g65816_op_clv, g65816_op_lda_addryw, g65816_op_tsxb, g65816_op_tyxb, /* bx */ g65816_op_ldy_addrxb, g65816_op_lda_addrxw, g65816_op_ldx_addryb, g65816_op_lda_longxw,
/* cx */ g65816_op_cpy_constb, g65816_op_cmp_idpxw, g65816_op_rep, g65816_op_cmp_srw, /* cx */ g65816_op_cpy_dpb, g65816_op_cmp_dpw, g65816_op_dec_dpw, g65816_op_cmp_ildpw, /* cx */ g65816_op_inyb, g65816_op_cmp_constw, g65816_op_dexb, g65816_op_wai, /* cx */ g65816_op_cpy_addrb, g65816_op_cmp_addrw, g65816_op_dec_addrw, g65816_op_cmp_longw,
/* dx */ g65816_op_bne, g65816_op_cmp_idpyw, g65816_op_cmp_idpw, g65816_op_cmp_isryw, /* dx */ g65816_op_pei, g65816_op_cmp_dpxw, g65816_op_dec_dpxw, g65816_op_cmp_ildpyw, /* dx */ g65816_op_cld, g65816_op_cmp_addryw, g65816_op_phxb, g65816_op_stp, /* dx */ g65816_op_jmp_iladdr, g65816_op_cmp_addrxw, g65816_op_dec_addrxw, g65816_op_cmp_longxw,
/* ex */ g65816_op_cpx_constb, g65816_op_sbc_idpxw, g65816_op_sep, g65816_op_sbc_srw, /* ex */ g65816_op_cpx_dpb, g65816_op_sbc_dpw, g65816_op_inc_dpw, g65816_op_sbc_ildpw, /* ex */ g65816_op_inxb, g65816_op_sbc_constw, g65816_op_nop, g65816_op_xba, /* ex */ g65816_op_cpx_addrb, g65816_op_sbc_addrw, g65816_op_inc_addrw, g65816_op_sbc_longw,
/* fx */ g65816_op_beq, g65816_op_sbc_idpyw, g65816_op_sbc_idpw, g65816_op_sbc_isryw, /* fx */ g65816_op_pea, g65816_op_sbc_dpxw, g65816_op_inc_dpxw, g65816_op_sbc_ildpyw, /* fx */ g65816_op_sed, g65816_op_sbc_addryw, g65816_op_plxb, g65816_op_xce, /* fx */ g65816_op_jsr_iaddrx, g65816_op_sbc_addrxw, g65816_op_inc_addrxw, g65816_op_sbc_longxw
};
vfunc g65816_optbl_mx[256] = { // g65816_optbl_mx, g65816_optbl_mx, g65816_optbl_mx,
// ----------------------x0, ----------------------x1, ----------------------x2, ----------------------x3, -------- ----------------------x4, ----------------------x5, ----------------------x6, ----------------------x7, -------- ----------------------x8, ----------------------x9, ----------------------xa, ----------------------xb, -------- ----------------------xc, ----------------------xd, ----------------------xe, ----------------------xf,
/* 0x */ g65816_op_brk, g65816_op_ora_idpxw, g65816_op_cop, g65816_op_ora_srw, /* 0x */ g65816_op_tsb_dpw, g65816_op_ora_dpw, g65816_op_asl_dpw, g65816_op_ora_ildpw, /* 0x */ g65816_op_php, g65816_op_ora_constw, g65816_op_aslw, g65816_op_phd, /* 0x */ g65816_op_tsb_addrw, g65816_op_ora_addrw, g65816_op_asl_addrw, g65816_op_ora_longw,
/* 1x */ g65816_op_bpl, g65816_op_ora_idpyw, g65816_op_ora_idpw, g65816_op_ora_isryw, /* 1x */ g65816_op_trb_dpw, g65816_op_ora_dpxw, g65816_op_asl_dpxw, g65816_op_ora_ildpyw, /* 1x */ g65816_op_clc, g65816_op_ora_addryw, g65816_op_incw, g65816_op_tcsn, /* 1x */ g65816_op_trb_addrw, g65816_op_ora_addrxw, g65816_op_asl_addrxw, g65816_op_ora_longxw,
/* 2x */ g65816_op_jsr_addr, g65816_op_and_idpxw, g65816_op_jsr_long, g65816_op_and_srw, /* 2x */ g65816_op_bit_dpw, g65816_op_and_dpw, g65816_op_rol_dpw, g65816_op_and_ildpw, /* 2x */ g65816_op_plp, g65816_op_and_constw, g65816_op_rolw, g65816_op_pld, /* 2x */ g65816_op_bit_addrw, g65816_op_and_addrw, g65816_op_rol_addrw, g65816_op_and_longw,
/* 3x */ g65816_op_bmi, g65816_op_and_idpyw, g65816_op_and_idpw, g65816_op_and_isryw, /* 3x */ g65816_op_bit_dpxw, g65816_op_and_dpxw, g65816_op_rol_dpxw, g65816_op_and_ildpyw, /* 3x */ g65816_op_sec, g65816_op_and_addryw, g65816_op_decw, g65816_op_tscn, /* 3x */ g65816_op_bit_addrxw, g65816_op_and_addrxw, g65816_op_rol_addrxw, g65816_op_and_longxw,
/* 4x */ g65816_op_rtin, g65816_op_eor_idpxw, g65816_op_wdm, g65816_op_eor_srw, /* 4x */ g65816_op_mvp, g65816_op_eor_dpw, g65816_op_lsr_dpw, g65816_op_eor_ildpw, /* 4x */ g65816_op_phaw, g65816_op_eor_constw, g65816_op_lsrw, g65816_op_phk, /* 4x */ g65816_op_jmp_addr, g65816_op_eor_addrw, g65816_op_lsr_addrw, g65816_op_eor_longw,
/* 5x */ g65816_op_bvc, g65816_op_eor_idpyw, g65816_op_eor_idpw, g65816_op_eor_isryw, /* 5x */ g65816_op_mvn, g65816_op_eor_dpxw, g65816_op_lsr_dpxw, g65816_op_eor_ildpyw, /* 5x */ g65816_op_cli, g65816_op_eor_addryw, g65816_op_phyw, g65816_op_tcd, /* 5x */ g65816_op_jmp_long, g65816_op_eor_addrxw, g65816_op_lsr_addrxw, g65816_op_eor_longxw,
/* 6x */ g65816_op_rts, g65816_op_adc_idpxw, g65816_op_per, g65816_op_adc_srw, /* 6x */ g65816_op_stz_dpw, g65816_op_adc_dpw, g65816_op_ror_dpw, g65816_op_adc_ildpw, /* 6x */ g65816_op_plaw, g65816_op_adc_constw, g65816_op_rorw, g65816_op_rtl, /* 6x */ g65816_op_jmp_iaddr, g65816_op_adc_addrw, g65816_op_ror_addrw, g65816_op_adc_longw,
/* 7x */ g65816_op_bvs, g65816_op_adc_idpyw, g65816_op_adc_idpw, g65816_op_adc_isryw, /* 7x */ g65816_op_stz_dpxw, g65816_op_adc_dpxw, g65816_op_ror_dpxw, g65816_op_adc_ildpyw, /* 7x */ g65816_op_sei, g65816_op_adc_addryw, g65816_op_plyw, g65816_tdc, /* 7x */ g65816_op_jmp_iaddrx, g65816_op_adc_addrxw, g65816_op_ror_addrxw, g65816_op_adc_longxw,
/* 8x */ g65816_op_bra, g65816_op_sta_idpxw, g65816_op_brl, g65816_op_sta_srw, /* 8x */ g65816_op_sty_dpw, g65816_op_sta_dpw, g65816_op_stx_dpw, g65816_op_sta_ildpw, /* 8x */ g65816_op_deyw, g65816_op_bit_constw, g65816_op_txaw, g65816_op_phb, /* 8x */ g65816_op_sty_addrw, g65816_op_sta_addrw, g65816_op_stx_addrw, g65816_op_sta_longw,
/* 9x */ g65816_op_bcc, g65816_op_sta_idpyw, g65816_op_sta_idpw, g65816_op_sta_isryw, /* 9x */ g65816_op_sty_dpxw, g65816_op_sta_dpxw, g65816_op_stx_dpyw, g65816_op_sta_ildpyw, /* 9x */ g65816_op_tyaw, g65816_op_sta_addryw, g65816_op_txsw, g65816_op_txyw, /* 9x */ g65816_op_stz_addrw, g65816_op_sta_addrxw, g65816_op_stz_addrxw, g65816_op_sta_longxw,
/* ax */ g65816_op_ldy_constw, g65816_op_lda_idpxw, g65816_op_ldx_constw, g65816_op_lda_srw, /* ax */ g65816_op_ldy_dpw, g65816_op_lda_dpw, g65816_op_ldx_dpw, g65816_op_lda_ildpw, /* ax */ g65816_op_tayw, g65816_op_lda_constw, g65816_op_taxw, g65816_op_plb, /* ax */ g65816_op_ldy_addrw, g65816_op_lda_addrw, g65816_op_ldx_addrw, g65816_op_lda_longw,
/* bx */ g65816_op_bcs, g65816_op_lda_idpyw, g65816_op_lda_idpw, g65816_op_lda_isryw, /* bx */ g65816_op_ldy_dpxw, g65816_op_lda_dpxw, g65816_op_ldx_dpyw, g65816_op_lda_ildpyw, /* bx */ g65816_op_clv, g65816_op_lda_addryw, g65816_op_tsxw, g65816_op_tyxw, /* bx */ g65816_op_ldy_addrxw, g65816_op_lda_addrxw, g65816_op_ldx_addryw, g65816_op_lda_longxw,
/* cx */ g65816_op_cpy_constw, g65816_op_cmp_idpxw, g65816_op_rep, g65816_op_cmp_srw, /* cx */ g65816_op_cpy_dpw, g65816_op_cmp_dpw, g65816_op_dec_dpw, g65816_op_cmp_ildpw, /* cx */ g65816_op_inyw, g65816_op_cmp_constw, g65816_op_dexw, g65816_op_wai, /* cx */ g65816_op_cpy_addrw, g65816_op_cmp_addrw, g65816_op_dec_addrw, g65816_op_cmp_longw,
/* dx */ g65816_op_bne, g65816_op_cmp_idpyw, g65816_op_cmp_idpw, g65816_op_cmp_isryw, /* dx */ g65816_op_pei, g65816_op_cmp_dpxw, g65816_op_dec_dpxw, g65816_op_cmp_ildpyw, /* dx */ g65816_op_cld, g65816_op_cmp_addryw, g65816_op_phxw, g65816_op_stp, /* dx */ g65816_op_jmp_iladdr, g65816_op_cmp_addrxw, g65816_op_dec_addrxw, g65816_op_cmp_longxw,
/* ex */ g65816_op_cpx_constw, g65816_op_sbc_idpxw, g65816_op_sep, g65816_op_sbc_srw, /* ex */ g65816_op_cpx_dpw, g65816_op_sbc_dpw, g65816_op_inc_dpw, g65816_op_sbc_ildpw, /* ex */ g65816_op_inxw, g65816_op_sbc_constw, g65816_op_nop, g65816_op_xba, /* ex */ g65816_op_cpx_addrw, g65816_op_sbc_addrw, g65816_op_inc_addrw, g65816_op_sbc_longw,
/* fx */ g65816_op_beq, g65816_op_sbc_idpyw, g65816_op_sbc_idpw, g65816_op_sbc_isryw, /* fx */ g65816_op_pea, g65816_op_sbc_dpxw, g65816_op_inc_dpxw, g65816_op_sbc_ildpyw, /* fx */ g65816_op_sed, g65816_op_sbc_addryw, g65816_op_plxw, g65816_op_xce, /* fx */ g65816_op_jsr_iaddrx, g65816_op_sbc_addrxw, g65816_op_inc_addrxw, g65816_op_sbc_longxw
};
+526
View File
@@ -0,0 +1,526 @@
void g65816_flags_adc_b(void) {
int r = gx816->regs.a.b + gx816->op.r.b + (gx816->regs.p & PF_C);
//bcd
if(gx816->regs.p & PF_D) {
if(((r ) & 15) > 9)r += 6;
if(((r >> 4) & 15) > 9)r += 6 << 4;
}
g65816_testn(r & 0x80);
g65816_testv(~(gx816->regs.a.b ^ gx816->op.r.b) & (gx816->regs.a.b ^ (byte)r) & 0x80);
g65816_testz((byte)r == 0);
g65816_testc(r > 0xff);
gx816->regs.a.b = r;
}
void g65816_flags_adc_w(void) {
int r = gx816->regs.a.w + gx816->op.r.w + (gx816->regs.p & PF_C);
//bcd
if(gx816->regs.p & PF_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;
}
g65816_testn(r & 0x8000);
g65816_testv(~(gx816->regs.a.w ^ gx816->op.r.w) & (gx816->regs.a.w ^ (word)r) & 0x8000);
g65816_testz((word)r == 0);
g65816_testc(r > 0xffff);
gx816->regs.a.w = r;
}
/************************
*** 0x69: adc #const ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; idl
[2a] pbr,pc+2 ; idh [1]
*/
void g65816_op_adc_constb(void) {
gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
g65816_flags_adc_b();
g65816_incpc(2);
}
void g65816_op_adc_constw(void) {
gx816->op.r.w = gx816->read_operand(2); //1,2,2a [op fetch]
g65816_flags_adc_w();
g65816_incpc(3);
}
/**********************
*** 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 g65816_op_adc_addrb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read]
g65816_flags_adc_b();
g65816_incpc(3);
}
void g65816_op_adc_addrw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high]
g65816_flags_adc_w();
g65816_incpc(3);
}
/************************
*** 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 g65816_op_adc_addrxb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read]
g65816_flags_adc_b();
g65816_incpc(3);
}
void g65816_op_adc_addrxw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //4a [read high]
g65816_flags_adc_w();
g65816_incpc(3);
}
/********************
*** 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 g65816_op_adc_dpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read]
g65816_flags_adc_b();
g65816_incpc(2);
}
void g65816_op_adc_dpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high]
g65816_flags_adc_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_adc_idpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read]
g65816_flags_adc_b();
g65816_incpc(2);
}
void g65816_op_adc_idpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //5a [read high]
g65816_flags_adc_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_adc_ildpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read]
g65816_flags_adc_b();
g65816_incpc(2);
}
void g65816_op_adc_ildpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //6a [read high]
g65816_flags_adc_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_adc_longb(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read]
g65816_flags_adc_b();
g65816_incpc(4);
}
void g65816_op_adc_longw(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read]
gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //5a [read]
g65816_flags_adc_w();
g65816_incpc(4);
}
/************************
*** 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 g65816_op_adc_longxb(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read]
g65816_flags_adc_b();
g65816_incpc(4);
}
void g65816_op_adc_longxw(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read]
gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x + 1); //5a [read]
g65816_flags_adc_w();
g65816_incpc(4);
}
/************************
*** 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 g65816_op_adc_addryb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read]
g65816_flags_adc_b();
g65816_incpc(3);
}
void g65816_op_adc_addryw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //4a [read high]
g65816_flags_adc_w();
g65816_incpc(3);
}
/**********************
*** 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 g65816_op_adc_dpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read]
g65816_flags_adc_b();
g65816_incpc(2);
}
void g65816_op_adc_dpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high]
g65816_flags_adc_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_adc_idpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read]
g65816_flags_adc_b();
g65816_incpc(2);
}
void g65816_op_adc_idpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //6 [read high]
g65816_flags_adc_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_adc_idpyb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read]
g65816_flags_adc_b();
g65816_incpc(2);
}
void g65816_op_adc_idpyw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //5a [read high]
g65816_flags_adc_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_adc_ildpyb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read]
g65816_flags_adc_b();
g65816_incpc(2);
}
void g65816_op_adc_ildpyw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y + 1); //6a [read high]
g65816_flags_adc_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_adc_srb(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read]
g65816_flags_adc_b();
g65816_incpc(2);
}
void g65816_op_adc_srw(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //4a [read high]
g65816_flags_adc_w();
g65816_incpc(2);
}
/**************************
*** 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 g65816_op_adc_isryb(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read]
g65816_flags_adc_b();
g65816_incpc(2);
}
void g65816_op_adc_isryw(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //7a [read high]
g65816_flags_adc_w();
g65816_incpc(2);
}
+504
View File
@@ -0,0 +1,504 @@
void g65816_flags_and_b() {
g65816_testn(gx816->regs.a.b & 0x80);
g65816_testz(gx816->regs.a.b == 0);
}
void g65816_flags_and_w() {
g65816_testn(gx816->regs.a.w & 0x8000);
g65816_testz(gx816->regs.a.w == 0);
}
/************************
*** 0x29: and #const ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; idl
[2a] pbr,pc+2 ; idh [1]
*/
void g65816_op_and_constb(void) {
gx816->regs.a.b &= gx816->read_operand(1); //1,2 [op fetch]
g65816_flags_and_b();
g65816_incpc(2);
}
void g65816_op_and_constw(void) {
gx816->regs.a.w &= gx816->read_operand(2); //1,2,2a [op fetch]
g65816_flags_and_w();
g65816_incpc(3);
}
/**********************
*** 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 g65816_op_and_addrb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->regs.a.b &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read]
g65816_flags_and_b();
g65816_incpc(3);
}
void g65816_op_and_addrw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->regs.a.p.l &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low]
gx816->regs.a.p.h &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high]
g65816_flags_and_w();
g65816_incpc(3);
}
/************************
*** 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 g65816_op_and_addrxb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0]
gx816->regs.a.b &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read]
g65816_flags_and_b();
g65816_incpc(3);
}
void g65816_op_and_addrxw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0]
gx816->regs.a.p.l &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read low]
gx816->regs.a.p.h &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //4a [read high]
g65816_flags_and_w();
g65816_incpc(3);
}
/********************
*** 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 g65816_op_and_dpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->regs.a.b &= gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read]
g65816_flags_and_b();
g65816_incpc(2);
}
void g65816_op_and_dpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->regs.a.p.l &= gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low]
gx816->regs.a.p.h &= gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high]
g65816_flags_and_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_and_idpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->regs.a.b &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read]
g65816_flags_and_b();
g65816_incpc(2);
}
void g65816_op_and_idpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->regs.a.p.l &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read low]
gx816->regs.a.p.h &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //5a [read high]
g65816_flags_and_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_and_ildpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->regs.a.b &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read]
g65816_flags_and_b();
g65816_incpc(2);
}
void g65816_op_and_ildpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->regs.a.p.l &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read low]
gx816->regs.a.p.h &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //6a [read high]
g65816_flags_and_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_and_longb(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->regs.a.b &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read]
g65816_flags_and_b();
g65816_incpc(4);
}
void g65816_op_and_longw(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->regs.a.p.l &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read]
gx816->regs.a.p.h &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //5a [read]
g65816_flags_and_w();
g65816_incpc(4);
}
/************************
*** 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 g65816_op_and_longxb(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->regs.a.b &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read]
g65816_flags_and_b();
g65816_incpc(4);
}
void g65816_op_and_longxw(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->regs.a.p.l &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read]
gx816->regs.a.p.h &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x + 1); //5a [read]
g65816_flags_and_w();
g65816_incpc(4);
}
/************************
*** 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 g65816_op_and_addryb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0]
gx816->regs.a.b &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read]
g65816_flags_and_b();
g65816_incpc(3);
}
void g65816_op_and_addryw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0]
gx816->regs.a.p.l &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read low]
gx816->regs.a.p.h &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //4a [read high]
g65816_flags_and_w();
g65816_incpc(3);
}
/**********************
*** 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 g65816_op_and_dpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->regs.a.b &= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read]
g65816_flags_and_b();
g65816_incpc(2);
}
void g65816_op_and_dpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->regs.a.p.l &= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low]
gx816->regs.a.p.h &= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high]
g65816_flags_and_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_and_idpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah]
gx816->regs.a.b &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read]
g65816_flags_and_b();
g65816_incpc(2);
}
void g65816_op_and_idpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah]
gx816->regs.a.p.l &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read low]
gx816->regs.a.p.h &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //6 [read high]
g65816_flags_and_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_and_idpyb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0]
gx816->regs.a.b &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read]
g65816_flags_and_b();
g65816_incpc(2);
}
void g65816_op_and_idpyw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0]
gx816->regs.a.p.l &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read low]
gx816->regs.a.p.h &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //5a [read high]
g65816_flags_and_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_and_ildpyb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->regs.a.b &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read]
g65816_flags_and_b();
g65816_incpc(2);
}
void g65816_op_and_ildpyw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->regs.a.p.l &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read low]
gx816->regs.a.p.h &= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y + 1); //6a [read high]
g65816_flags_and_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_and_srb(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->regs.a.b &= gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read]
g65816_flags_and_b();
g65816_incpc(2);
}
void g65816_op_and_srw(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->regs.a.p.l &= gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read low]
gx816->regs.a.p.h &= gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //4a [read high]
g65816_flags_and_w();
g65816_incpc(2);
}
/**************************
*** 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 g65816_op_and_isryb(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->regs.a.b &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read]
g65816_flags_and_b();
g65816_incpc(2);
}
void g65816_op_and_isryw(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->regs.a.p.l &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read low]
gx816->regs.a.p.h &= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //7a [read high]
g65816_flags_and_w();
g65816_incpc(2);
}
+508
View File
@@ -0,0 +1,508 @@
void g65816_flags_cmp_b() {
int r = gx816->regs.a.b - gx816->op.r.b;
g65816_testn(r & 0x80);
g65816_testz((byte)r == 0);
g65816_testc(r >= 0);
}
void g65816_flags_cmp_w() {
int r = gx816->regs.a.w - gx816->op.r.w;
g65816_testn(r & 0x8000);
g65816_testz((word)r == 0);
g65816_testc(r >= 0);
}
/************************
*** 0xc9: cmp #const ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; idl
[2a] pbr,pc+2 ; idh [1]
*/
void g65816_op_cmp_constb(void) {
gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
g65816_flags_cmp_b();
g65816_incpc(2);
}
void g65816_op_cmp_constw(void) {
gx816->op.r.w = gx816->read_operand(2); //1,2,2a [op fetch]
g65816_flags_cmp_w();
g65816_incpc(3);
}
/**********************
*** 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 g65816_op_cmp_addrb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read]
g65816_flags_cmp_b();
g65816_incpc(3);
}
void g65816_op_cmp_addrw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high]
g65816_flags_cmp_w();
g65816_incpc(3);
}
/************************
*** 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 g65816_op_cmp_addrxb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read]
g65816_flags_cmp_b();
g65816_incpc(3);
}
void g65816_op_cmp_addrxw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //4a [read high]
g65816_flags_cmp_w();
g65816_incpc(3);
}
/********************
*** 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 g65816_op_cmp_dpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read]
g65816_flags_cmp_b();
g65816_incpc(2);
}
void g65816_op_cmp_dpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high]
g65816_flags_cmp_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_cmp_idpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read]
g65816_flags_cmp_b();
g65816_incpc(2);
}
void g65816_op_cmp_idpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //5a [read high]
g65816_flags_cmp_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_cmp_ildpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read]
g65816_flags_cmp_b();
g65816_incpc(2);
}
void g65816_op_cmp_ildpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //6a [read high]
g65816_flags_cmp_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_cmp_longb(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read]
g65816_flags_cmp_b();
g65816_incpc(4);
}
void g65816_op_cmp_longw(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read]
gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //5a [read]
g65816_flags_cmp_w();
g65816_incpc(4);
}
/************************
*** 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 g65816_op_cmp_longxb(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read]
g65816_flags_cmp_b();
g65816_incpc(4);
}
void g65816_op_cmp_longxw(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read]
gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x + 1); //5a [read]
g65816_flags_cmp_w();
g65816_incpc(4);
}
/************************
*** 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 g65816_op_cmp_addryb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read]
g65816_flags_cmp_b();
g65816_incpc(3);
}
void g65816_op_cmp_addryw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //4a [read high]
g65816_flags_cmp_w();
g65816_incpc(3);
}
/**********************
*** 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 g65816_op_cmp_dpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read]
g65816_flags_cmp_b();
g65816_incpc(2);
}
void g65816_op_cmp_dpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high]
g65816_flags_cmp_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_cmp_idpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read]
g65816_flags_cmp_b();
g65816_incpc(2);
}
void g65816_op_cmp_idpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //6 [read high]
g65816_flags_cmp_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_cmp_idpyb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read]
g65816_flags_cmp_b();
g65816_incpc(2);
}
void g65816_op_cmp_idpyw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //5a [read high]
g65816_flags_cmp_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_cmp_ildpyb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read]
g65816_flags_cmp_b();
g65816_incpc(2);
}
void g65816_op_cmp_ildpyw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y + 1); //6a [read high]
g65816_flags_cmp_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_cmp_srb(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read]
g65816_flags_cmp_b();
g65816_incpc(2);
}
void g65816_op_cmp_srw(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //4a [read high]
g65816_flags_cmp_w();
g65816_incpc(2);
}
/**************************
*** 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 g65816_op_cmp_isryb(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read]
g65816_flags_cmp_b();
g65816_incpc(2);
}
void g65816_op_cmp_isryw(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //7a [read high]
g65816_flags_cmp_w();
g65816_incpc(2);
}
+504
View File
@@ -0,0 +1,504 @@
void g65816_flags_eor_b() {
g65816_testn(gx816->regs.a.b & 0x80);
g65816_testz(gx816->regs.a.b == 0);
}
void g65816_flags_eor_w() {
g65816_testn(gx816->regs.a.w & 0x8000);
g65816_testz(gx816->regs.a.w == 0);
}
/************************
*** 0x49: eor #const ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; idl
[2a] pbr,pc+2 ; idh [1]
*/
void g65816_op_eor_constb(void) {
gx816->regs.a.b ^= gx816->read_operand(1); //1,2 [op fetch]
g65816_flags_eor_b();
g65816_incpc(2);
}
void g65816_op_eor_constw(void) {
gx816->regs.a.w ^= gx816->read_operand(2); //1,2,2a [op fetch]
g65816_flags_eor_w();
g65816_incpc(3);
}
/**********************
*** 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 g65816_op_eor_addrb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->regs.a.b ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read]
g65816_flags_eor_b();
g65816_incpc(3);
}
void g65816_op_eor_addrw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->regs.a.p.l ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low]
gx816->regs.a.p.h ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high]
g65816_flags_eor_w();
g65816_incpc(3);
}
/************************
*** 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 g65816_op_eor_addrxb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0]
gx816->regs.a.b ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read]
g65816_flags_eor_b();
g65816_incpc(3);
}
void g65816_op_eor_addrxw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0]
gx816->regs.a.p.l ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read low]
gx816->regs.a.p.h ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //4a [read high]
g65816_flags_eor_w();
g65816_incpc(3);
}
/********************
*** 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 g65816_op_eor_dpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->regs.a.b ^= gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read]
g65816_flags_eor_b();
g65816_incpc(2);
}
void g65816_op_eor_dpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->regs.a.p.l ^= gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low]
gx816->regs.a.p.h ^= gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high]
g65816_flags_eor_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_eor_idpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->regs.a.b ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read]
g65816_flags_eor_b();
g65816_incpc(2);
}
void g65816_op_eor_idpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->regs.a.p.l ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read low]
gx816->regs.a.p.h ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //5a [read high]
g65816_flags_eor_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_eor_ildpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->regs.a.b ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read]
g65816_flags_eor_b();
g65816_incpc(2);
}
void g65816_op_eor_ildpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->regs.a.p.l ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read low]
gx816->regs.a.p.h ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //6a [read high]
g65816_flags_eor_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_eor_longb(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->regs.a.b ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read]
g65816_flags_eor_b();
g65816_incpc(4);
}
void g65816_op_eor_longw(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->regs.a.p.l ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read]
gx816->regs.a.p.h ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //5a [read]
g65816_flags_eor_w();
g65816_incpc(4);
}
/************************
*** 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 g65816_op_eor_longxb(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->regs.a.b ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read]
g65816_flags_eor_b();
g65816_incpc(4);
}
void g65816_op_eor_longxw(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->regs.a.p.l ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read]
gx816->regs.a.p.h ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x + 1); //5a [read]
g65816_flags_eor_w();
g65816_incpc(4);
}
/************************
*** 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 g65816_op_eor_addryb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0]
gx816->regs.a.b ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read]
g65816_flags_eor_b();
g65816_incpc(3);
}
void g65816_op_eor_addryw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0]
gx816->regs.a.p.l ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read low]
gx816->regs.a.p.h ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //4a [read high]
g65816_flags_eor_w();
g65816_incpc(3);
}
/**********************
*** 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 g65816_op_eor_dpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->regs.a.b ^= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read]
g65816_flags_eor_b();
g65816_incpc(2);
}
void g65816_op_eor_dpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->regs.a.p.l ^= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low]
gx816->regs.a.p.h ^= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high]
g65816_flags_eor_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_eor_idpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah]
gx816->regs.a.b ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read]
g65816_flags_eor_b();
g65816_incpc(2);
}
void g65816_op_eor_idpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah]
gx816->regs.a.p.l ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read low]
gx816->regs.a.p.h ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //6 [read high]
g65816_flags_eor_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_eor_idpyb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0]
gx816->regs.a.b ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read]
g65816_flags_eor_b();
g65816_incpc(2);
}
void g65816_op_eor_idpyw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0]
gx816->regs.a.p.l ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read low]
gx816->regs.a.p.h ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //5a [read high]
g65816_flags_eor_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_eor_ildpyb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->regs.a.b ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read]
g65816_flags_eor_b();
g65816_incpc(2);
}
void g65816_op_eor_ildpyw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->regs.a.p.l ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read low]
gx816->regs.a.p.h ^= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y + 1); //6a [read high]
g65816_flags_eor_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_eor_srb(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->regs.a.b ^= gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read]
g65816_flags_eor_b();
g65816_incpc(2);
}
void g65816_op_eor_srw(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->regs.a.p.l ^= gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read low]
gx816->regs.a.p.h ^= gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //4a [read high]
g65816_flags_eor_w();
g65816_incpc(2);
}
/**************************
*** 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 g65816_op_eor_isryb(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->regs.a.b ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read]
g65816_flags_eor_b();
g65816_incpc(2);
}
void g65816_op_eor_isryw(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->regs.a.p.l ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read low]
gx816->regs.a.p.h ^= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //7a [read high]
g65816_flags_eor_w();
g65816_incpc(2);
}
+511
View File
@@ -0,0 +1,511 @@
/*****************
*** 0x1a: inc ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void g65816_op_incb(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->regs.a.b++;
g65816_testn(gx816->regs.a.b & 0x80);
g65816_testz(gx816->regs.a.b == 0);
g65816_incpc(1);
}
void g65816_op_incw(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->regs.a.w++;
g65816_testn(gx816->regs.a.w & 0x8000);
g65816_testz(gx816->regs.a.w == 0);
g65816_incpc(1);
}
/**********************
*** 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 g65816_op_inc_addrb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read]
snes_time->add_cpu_icycles(1); //5 [i/o]
gx816->op.r.b++;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.b); //6 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(3);
}
void g65816_op_inc_addrw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high]
snes_time->add_cpu_icycles(1); //5 [i/o]
gx816->op.r.w++;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->op.r.p.h); //6a [write high]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.p.l); //6 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(3);
}
/************************
*** 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 g65816_op_inc_addrxb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->op.r.b++;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.b); //7 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(3);
}
void g65816_op_inc_addrxw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //5a [read high]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->op.r.w++;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1, gx816->op.r.p.h); //7a [write high]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.p.l); //7 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(3);
}
/********************
*** 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 g65816_op_inc_dpb(void) {
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read]
snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->op.r.b++;
gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.b); //5 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(2);
}
void g65816_op_inc_dpw(void) {
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high]
snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->op.r.w++;
gx816->op_write(OPMODE_DP, gx816->op.dp + 1, gx816->op.r.p.h); //5a [write high]
gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.p.l); //5 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_inc_dpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read]
snes_time->add_cpu_icycles(1); //5 [i/o]
gx816->op.r.b++;
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.b); //6 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(2);
}
void g65816_op_inc_dpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high]
snes_time->add_cpu_icycles(1); //5 [i/o]
gx816->op.r.w++;
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1, gx816->op.r.p.h); //6a [write high]
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.p.l); //6 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(2);
}
/*****************
*** 0xe8: inx ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void g65816_op_inxb(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->regs.x++;
gx816->regs.x &= 0xff;
g65816_testn(gx816->regs.x & 0x80);
g65816_testz(gx816->regs.x == 0);
g65816_incpc(1);
}
void g65816_op_inxw(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->regs.x++;
g65816_testn(gx816->regs.x & 0x8000);
g65816_testz(gx816->regs.x == 0);
g65816_incpc(1);
}
/*****************
*** 0xc8: iny ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void g65816_op_inyb(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->regs.y++;
gx816->regs.y &= 0xff;
g65816_testn(gx816->regs.y & 0x80);
g65816_testz(gx816->regs.y == 0);
g65816_incpc(1);
}
void g65816_op_inyw(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->regs.y++;
g65816_testn(gx816->regs.y & 0x8000);
g65816_testz(gx816->regs.y == 0);
g65816_incpc(1);
}
/*****************
*** 0x3a: dec ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void g65816_op_decb(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->regs.a.b--;
g65816_testn(gx816->regs.a.b & 0x80);
g65816_testz(gx816->regs.a.b == 0);
g65816_incpc(1);
}
void g65816_op_decw(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->regs.a.w--;
g65816_testn(gx816->regs.a.w & 0x8000);
g65816_testz(gx816->regs.a.w == 0);
g65816_incpc(1);
}
/**********************
*** 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 g65816_op_dec_addrb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read]
snes_time->add_cpu_icycles(1); //5 [i/o]
gx816->op.r.b--;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.b); //6 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(3);
}
void g65816_op_dec_addrw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high]
snes_time->add_cpu_icycles(1); //5 [i/o]
gx816->op.r.w--;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->op.r.p.h); //6a [write high]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.p.l); //6 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(3);
}
/************************
*** 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 g65816_op_dec_addrxb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->op.r.b--;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.b); //7 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(3);
}
void g65816_op_dec_addrxw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //5a [read high]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->op.r.w--;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1, gx816->op.r.p.h); //7a [write high]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.p.l); //7 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(3);
}
/********************
*** 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 g65816_op_dec_dpb(void) {
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read]
snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->op.r.b--;
gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.b); //5 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(2);
}
void g65816_op_dec_dpw(void) {
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high]
snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->op.r.w--;
gx816->op_write(OPMODE_DP, gx816->op.dp + 1, gx816->op.r.p.h); //5a [write high]
gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.p.l); //5 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_dec_dpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read]
snes_time->add_cpu_icycles(1); //5 [i/o]
gx816->op.r.b--;
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.b); //6 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(2);
}
void g65816_op_dec_dpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high]
snes_time->add_cpu_icycles(1); //5 [i/o]
gx816->op.r.w--;
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1, gx816->op.r.p.h); //6a [write high]
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.p.l); //6 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(2);
}
/*****************
*** 0xca: dex ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void g65816_op_dexb(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->regs.x--;
gx816->regs.x &= 0xff;
g65816_testn(gx816->regs.x & 0x80);
g65816_testz(gx816->regs.x == 0);
g65816_incpc(1);
}
void g65816_op_dexw(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->regs.x--;
g65816_testn(gx816->regs.x & 0x8000);
g65816_testz(gx816->regs.x == 0);
g65816_incpc(1);
}
/*****************
*** 0x88: dey ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void g65816_op_deyb(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->regs.y--;
gx816->regs.y &= 0xff;
g65816_testn(gx816->regs.y & 0x80);
g65816_testz(gx816->regs.y == 0);
g65816_incpc(1);
}
void g65816_op_deyw(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->regs.y--;
g65816_testn(gx816->regs.y & 0x8000);
g65816_testz(gx816->regs.y == 0);
g65816_incpc(1);
}
+504
View File
@@ -0,0 +1,504 @@
void g65816_flags_lda_b(void) {
g65816_testn(gx816->regs.a.b & 0x80);
g65816_testz(gx816->regs.a.b == 0);
}
void g65816_flags_lda_w(void) {
g65816_testn(gx816->regs.a.w & 0x8000);
g65816_testz(gx816->regs.a.w == 0);
}
/************************
*** 0xa9: lda #const ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; idl
[2a] pbr,pc+2 ; idh [1]
*/
void g65816_op_lda_constb(void) {
gx816->regs.a.b = gx816->read_operand(1); //1,2 [op fetch]
g65816_flags_lda_b();
g65816_incpc(2);
}
void g65816_op_lda_constw(void) {
gx816->regs.a.w = gx816->read_operand(2); //1,2,2a [op fetch]
g65816_flags_lda_w();
g65816_incpc(3);
}
/**********************
*** 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 g65816_op_lda_addrb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->regs.a.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read]
g65816_flags_lda_b();
g65816_incpc(3);
}
void g65816_op_lda_addrw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->regs.a.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low]
gx816->regs.a.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high]
g65816_flags_lda_w();
g65816_incpc(3);
}
/************************
*** 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 g65816_op_lda_addrxb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0]
gx816->regs.a.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read]
g65816_flags_lda_b();
g65816_incpc(3);
}
void g65816_op_lda_addrxw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0]
gx816->regs.a.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read low]
gx816->regs.a.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //4a [read high]
g65816_flags_lda_w();
g65816_incpc(3);
}
/********************
*** 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 g65816_op_lda_dpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->regs.a.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read]
g65816_flags_lda_b();
g65816_incpc(2);
}
void g65816_op_lda_dpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->regs.a.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low]
gx816->regs.a.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high]
g65816_flags_lda_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_lda_idpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->regs.a.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read]
g65816_flags_lda_b();
g65816_incpc(2);
}
void g65816_op_lda_idpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->regs.a.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read low]
gx816->regs.a.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //5a [read high]
g65816_flags_lda_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_lda_ildpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->regs.a.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read]
g65816_flags_lda_b();
g65816_incpc(2);
}
void g65816_op_lda_ildpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->regs.a.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read low]
gx816->regs.a.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //6a [read high]
g65816_flags_lda_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_lda_longb(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->regs.a.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read]
g65816_flags_lda_b();
g65816_incpc(4);
}
void g65816_op_lda_longw(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->regs.a.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read]
gx816->regs.a.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //5a [read]
g65816_flags_lda_w();
g65816_incpc(4);
}
/************************
*** 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 g65816_op_lda_longxb(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->regs.a.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read]
g65816_flags_lda_b();
g65816_incpc(4);
}
void g65816_op_lda_longxw(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->regs.a.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read]
gx816->regs.a.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x + 1); //5a [read]
g65816_flags_lda_w();
g65816_incpc(4);
}
/************************
*** 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 g65816_op_lda_addryb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0]
gx816->regs.a.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read]
g65816_flags_lda_b();
g65816_incpc(3);
}
void g65816_op_lda_addryw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0]
gx816->regs.a.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read low]
gx816->regs.a.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //4a [read high]
g65816_flags_lda_w();
g65816_incpc(3);
}
/**********************
*** 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 g65816_op_lda_dpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->regs.a.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read]
g65816_flags_lda_b();
g65816_incpc(2);
}
void g65816_op_lda_dpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->regs.a.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low]
gx816->regs.a.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high]
g65816_flags_lda_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_lda_idpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah]
gx816->regs.a.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read]
g65816_flags_lda_b();
g65816_incpc(2);
}
void g65816_op_lda_idpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah]
gx816->regs.a.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read low]
gx816->regs.a.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //6 [read high]
g65816_flags_lda_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_lda_idpyb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0]
gx816->regs.a.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read]
g65816_flags_lda_b();
g65816_incpc(2);
}
void g65816_op_lda_idpyw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0]
gx816->regs.a.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read low]
gx816->regs.a.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //5a [read high]
g65816_flags_lda_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_lda_ildpyb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->regs.a.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read]
g65816_flags_lda_b();
g65816_incpc(2);
}
void g65816_op_lda_ildpyw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->regs.a.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read low]
gx816->regs.a.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y + 1); //6a [read high]
g65816_flags_lda_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_lda_srb(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->regs.a.b = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read]
g65816_flags_lda_b();
g65816_incpc(2);
}
void g65816_op_lda_srw(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->regs.a.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read low]
gx816->regs.a.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //4a [read high]
g65816_flags_lda_w();
g65816_incpc(2);
}
/**************************
*** 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 g65816_op_lda_isryb(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->regs.a.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read]
g65816_flags_lda_b();
g65816_incpc(2);
}
void g65816_op_lda_isryw(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->regs.a.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read low]
gx816->regs.a.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //7a [read high]
g65816_flags_lda_w();
g65816_incpc(2);
}
File diff suppressed because it is too large. Load diff
+504
View File
@@ -0,0 +1,504 @@
void g65816_flags_ora_b() {
g65816_testn(gx816->regs.a.b & 0x80);
g65816_testz(gx816->regs.a.b == 0);
}
void g65816_flags_ora_w() {
g65816_testn(gx816->regs.a.w & 0x8000);
g65816_testz(gx816->regs.a.w == 0);
}
/************************
*** 0x09: ora #const ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; idl
[2a] pbr,pc+2 ; idh [1]
*/
void g65816_op_ora_constb(void) {
gx816->regs.a.b |= gx816->read_operand(1); //1,2 [op fetch]
g65816_flags_ora_b();
g65816_incpc(2);
}
void g65816_op_ora_constw(void) {
gx816->regs.a.w |= gx816->read_operand(2); //1,2,2a [op fetch]
g65816_flags_ora_w();
g65816_incpc(3);
}
/**********************
*** 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 g65816_op_ora_addrb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->regs.a.b |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read]
g65816_flags_ora_b();
g65816_incpc(3);
}
void g65816_op_ora_addrw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->regs.a.p.l |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low]
gx816->regs.a.p.h |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high]
g65816_flags_ora_w();
g65816_incpc(3);
}
/************************
*** 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 g65816_op_ora_addrxb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0]
gx816->regs.a.b |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read]
g65816_flags_ora_b();
g65816_incpc(3);
}
void g65816_op_ora_addrxw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0]
gx816->regs.a.p.l |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read low]
gx816->regs.a.p.h |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //4a [read high]
g65816_flags_ora_w();
g65816_incpc(3);
}
/********************
*** 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 g65816_op_ora_dpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->regs.a.b |= gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read]
g65816_flags_ora_b();
g65816_incpc(2);
}
void g65816_op_ora_dpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->regs.a.p.l |= gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low]
gx816->regs.a.p.h |= gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high]
g65816_flags_ora_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_ora_idpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->regs.a.b |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read]
g65816_flags_ora_b();
g65816_incpc(2);
}
void g65816_op_ora_idpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->regs.a.p.l |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read low]
gx816->regs.a.p.h |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //5a [read high]
g65816_flags_ora_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_ora_ildpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->regs.a.b |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read]
g65816_flags_ora_b();
g65816_incpc(2);
}
void g65816_op_ora_ildpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->regs.a.p.l |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read low]
gx816->regs.a.p.h |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //6a [read high]
g65816_flags_ora_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_ora_longb(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->regs.a.b |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read]
g65816_flags_ora_b();
g65816_incpc(4);
}
void g65816_op_ora_longw(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->regs.a.p.l |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read]
gx816->regs.a.p.h |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //5a [read]
g65816_flags_ora_w();
g65816_incpc(4);
}
/************************
*** 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 g65816_op_ora_longxb(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->regs.a.b |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read]
g65816_flags_ora_b();
g65816_incpc(4);
}
void g65816_op_ora_longxw(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->regs.a.p.l |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read]
gx816->regs.a.p.h |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x + 1); //5a [read]
g65816_flags_ora_w();
g65816_incpc(4);
}
/************************
*** 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 g65816_op_ora_addryb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0]
gx816->regs.a.b |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read]
g65816_flags_ora_b();
g65816_incpc(3);
}
void g65816_op_ora_addryw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0]
gx816->regs.a.p.l |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read low]
gx816->regs.a.p.h |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //4a [read high]
g65816_flags_ora_w();
g65816_incpc(3);
}
/**********************
*** 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 g65816_op_ora_dpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->regs.a.b |= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read]
g65816_flags_ora_b();
g65816_incpc(2);
}
void g65816_op_ora_dpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->regs.a.p.l |= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low]
gx816->regs.a.p.h |= gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high]
g65816_flags_ora_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_ora_idpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah]
gx816->regs.a.b |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read]
g65816_flags_ora_b();
g65816_incpc(2);
}
void g65816_op_ora_idpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah]
gx816->regs.a.p.l |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read low]
gx816->regs.a.p.h |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //6 [read high]
g65816_flags_ora_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_ora_idpyb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0]
gx816->regs.a.b |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read]
g65816_flags_ora_b();
g65816_incpc(2);
}
void g65816_op_ora_idpyw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0]
gx816->regs.a.p.l |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read low]
gx816->regs.a.p.h |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //5a [read high]
g65816_flags_ora_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_ora_ildpyb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->regs.a.b |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read]
g65816_flags_ora_b();
g65816_incpc(2);
}
void g65816_op_ora_ildpyw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->regs.a.p.l |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read low]
gx816->regs.a.p.h |= gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y + 1); //6a [read high]
g65816_flags_ora_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_ora_srb(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->regs.a.b |= gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read]
g65816_flags_ora_b();
g65816_incpc(2);
}
void g65816_op_ora_srw(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->regs.a.p.l |= gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read low]
gx816->regs.a.p.h |= gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //4a [read high]
g65816_flags_ora_w();
g65816_incpc(2);
}
/**************************
*** 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 g65816_op_ora_isryb(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->regs.a.b |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read]
g65816_flags_ora_b();
g65816_incpc(2);
}
void g65816_op_ora_isryw(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->regs.a.p.l |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read low]
gx816->regs.a.p.h |= gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //7a [read high]
g65816_flags_ora_w();
g65816_incpc(2);
}
+497
View File
@@ -0,0 +1,497 @@
/**********************
*** 0x4c: jmp addr ***
**********************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; new pcl
[3] pbr,pc+2 ; new pch
*/
void g65816_op_jmp_addr(void) {
gx816->op.r.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->op.r.w;
}
/**********************
*** 0x5c: jml 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 g65816_op_jmp_long(void) {
gx816->regs.pc = gx816->read_operand(3); //1-4 [op fetch]
}
/************************
*** 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 g65816_op_jmp_iaddr(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.p.l = gx816->op_read(OPMODE_ADDR, gx816->op.aa.w); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_ADDR, gx816->op.aa.w + 1); //5 [read high]
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->op.r.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 g65816_op_jmp_iaddrx(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_PBR, gx816->op.aa.w + gx816->regs.x); //5 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_PBR, gx816->op.aa.w + gx816->regs.x + 1); //6 [read high]
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->op.r.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 g65816_op_jmp_iladdr(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.p.l = gx816->op_read(OPMODE_ADDR, gx816->op.aa.w); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_ADDR, gx816->op.aa.w + 1); //5 [read high]
gx816->op.r.p.b = gx816->op_read(OPMODE_ADDR, gx816->op.aa.w + 2); //6 [read bank]
gx816->regs.pc = gx816->op.r.l;
}
/**********************
*** 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 g65816_op_jsr_addr(void) {
gx816->op.r.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->regs.pc += 2;
gx816->stack_write(gx816->regs.pc >> 8); //5 [write high]
gx816->stack_write(gx816->regs.pc); //6 [write low]
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->op.r.w;
}
/**********************
*** 0x22: jsl 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 g65816_op_jsr_long(void) {
gx816->op.r.l = gx816->read_operand(3); //1-3,6 [op fetch]
gx816->regs.pc += 3;
gx816->stack_write(gx816->regs.pc >> 16); //4 [write bank]
snes_time->add_cpu_icycles(1); //5 [i/o]
gx816->stack_write(gx816->regs.pc >> 8); //7 [write high]
gx816->stack_write(gx816->regs.pc); //8 [write low]
gx816->regs.pc = gx816->op.r.l;
}
/**************************
*** 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 g65816_op_jsr_iaddrx(void) {
gx816->op.aa.w = gx816->read_operand(2); //1,2,5 [op fetch]
gx816->regs.pc += 2;
gx816->stack_write(gx816->regs.pc >> 8); //3 [write high]
gx816->stack_write(gx816->regs.pc); //4 [write low]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_PBR, gx816->op.aa.w + gx816->regs.x); //7 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_PBR, gx816->op.aa.w + gx816->regs.x + 1); //8 [read high]
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->op.r.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 g65816_op_rtie(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(2); //2,3 [i/o]
gx816->regs.p = gx816->stack_read(); //4 [read p]
gx816->op.r.p.l = gx816->stack_read(); //5 [read pcl]
gx816->op.r.p.h = gx816->stack_read(); //6 [read pch]
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->op.r.w;
if(gx816->regs.p & PF_X) { gx816->regs.x &= 0xff; gx816->regs.y &= 0xff; }
gx816->regs.p &= ~ PF_I;
}
void g65816_op_rtin(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(2); //2,3 [i/o]
gx816->regs.p = gx816->stack_read(); //4 [read p]
gx816->op.r.p.l = gx816->stack_read(); //5 [read pcl]
gx816->op.r.p.h = gx816->stack_read(); //6 [read pch]
gx816->op.r.p.b = gx816->stack_read(); //7 [read pbr]
gx816->regs.pc = gx816->op.r.l;
if(gx816->regs.p & PF_X) { gx816->regs.x &= 0xff; gx816->regs.y &= 0xff; }
gx816->regs.p &= ~ PF_I;
}
/*****************
*** 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 g65816_op_rts(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(2); //2,3 [i/o]
gx816->op.r.p.l = gx816->stack_read(); //4 [read low]
gx816->op.r.p.h = gx816->stack_read(); //5 [read high]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | gx816->op.r.w;
g65816_incpc(1);
}
/*****************
*** 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 g65816_op_rtl(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(2); //2,3 [i/o]
gx816->op.r.p.l = gx816->stack_read(); //4 [read low]
gx816->op.r.p.h = gx816->stack_read(); //5 [read high]
gx816->op.r.p.b = gx816->stack_read(); //6 [read bank]
gx816->regs.pc = gx816->op.r.l;
g65816_incpc(1);
}
/**********************
*** 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 g65816_op_bra(void) {
word r;
gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //2a [i/o]
r = gx816->regs.pc + (signed char)gx816->op.r.b;
if(gx816->regs.e == true) {
if((gx816->regs.pc & 0xff00) != ((r + 2) & 0xff00)) {
snes_time->add_cpu_icycles(1); //2b [i/o]
}
}
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r;
g65816_incpc(2);
}
/*********************
*** 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 g65816_op_brl(void) {
word r;
gx816->op.r.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //4 [i/o]
r = gx816->regs.pc + (signed short)gx816->op.r.w;
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r;
g65816_incpc(3);
}
/**********************
*** 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 g65816_op_bcc(void) {
word r;
gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
if(!(gx816->regs.p & PF_C)) {
snes_time->add_cpu_icycles(1); //2a [i/o]
r = gx816->regs.pc + (signed char)gx816->op.r.b;
if(gx816->regs.e == true) {
if((gx816->regs.pc & 0xff00) != ((r + 2) & 0xff00)) {
snes_time->add_cpu_icycles(1); //2b [i/o]
}
}
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r;
}
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_bcs(void) {
word r;
gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
if(gx816->regs.p & PF_C) {
snes_time->add_cpu_icycles(1); //2a [i/o]
r = gx816->regs.pc + (signed char)gx816->op.r.b;
if(gx816->regs.e == true) {
if((gx816->regs.pc & 0xff00) != ((r + 2) & 0xff00)) {
snes_time->add_cpu_icycles(1); //2b [i/o]
}
}
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r;
}
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_bne(void) {
word r;
gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
if(!(gx816->regs.p & PF_Z)) {
snes_time->add_cpu_icycles(1); //2a [i/o]
r = gx816->regs.pc + (signed char)gx816->op.r.b;
if(gx816->regs.e == true) {
if((gx816->regs.pc & 0xff00) != ((r + 2) & 0xff00)) {
snes_time->add_cpu_icycles(1); //2b [i/o]
}
}
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r;
}
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_beq(void) {
word r;
gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
if(gx816->regs.p & PF_Z) {
snes_time->add_cpu_icycles(1); //2a [i/o]
r = gx816->regs.pc + (signed char)gx816->op.r.b;
if(gx816->regs.e == true) {
if((gx816->regs.pc & 0xff00) != ((r + 2) & 0xff00)) {
snes_time->add_cpu_icycles(1); //2b [i/o]
}
}
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r;
}
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_bpl(void) {
word r;
gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
if(!(gx816->regs.p & PF_N)) {
snes_time->add_cpu_icycles(1); //2a [i/o]
r = gx816->regs.pc + (signed char)gx816->op.r.b;
if(gx816->regs.e == true) {
if((gx816->regs.pc & 0xff00) != ((r + 2) & 0xff00)) {
snes_time->add_cpu_icycles(1); //2b [i/o]
}
}
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r;
}
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_bmi(void) {
word r;
gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
if(gx816->regs.p & PF_N) {
snes_time->add_cpu_icycles(1); //2a [i/o]
r = gx816->regs.pc + (signed char)gx816->op.r.b;
if(gx816->regs.e == true) {
if((gx816->regs.pc & 0xff00) != ((r + 2) & 0xff00)) {
snes_time->add_cpu_icycles(1); //2b [i/o]
}
}
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r;
}
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_bvc(void) {
word r;
gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
if(!(gx816->regs.p & PF_V)) {
snes_time->add_cpu_icycles(1); //2a [i/o]
r = gx816->regs.pc + (signed char)gx816->op.r.b;
if(gx816->regs.e == true) {
if((gx816->regs.pc & 0xff00) != ((r + 2) & 0xff00)) {
snes_time->add_cpu_icycles(1); //2b [i/o]
}
}
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r;
}
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_bvs(void) {
word r;
gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
if(gx816->regs.p & PF_V) {
snes_time->add_cpu_icycles(1); //2a [i/o]
r = gx816->regs.pc + (signed char)gx816->op.r.b;
if(gx816->regs.e == true) {
if((gx816->regs.pc & 0xff00) != ((r + 2) & 0xff00)) {
snes_time->add_cpu_icycles(1); //2b [i/o]
}
}
gx816->regs.pc = (gx816->regs.pc & 0xff0000) | r;
}
g65816_incpc(2);
}
+526
View File
@@ -0,0 +1,526 @@
void g65816_flags_sbc_b() {
int r = gx816->regs.a.b - gx816->op.r.b - !(gx816->regs.p & PF_C);
//bcd
if(gx816->regs.p & PF_D) {
if(((r ) & 15) > 9)r -= 6;
if(((r >> 4) & 15) > 9)r -= 6 << 4;
}
g65816_testn(r & 0x80);
g65816_testv((gx816->regs.a.b ^ gx816->op.r.b) & (gx816->regs.a.b ^ (byte)r) & 0x80);
g65816_testz((byte)r == 0);
g65816_testc(r >= 0);
gx816->regs.a.b = r;
}
void g65816_flags_sbc_w() {
int r = gx816->regs.a.w - gx816->op.r.w - !(gx816->regs.p & PF_C);
//bcd
if(gx816->regs.p & PF_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;
}
g65816_testn(r & 0x8000);
g65816_testv((gx816->regs.a.w ^ gx816->op.r.w) & (gx816->regs.a.w ^ (word)r) & 0x8000);
g65816_testz((word)r == 0);
g65816_testc(r >= 0);
gx816->regs.a.w = r;
}
/************************
*** 0xe9: sbc #const ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; idl
[2a] pbr,pc+2 ; idh [1]
*/
void g65816_op_sbc_constb(void) {
gx816->op.r.b = gx816->read_operand(1); //1,2 [op fetch]
g65816_flags_sbc_b();
g65816_incpc(2);
}
void g65816_op_sbc_constw(void) {
gx816->op.r.w = gx816->read_operand(2); //1,2,2a [op fetch]
g65816_flags_sbc_w();
g65816_incpc(3);
}
/**********************
*** 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 g65816_op_sbc_addrb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read]
g65816_flags_sbc_b();
g65816_incpc(3);
}
void g65816_op_sbc_addrw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high]
g65816_flags_sbc_w();
g65816_incpc(3);
}
/************************
*** 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 g65816_op_sbc_addrxb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read]
g65816_flags_sbc_b();
g65816_incpc(3);
}
void g65816_op_sbc_addrxw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.x); //3a [pbc or p.x=0]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //4a [read high]
g65816_flags_sbc_w();
g65816_incpc(3);
}
/********************
*** 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 g65816_op_sbc_dpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read]
g65816_flags_sbc_b();
g65816_incpc(2);
}
void g65816_op_sbc_dpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high]
g65816_flags_sbc_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_sbc_idpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read]
g65816_flags_sbc_b();
g65816_incpc(2);
}
void g65816_op_sbc_idpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //5 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //5a [read high]
g65816_flags_sbc_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_sbc_ildpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read]
g65816_flags_sbc_b();
g65816_incpc(2);
}
void g65816_op_sbc_ildpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //6 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //6a [read high]
g65816_flags_sbc_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_sbc_longb(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read]
g65816_flags_sbc_b();
g65816_incpc(4);
}
void g65816_op_sbc_longw(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l); //5 [read]
gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + 1); //5a [read]
g65816_flags_sbc_w();
g65816_incpc(4);
}
/************************
*** 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 g65816_op_sbc_longxb(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read]
g65816_flags_sbc_b();
g65816_incpc(4);
}
void g65816_op_sbc_longxw(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x); //5 [read]
gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x + 1); //5a [read]
g65816_flags_sbc_w();
g65816_incpc(4);
}
/************************
*** 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 g65816_op_sbc_addryb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read]
g65816_flags_sbc_b();
g65816_incpc(3);
}
void g65816_op_sbc_addryw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //3a [pbc or p.x=0]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //4a [read high]
g65816_flags_sbc_w();
g65816_incpc(3);
}
/**********************
*** 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 g65816_op_sbc_dpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read]
g65816_flags_sbc_b();
g65816_incpc(2);
}
void g65816_op_sbc_dpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high]
g65816_flags_sbc_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_sbc_idpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read]
g65816_flags_sbc_b();
g65816_incpc(2);
}
void g65816_op_sbc_idpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //6 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //6 [read high]
g65816_flags_sbc_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_sbc_idpyb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read]
g65816_flags_sbc_b();
g65816_incpc(2);
}
void g65816_op_sbc_idpyw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op_cond(4, gx816->op.aa.w, gx816->op.aa.w + gx816->regs.y); //4a [pbc or p.x=0]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //5 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //5a [read high]
g65816_flags_sbc_w();
g65816_incpc(2);
}
/************************
*** 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 g65816_op_sbc_ildpyb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->op.r.b = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read]
g65816_flags_sbc_b();
g65816_incpc(2);
}
void g65816_op_sbc_ildpyw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->op.r.p.l = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y); //6 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y + 1); //6a [read high]
g65816_flags_sbc_w();
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_sbc_srb(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read]
g65816_flags_sbc_b();
g65816_incpc(2);
}
void g65816_op_sbc_srw(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //4a [read high]
g65816_flags_sbc_w();
g65816_incpc(2);
}
/**************************
*** 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 g65816_op_sbc_isryb(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read]
g65816_flags_sbc_b();
g65816_incpc(2);
}
void g65816_op_sbc_isryw(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y); //7 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1); //7a [read high]
g65816_flags_sbc_w();
g65816_incpc(2);
}
+873
View File
@@ -0,0 +1,873 @@
/*****************
*** 0x0a: asl ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void g65816_op_aslb(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
g65816_testc(gx816->regs.a.b & 0x80);
gx816->regs.a.b <<= 1;
g65816_testn(gx816->regs.a.b & 0x80);
g65816_testz(gx816->regs.a.b == 0);
g65816_incpc(1);
}
void g65816_op_aslw(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
g65816_testc(gx816->regs.a.w & 0x8000);
gx816->regs.a.w <<= 1;
g65816_testn(gx816->regs.a.w & 0x8000);
g65816_testz(gx816->regs.a.w == 0);
g65816_incpc(1);
}
/**********************
*** 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 g65816_op_asl_addrb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read]
snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testc(gx816->op.r.b & 0x80);
gx816->op.r.b <<= 1;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.b); //6 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(3);
}
void g65816_op_asl_addrw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high]
snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testc(gx816->op.r.w & 0x8000);
gx816->op.r.w <<= 1;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->op.r.p.h); //6a [write high]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.p.l); //6 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(3);
}
/************************
*** 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 g65816_op_asl_addrxb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read]
snes_time->add_cpu_icycles(1); //6 [i/o]
g65816_testc(gx816->op.r.b & 0x80);
gx816->op.r.b <<= 1;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.b); //7 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(3);
}
void g65816_op_asl_addrxw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //5a [read high]
snes_time->add_cpu_icycles(1); //6 [i/o]
g65816_testc(gx816->op.r.w & 0x8000);
gx816->op.r.w <<= 1;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1, gx816->op.r.p.h); //7a [write high]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.p.l); //7 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(3);
}
/********************
*** 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 g65816_op_asl_dpb(void) {
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read]
snes_time->add_cpu_icycles(1); //4 [i/o]
g65816_testc(gx816->op.r.b & 0x80);
gx816->op.r.b <<= 1;
gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.b); //5 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(2);
}
void g65816_op_asl_dpw(void) {
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high]
snes_time->add_cpu_icycles(1); //4 [i/o]
g65816_testc(gx816->op.r.w & 0x8000);
gx816->op.r.w <<= 1;
gx816->op_write(OPMODE_DP, gx816->op.dp + 1, gx816->op.r.p.h); //5a [write high]
gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.p.l); //5 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_asl_dpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read]
snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testc(gx816->op.r.b & 0x80);
gx816->op.r.b <<= 1;
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.b); //6 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(2);
}
void g65816_op_asl_dpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high]
snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testc(gx816->op.r.w & 0x8000);
gx816->op.r.w <<= 1;
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1, gx816->op.r.p.h); //6a [write high]
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.p.l); //6 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(2);
}
/*****************
*** 0x4a: lsr ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void g65816_op_lsrb(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
g65816_testc(gx816->regs.a.b & 0x01);
gx816->regs.a.b >>= 1;
g65816_clrn();
g65816_testz(gx816->regs.a.b == 0);
g65816_incpc(1);
}
void g65816_op_lsrw(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
g65816_testc(gx816->regs.a.w & 0x0001);
gx816->regs.a.w >>= 1;
g65816_clrn();
g65816_testz(gx816->regs.a.w == 0);
g65816_incpc(1);
}
/**********************
*** 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 g65816_op_lsr_addrb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read]
snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testc(gx816->op.r.b & 0x01);
gx816->op.r.b >>= 1;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.b); //6 [write]
g65816_clrn();
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(3);
}
void g65816_op_lsr_addrw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high]
snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testc(gx816->op.r.w & 0x0001);
gx816->op.r.w >>= 1;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->op.r.p.h); //6a [write high]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.p.l); //6 [write low]
g65816_clrn();
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(3);
}
/************************
*** 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 g65816_op_lsr_addrxb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read]
snes_time->add_cpu_icycles(1); //6 [i/o]
g65816_testc(gx816->op.r.b & 0x01);
gx816->op.r.b >>= 1;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.b); //7 [write]
g65816_clrn();
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(3);
}
void g65816_op_lsr_addrxw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //5a [read high]
snes_time->add_cpu_icycles(1); //6 [i/o]
g65816_testc(gx816->op.r.w & 0x0001);
gx816->op.r.w >>= 1;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1, gx816->op.r.p.h); //7a [write high]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.p.l); //7 [write low]
g65816_clrn();
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(3);
}
/********************
*** 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 g65816_op_lsr_dpb(void) {
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read]
snes_time->add_cpu_icycles(1); //4 [i/o]
g65816_testc(gx816->op.r.b & 0x01);
gx816->op.r.b >>= 1;
gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.b); //5 [write]
g65816_clrn();
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(2);
}
void g65816_op_lsr_dpw(void) {
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high]
snes_time->add_cpu_icycles(1); //4 [i/o]
g65816_testc(gx816->op.r.w & 0x0001);
gx816->op.r.w >>= 1;
gx816->op_write(OPMODE_DP, gx816->op.dp + 1, gx816->op.r.p.h); //5a [write high]
gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.p.l); //5 [write low]
g65816_clrn();
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_lsr_dpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read]
snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testc(gx816->op.r.b & 0x80);
gx816->op.r.b >>= 1;
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.b); //6 [write]
g65816_clrn();
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(2);
}
void g65816_op_lsr_dpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high]
snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testc(gx816->op.r.w & 0x001);
gx816->op.r.w >>= 1;
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1, gx816->op.r.p.h); //6a [write high]
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.p.l); //6 [write low]
g65816_clrn();
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(2);
}
/*****************
*** 0x2a: rol ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void g65816_op_rolb(void) {
byte c = (gx816->regs.p & PF_C)?0x01:0x00;
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
g65816_testc(gx816->regs.a.b & 0x80);
gx816->regs.a.b <<= 1;
gx816->regs.a.b |= c;
g65816_testn(gx816->regs.a.b & 0x80);
g65816_testz(gx816->regs.a.b == 0);
g65816_incpc(1);
}
void g65816_op_rolw(void) {
word c = (gx816->regs.p & PF_C)?0x0001:0x0000;
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
g65816_testc(gx816->regs.a.w & 0x8000);
gx816->regs.a.w <<= 1;
gx816->regs.a.w |= c;
g65816_testn(gx816->regs.a.w & 0x8000);
g65816_testz(gx816->regs.a.w == 0);
g65816_incpc(1);
}
/**********************
*** 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 g65816_op_rol_addrb(void) {
byte c = (gx816->regs.p & PF_C)?0x01:0x00;
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read]
snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testc(gx816->op.r.b & 0x80);
gx816->op.r.b <<= 1;
gx816->op.r.b |= c;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.b); //6 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(3);
}
void g65816_op_rol_addrw(void) {
word c = (gx816->regs.p & PF_C)?0x0001:0x0000;
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high]
snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testc(gx816->op.r.w & 0x8000);
gx816->op.r.w <<= 1;
gx816->op.r.w |= c;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->op.r.p.h); //6a [write high]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.p.l); //6 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(3);
}
/************************
*** 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 g65816_op_rol_addrxb(void) {
byte c = (gx816->regs.p & PF_C)?0x01:0x00;
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read]
snes_time->add_cpu_icycles(1); //6 [i/o]
g65816_testc(gx816->op.r.b & 0x80);
gx816->op.r.b <<= 1;
gx816->op.r.b |= c;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.b); //7 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(3);
}
void g65816_op_rol_addrxw(void) {
word c = (gx816->regs.p & PF_C)?0x0001:0x0000;
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //5a [read high]
snes_time->add_cpu_icycles(1); //6 [i/o]
g65816_testc(gx816->op.r.w & 0x8000);
gx816->op.r.w <<= 1;
gx816->op.r.w |= c;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1, gx816->op.r.p.h); //7a [write high]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.p.l); //7 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(3);
}
/********************
*** 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 g65816_op_rol_dpb(void) {
byte c = (gx816->regs.p & PF_C)?0x01:0x00;
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read]
snes_time->add_cpu_icycles(1); //4 [i/o]
g65816_testc(gx816->op.r.b & 0x80);
gx816->op.r.b <<= 1;
gx816->op.r.b |= c;
gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.b); //5 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(2);
}
void g65816_op_rol_dpw(void) {
word c = (gx816->regs.p & PF_C)?0x0001:0x0000;
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high]
snes_time->add_cpu_icycles(1); //4 [i/o]
g65816_testc(gx816->op.r.w & 0x8000);
gx816->op.r.w <<= 1;
gx816->op.r.w |= c;
gx816->op_write(OPMODE_DP, gx816->op.dp + 1, gx816->op.r.p.h); //5a [write high]
gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.p.l); //5 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_rol_dpxb(void) {
byte c = (gx816->regs.p & PF_C)?0x01:0x00;
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read]
snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testc(gx816->op.r.b & 0x80);
gx816->op.r.b <<= 1;
gx816->op.r.b |= c;
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.b); //6 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(2);
}
void g65816_op_rol_dpxw(void) {
word c = (gx816->regs.p & PF_C)?0x0001:0x0000;
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high]
snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testc(gx816->op.r.w & 0x8000);
gx816->op.r.w <<= 1;
gx816->op.r.w |= c;
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1, gx816->op.r.p.h); //6a [write high]
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.p.l); //6 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(2);
}
/*****************
*** 0x6a: ror ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void g65816_op_rorb(void) {
byte c = (gx816->regs.p & PF_C)?0x80:0x00;
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
g65816_testc(gx816->regs.a.b & 0x01);
gx816->regs.a.b >>= 1;
gx816->regs.a.b |= c;
g65816_testn(gx816->regs.a.b & 0x80);
g65816_testz(gx816->regs.a.b == 0);
g65816_incpc(1);
}
void g65816_op_rorw(void) {
word c = (gx816->regs.p & PF_C)?0x8000:0x0000;
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
g65816_testc(gx816->regs.a.w & 0x0001);
gx816->regs.a.w >>= 1;
gx816->regs.a.w |= c;
g65816_testn(gx816->regs.a.w & 0x8000);
g65816_testz(gx816->regs.a.w == 0);
g65816_incpc(1);
}
/**********************
*** 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 g65816_op_ror_addrb(void) {
byte c = (gx816->regs.p & PF_C)?0x80:0x00;
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read]
snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testc(gx816->op.r.b & 0x01);
gx816->op.r.b >>= 1;
gx816->op.r.b |= c;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.b); //6 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(3);
}
void g65816_op_ror_addrw(void) {
word c = (gx816->regs.p & PF_C)?0x8000:0x0000;
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + 1); //4a [read high]
snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testc(gx816->op.r.w & 0x0001);
gx816->op.r.w >>= 1;
gx816->op.r.w |= c;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->op.r.p.h); //6a [write high]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->op.r.p.l); //6 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(3);
}
/************************
*** 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 g65816_op_ror_addrxb(void) {
byte c = (gx816->regs.p & PF_C)?0x80:0x00;
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read]
snes_time->add_cpu_icycles(1); //6 [i/o]
g65816_testc(gx816->op.r.b & 0x01);
gx816->op.r.b >>= 1;
gx816->op.r.b |= c;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.b); //7 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(3);
}
void g65816_op_ror_addrxw(void) {
word c = (gx816->regs.p & PF_C)?0x8000:0x0000;
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //4 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x); //5 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1); //5a [read high]
snes_time->add_cpu_icycles(1); //6 [i/o]
g65816_testc(gx816->op.r.w & 0x0001);
gx816->op.r.w >>= 1;
gx816->op.r.w |= c;
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1, gx816->op.r.p.h); //7a [write high]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->op.r.p.l); //7 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(3);
}
/********************
*** 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 g65816_op_ror_dpb(void) {
byte c = (gx816->regs.p & PF_C)?0x80:0x00;
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read]
snes_time->add_cpu_icycles(1); //4 [i/o]
g65816_testc(gx816->op.r.b & 0x01);
gx816->op.r.b >>= 1;
gx816->op.r.b |= c;
gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.b); //5 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(2);
}
void g65816_op_ror_dpw(void) {
word c = (gx816->regs.p & PF_C)?0x8000:0x0000;
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //3a [read high]
snes_time->add_cpu_icycles(1); //4 [i/o]
g65816_testc(gx816->op.r.w & 0x0001);
gx816->op.r.w >>= 1;
gx816->op.r.w |= c;
gx816->op_write(OPMODE_DP, gx816->op.dp + 1, gx816->op.r.p.h); //5a [write high]
gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->op.r.p.l); //5 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_ror_dpxb(void) {
byte c = (gx816->regs.p & PF_C)?0x80:0x00;
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.b = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read]
snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testc(gx816->op.r.b & 0x80);
gx816->op.r.b >>= 1;
gx816->op.r.b |= c;
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.b); //6 [write]
g65816_testn(gx816->op.r.b & 0x80);
g65816_testz(gx816->op.r.b == 0);
g65816_incpc(2);
}
void g65816_op_ror_dpxw(void) {
word c = (gx816->regs.p & PF_C)?0x8000:0x0000;
gx816->op.dp = gx816->read_operand(1); //1-2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.r.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [read low]
gx816->op.r.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //4a [read high]
snes_time->add_cpu_icycles(1); //5 [i/o]
g65816_testc(gx816->op.r.w & 0x001);
gx816->op.r.w >>= 1;
gx816->op.r.w |= c;
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1, gx816->op.r.p.h); //6a [write high]
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->op.r.p.l); //6 [write low]
g65816_testn(gx816->op.r.w & 0x8000);
g65816_testz(gx816->op.r.w == 0);
g65816_incpc(2);
}
+443
View File
@@ -0,0 +1,443 @@
/**********************
*** 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 g65816_op_sta_addrb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->regs.a.b); //4 [write]
g65816_incpc(3);
}
void g65816_op_sta_addrw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->regs.a.p.l); //4 [write low]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->regs.a.p.h); //4a [write high]
g65816_incpc(3);
}
/************************
*** 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 g65816_op_sta_addrxb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //3a [write i/o]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->regs.a.b); //4 [write]
g65816_incpc(3);
}
void g65816_op_sta_addrxw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //3a [write i/o]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x, gx816->regs.a.p.l); //4 [write low]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.x + 1, gx816->regs.a.p.h); //4a [write high]
g65816_incpc(3);
}
/********************
*** 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 g65816_op_sta_dpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->regs.a.b); //3 [write]
g65816_incpc(2);
}
void g65816_op_sta_dpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op_write(OPMODE_DP, gx816->op.dp, gx816->regs.a.p.l); //3 [write low]
gx816->op_write(OPMODE_DP, gx816->op.dp + 1, gx816->regs.a.p.h); //3a [write high]
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_sta_idpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->regs.a.b); //5 [write]
g65816_incpc(2);
}
void g65816_op_sta_idpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->regs.a.p.l); //5 [write low]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->regs.a.p.h); //5a [write high]
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_sta_ildpb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->op_write(OPMODE_LONG, gx816->op.aa.l, gx816->regs.a.b); //6 [write]
g65816_incpc(2);
}
void g65816_op_sta_ildpw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->op_write(OPMODE_LONG, gx816->op.aa.l, gx816->regs.a.p.l); //6 [write low]
gx816->op_write(OPMODE_LONG, gx816->op.aa.l + 1, gx816->regs.a.p.h); //6a [write high]
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_sta_longb(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->op_write(OPMODE_LONG, gx816->op.aa.l, gx816->regs.a.b); //5 [write]
g65816_incpc(4);
}
void g65816_op_sta_longw(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->op_write(OPMODE_LONG, gx816->op.aa.l, gx816->regs.a.p.l); //5 [write]
gx816->op_write(OPMODE_LONG, gx816->op.aa.l + 1, gx816->regs.a.p.h); //5a [write]
g65816_incpc(4);
}
/************************
*** 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 g65816_op_sta_longxb(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->op_write(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x, gx816->regs.a.b); //5 [write]
g65816_incpc(4);
}
void g65816_op_sta_longxw(void) {
gx816->op.aa.l = gx816->read_operand(3); //1-4 [op fetch]
gx816->op_write(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x, gx816->regs.a.p.l); //5 [write]
gx816->op_write(OPMODE_LONG, gx816->op.aa.l + gx816->regs.x + 1, gx816->regs.a.p.h); //5a [write]
g65816_incpc(4);
}
/************************
*** 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 g65816_op_sta_addryb(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //3a [write i/o]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y, gx816->regs.a.b); //4 [write]
g65816_incpc(3);
}
void g65816_op_sta_addryw(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //3a [write i/o]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y, gx816->regs.a.p.l); //4 [write low]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1, gx816->regs.a.p.h); //4a [write high]
g65816_incpc(3);
}
/**********************
*** 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 g65816_op_sta_dpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->regs.a.b); //4 [write]
g65816_incpc(2);
}
void g65816_op_sta_dpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x, gx816->regs.a.p.l); //4 [write low]
gx816->op_write(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1, gx816->regs.a.p.h); //4a [write high]
g65816_incpc(2);
}
/************************
*** 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 g65816_op_sta_idpxb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->regs.a.b); //6 [write]
g65816_incpc(2);
}
void g65816_op_sta_idpxw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + gx816->regs.x + 1); //5 [aah]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w, gx816->regs.a.p.l); //6 [write low]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + 1, gx816->regs.a.p.h); //6 [write high]
g65816_incpc(2);
}
/************************
*** 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 g65816_op_sta_idpyb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
snes_time->add_cpu_icycles(1); //4a [write i/o]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y, gx816->regs.a.b); //5 [write]
g65816_incpc(2);
}
void g65816_op_sta_idpyw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
snes_time->add_cpu_icycles(1); //4a [write i/o]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y, gx816->regs.a.p.l); //5 [write low]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1, gx816->regs.a.p.h); //5a [write high]
g65816_incpc(2);
}
/************************
*** 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 g65816_op_sta_ildpyb(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->op_write(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y, gx816->regs.a.b); //6 [write]
g65816_incpc(2);
}
void g65816_op_sta_ildpyw(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [dl!=0]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [aah]
gx816->op.aa.p.b = gx816->op_read(OPMODE_DP, gx816->op.dp + 2); //5 [aab]
gx816->op_write(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y, gx816->regs.a.p.l); //6 [write low]
gx816->op_write(OPMODE_LONG, gx816->op.aa.l + gx816->regs.y + 1, gx816->regs.a.p.h); //6a [write high]
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_sta_srb(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op_write(OPMODE_SP, gx816->op.sp, gx816->regs.a.b); //4 [write]
g65816_incpc(2);
}
void g65816_op_sta_srw(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op_write(OPMODE_SP, gx816->op.sp, gx816->regs.a.p.l); //4 [write low]
gx816->op_write(OPMODE_SP, gx816->op.sp + 1, gx816->regs.a.p.h); //4a [write high]
g65816_incpc(2);
}
/**************************
*** 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 g65816_op_sta_isryb(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y, gx816->regs.a.b); //7 [write]
g65816_incpc(2);
}
void g65816_op_sta_isryw(void) {
gx816->op.sp = gx816->read_operand(1); //1,2 [op fetch]
snes_time->add_cpu_icycles(1); //3 [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_SP, gx816->op.sp); //4 [aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_SP, gx816->op.sp + 1); //5 [aah]
snes_time->add_cpu_icycles(1); //6 [i/o]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y, gx816->regs.a.p.l); //7 [write low]
gx816->op_write(OPMODE_DBR, gx816->op.aa.w + gx816->regs.y + 1, gx816->regs.a.p.h); //7a [write high]
g65816_incpc(2);
}
+357
View File
@@ -0,0 +1,357 @@
/*****************
*** 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 g65816_op_phab(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->stack_write(gx816->regs.a.b); //3 [reg low]
g65816_incpc(1);
}
void g65816_op_phaw(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->stack_write(gx816->regs.a.p.h); //3a [reg high]
gx816->stack_write(gx816->regs.a.p.l); //3 [reg low]
g65816_incpc(1);
}
/*****************
*** 0x8b: phb ***
*****************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; io
[3a] 0,s ; reg high [1]
[3 ] 0,s-1 ; reg low
*/
void g65816_op_phb(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->stack_write(gx816->regs.db); //3 [reg low]
g65816_incpc(1);
}
/*****************
*** 0x0b: phd ***
*****************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; io
[3a] 0,s ; reg high [1]
[3 ] 0,s-1 ; reg low
*/
void g65816_op_phd(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->stack_write(gx816->regs.d >> 8); //3a [reg high]
gx816->stack_write(gx816->regs.d); //3 [reg low]
g65816_incpc(1);
}
/*****************
*** 0x4b: phk ***
*****************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; io
[3a] 0,s ; reg high [1]
[3 ] 0,s-1 ; reg low
*/
void g65816_op_phk(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->stack_write(gx816->regs.pc >> 16); //3 [reg low]
g65816_incpc(1);
}
/*****************
*** 0x08: php ***
*****************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; io
[3a] 0,s ; reg high [1]
[3 ] 0,s-1 ; reg low
*/
void g65816_op_php(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->stack_write(gx816->regs.p); //3 [reg low]
g65816_incpc(1);
}
/*****************
*** 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 g65816_op_phxb(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->stack_write(gx816->regs.x); //3 [reg low]
g65816_incpc(1);
}
void g65816_op_phxw(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->stack_write(gx816->regs.x >> 8); //3a [reg high]
gx816->stack_write(gx816->regs.x); //3 [reg low]
g65816_incpc(1);
}
/*****************
*** 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 g65816_op_phyb(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->stack_write(gx816->regs.y); //3 [reg low]
g65816_incpc(1);
}
void g65816_op_phyw(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(1); //2 [i/o]
gx816->stack_write(gx816->regs.y >> 8); //3a [reg high]
gx816->stack_write(gx816->regs.y); //3 [reg low]
g65816_incpc(1);
}
/*****************
*** 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 g65816_op_plab(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(2); //2,3 [i/o]
gx816->regs.a.b = gx816->stack_read(); //4 [reg low]
g65816_testn(gx816->regs.a.b & 0x80);
g65816_testz(gx816->regs.a.b == 0);
g65816_incpc(1);
}
void g65816_op_plaw(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(2); //2,3 [i/o]
gx816->regs.a.p.l = gx816->stack_read(); //4 [reg low]
gx816->regs.a.p.h = gx816->stack_read(); //4a [reg high]
g65816_testn(gx816->regs.a.w & 0x8000);
g65816_testz(gx816->regs.a.w == 0);
g65816_incpc(1);
}
/*****************
*** 0xab: plb ***
*****************
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 g65816_op_plb(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(2); //2,3 [i/o]
gx816->regs.db = gx816->stack_read(); //4 [reg low]
g65816_testn(gx816->regs.db & 0x80);
g65816_testz(gx816->regs.db == 0);
g65816_incpc(1);
}
/*****************
*** 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 [1]
*/
void g65816_op_pld(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(2); //2,3 [i/o]
gx816->regs.d = gx816->stack_read(); //4 [reg low]
gx816->regs.d |= gx816->stack_read() << 8; //4a [reg high]
g65816_testn(gx816->regs.d & 0x8000);
g65816_testz(gx816->regs.d == 0);
g65816_incpc(1);
}
/*****************
*** 0x28: plp ***
*****************
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 g65816_op_plp(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(2); //2,3 [i/o]
gx816->regs.p = gx816->stack_read(); //4 [reg low]
g65816_incpc(1);
if(gx816->regs.e == true)gx816->regs.p |= 0x30;
if(gx816->regs.p & PF_X) { gx816->regs.x &= 0xff; gx816->regs.y &= 0xff; }
}
/*****************
*** 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 g65816_op_plxb(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(2); //2,3 [i/o]
gx816->regs.x = gx816->stack_read(); //4 [reg low]
g65816_testn(gx816->regs.x & 0x80);
g65816_testz(gx816->regs.x == 0);
g65816_incpc(1);
}
void g65816_op_plxw(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(2); //2,3 [i/o]
gx816->regs.x = gx816->stack_read(); //4 [reg low]
gx816->regs.x |= gx816->stack_read() << 8; //4a [reg high]
g65816_testn(gx816->regs.x & 0x8000);
g65816_testz(gx816->regs.x == 0);
g65816_incpc(1);
}
/*****************
*** 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 g65816_op_plyb(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(2); //2,3 [i/o]
gx816->regs.y = gx816->stack_read(); //4 [reg low]
g65816_testn(gx816->regs.y & 0x80);
g65816_testz(gx816->regs.y == 0);
g65816_incpc(1);
}
void g65816_op_plyw(void) {
snes_time->add_cpu_pcycles(1); //1 [op fetch]
snes_time->add_cpu_icycles(2); //2,3 [i/o]
gx816->regs.y = gx816->stack_read(); //4 [reg low]
gx816->regs.y |= gx816->stack_read() << 8; //4a [reg high]
g65816_testn(gx816->regs.y & 0x8000);
g65816_testz(gx816->regs.y == 0);
g65816_incpc(1);
}
/**********************
*** 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 g65816_op_pea(void) {
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
gx816->stack_write(gx816->op.aa.p.h); //4 [write high]
gx816->stack_write(gx816->op.aa.p.l); //5 [write low]
g65816_incpc(3);
}
/**********************
*** 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 g65816_op_pei(void) {
gx816->op.dp = gx816->read_operand(1); //1,2 [op fetch]
gx816->op_cond(2); //2a [i/o]
gx816->op.aa.p.l = gx816->op_read(OPMODE_DP, gx816->op.dp); //3 [read aal]
gx816->op.aa.p.h = gx816->op_read(OPMODE_DP, gx816->op.dp + 1); //4 [read aah]
gx816->stack_write(gx816->op.aa.p.h); //5 [write aah]
gx816->stack_write(gx816->op.aa.p.l); //6 [write aal]
g65816_incpc(2);
}
/**********************
*** 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 g65816_op_per(void) {
word r;
gx816->op.aa.w = gx816->read_operand(2); //1-3 [op fetch]
snes_time->add_cpu_icycles(1); //4 [i/o]
r = (gx816->regs.pc + (signed short)gx816->op.aa.w + 3);
gx816->stack_write(r >> 8); //5 [write pch]
gx816->stack_write(r); //6 [write pcl]
g65816_incpc(3);
}
+214
View File
@@ -0,0 +1,214 @@
/* bsnes
project started: 10/14/2004
author: byuu */
#include "base.h"
#include "main.h"
#include "timing/timing.h"
#include "cpu/g65816.h"
#include "apu/spc700.h"
#include "bridge/bridge.h"
extern snes_timer *snes_time;
extern g65816 *gx816;
extern sony_spc700 *spc700;
extern ppustate ppu;
extern port_bridge *cpu_apu_bridge;
debugstate debugger;
void debug_test_breakpoint_hit(byte source, byte flag, ulong offset, byte value, int i) {
dprintf("* breakpoint %d hit", i);
debugger.bp_list[i].hit_count++;
debugger.refresh_bp = true;
debug_set_state(DEBUGMODE_WAIT);
if(source == BPSRC_SPCRAM) {
disas_spc700_op();
} else {
disas_g65816_op();
}
}
void debug_test_breakpoint(byte source, byte flag, ulong offset, byte value) {
int i;
if(debug_get_state() == DEBUGMODE_DISABLED)return;
for(i=0;i<16;i++) {
if(debugger.bp_list[i].source != source)continue;
if(debugger.bp_list[i].flags & flag) {
if(debugger.bp_list[i].offset == offset) {
if(debugger.bp_list[i].flags & BP_VAL) {
if(debugger.bp_list[i].value == value) {
debug_test_breakpoint_hit(source, flag, offset, value, i);
}
} else {
debug_test_breakpoint_hit(source, flag, offset, value, i);
}
}
}
}
}
ulong debug_write_status(void) {
if(debugger_enabled() == false)return DEBUGWRITE_NONE;
if(debug_get_state() == DEBUGMODE_RUN) {
if(debugger.trace_enabled == false)return DEBUGWRITE_NONE;
if(debugger.trace_output_enabled == true) {
return DEBUGWRITE_CONSOLE | DEBUGWRITE_TRACE;
}
return DEBUGWRITE_TRACE;
}
return DEBUGWRITE_CONSOLE;
}
void init_debugstate(void) {
debugger.mode = DEBUGMODE_DISABLED;
debugger.mem_ptr = 0x7e0000;
debugger.disas_cpu_op = true;
debugger.disas_apu_op = true;
debugger.refresh_mem = true;
debugger.refresh_bp = true;
debugger.refresh_status = true;
debugger.cpu_op_executed = false;
debugger.apu_op_executed = false;
debugger.output_cpu_instrs = true;
debugger.output_apu_instrs = true;
debugger.output_debug_info = true;
debugger.trace_enabled = false;
debugger.trace_output_enabled = false;
debugger.lock_up = debugger.lock_down = debugger.lock_left = debugger.lock_right = false;
debugger.lock_a = debugger.lock_b = debugger.lock_x = debugger.lock_y = false;
debugger.lock_l = debugger.lock_r = debugger.lock_select = debugger.lock_start = false;
}
void RunSNES(void) {
if(emu_state.rom_loaded == false)return;
if(debugger_enabled() == false) {
gx816->Run();
spc700->Run();
return;
}
if(debug_get_state() == DEBUGMODE_RUN) {
gx816->Run();
spc700->Run();
if(debugger.trace_enabled == true) {
if(debugger.disas_cpu_op == true) {
disas_g65816_op();
debugger.disas_cpu_op = false;
}
if(debugger.disas_apu_op == true) {
disas_spc700_op();
debugger.disas_apu_op = false;
}
}
} else {
if(debugger.disas_cpu_op == true) {
disas_g65816_op();
debugger.disas_cpu_op = false;
}
if(debugger.disas_apu_op == true) {
disas_spc700_op();
debugger.disas_apu_op = false;
}
if(debugger.refresh_mem == true) {
debug_refresh_mem();
debugger.refresh_mem = false;
}
if(debugger.refresh_bp == true) {
debug_refresh_bp();
debugger.refresh_bp = false;
}
if(debugger.refresh_status == true) {
debug_update_status();
debugger.refresh_status = false;
}
if(debug_get_state() == DEBUGMODE_WAIT)return;
if(debug_get_state() == DEBUGMODE_CPUSTEP) {
gx816->Run();
spc700->Run();
if(debugger.cpu_op_executed == true) {
debug_set_state(DEBUGMODE_WAIT);
}
}
if(debug_get_state() == DEBUGMODE_APUSTEP) {
gx816->Run();
spc700->Run();
if(debugger.apu_op_executed == true) {
debug_set_state(DEBUGMODE_WAIT);
}
}
}
debug_update_status();
}
extern vfunc spc700_optbl[256];
void InitSNES(void) {
int i, z;
snes_time = new snes_timer();
gx816 = new g65816();
gx816->PowerOn(1);
spc700 = new sony_spc700();
spc700->Reset();
snes_time->reset_clock();
cpu_apu_bridge = new port_bridge();
if(*emu_state.rom_name == 0) {
emu_state.rom_loaded = false;
} else {
gx816->LoadROM();
emu_state.rom_loaded = true;
}
for(i=0;i<16;i++) {
debugger.bp_list[i].offset = 0;
debugger.bp_list[i].flags = BP_OFF;
debugger.bp_list[i].source = BPSRC_MEM;
debugger.bp_list[i].value = 0;
debugger.bp_list[i].hit_count = 0;
}
}
void ResetSNES(void) {
int i;
gx816->Reset();
spc700->Reset();
snes_time->reset_clock();
for(i=0;i<16;i++) {
debugger.bp_list[i].offset = 0;
debugger.bp_list[i].flags = BP_OFF;
debugger.bp_list[i].source = BPSRC_MEM;
debugger.bp_list[i].value = 0;
debugger.bp_list[i].hit_count = 0;
}
}
#include <windows.h>
int __stdcall WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) {
char fn[MAX_PATH];
strcpy(fn, lpcmdline);
//remove quotes from filename, if neccesary (if path contains spaces, quotes will be around command line arg)
if(*fn == '\"') {
strcpy(emu_state.rom_name, fn + 1);
emu_state.rom_name[strlen(emu_state.rom_name) - 1] = 0;
} else {
strcpy(emu_state.rom_name, fn);
}
//create save ram file name
strcpy(emu_state.sram_name, emu_state.rom_name);
if(strlen(emu_state.sram_name) > 4) {
emu_state.sram_name[strlen(emu_state.sram_name) - 4] = 0;
}
strcat(emu_state.sram_name, ".srm");
init_debugstate();
__winmain(); //located in win/gui.cpp
return 0;
}
+25
View File
@@ -0,0 +1,25 @@
void __winmain(void);
/*
*1 - how many instructions to execute before saving sram data
to emu_state.sram_name
*/
emustate emu_state = {
false, //rom loaded
20000000, //sram save tick count *1
"", "" //rom name, sram name
};
videostate render = {
512, 448, //display resolution
256, 224, //snes internal resolution
false, //fullscreen
true, //show menu
0, //frame skip
0, //frame count
{ true, true, true }, //bg1 enable
{ true, true, true }, //bg2 enable
{ true, true, true }, //bg3 enable
{ true, true, true }, //bg4 enable
{ true, true, true, true, true } //oam enable
};
+434
View File
@@ -0,0 +1,434 @@
#include "../base.h"
#include "../cpu/g65816.h"
#include "../timing/timing.h"
extern g65816 *gx816;
extern emustate emu_state;
extern debugstate debugger;
extern snes_timer *snes_time;
void g65816::InitializeROM(byte memory_map) {
memset(rom, 0, 0x600000);
map = memory_map;
}
void g65816::InitializeWRAM(byte value) {
memset(wram, value, 0x020000);
memset(sram, 0x00, 0x0e0000);
}
/***********************
*** SNES Memory Map ***
**************************************************
*** 00-3f 0000-1fff First 8k WRAM ***
*** 2000-5fff MMIO ***
*** 6000-7fff Expansion RAM (Unmapped) ***
*** 8000-ffff Cartridge ROM ***
*** 40-7d 0000-ffff Cartridge ROM ***
*** 7e-7f 0000-ffff 128k WRAM ***
*** 80-bf 0000-1fff First 8k WRAM ***
*** 2000-5fff MMIO ***
*** 6000-7fff Expansion RAM (Unmapped) ***
*** 8000-ffff Cartridge ROM ***
*** c0-ff 0000-ffff Cartridge ROM ***
**************************************************/
ulong g65816::mirror_offset(ulong addr) {
byte db;
word a;
ulong r = 0;
db = (addr >> 16) & 0xff;
a = (addr & 0xffff);
if(db >= 0x00 && db <= 0x3f) {
if(a >= 0x0000 && a <= 0x1fff) {
r = 0x7e0000 | (a & 0x1fff);
} else if(a >= 0x2000 && a <= 0x5fff) {
r = a;
} else if(a >= 0x6000 && a <= 0x7fff) {
r = (db << 16) | a;
} else if(a >= 0x8000 && a <= 0xffff) {
r = (db << 16) | a;
}
} else if(db >= 0x40 && db <= 0x7d) {
r = (db << 16) | a;
} else if(db >= 0x7e && db <= 0x7f) {
r = addr;
} else if(db >= 0x80 && db <= 0xbf) {
if(a >= 0x0000 && a <= 0x1fff) {
r = 0x7e0000 | (a & 0x1fff);
} else if(a >= 0x2000 && a <= 0x5fff) {
r = a;
} else if(a >= 0x6000 && a <= 0x7fff) {
r = (db << 16) | a;
} else if(a >= 0x8000 && a <= 0xffff) {
r = ((db & 0x7f) << 16) | a;
}
} else if(db >= 0xc0 && db <= 0xff) {
r = addr;
}
return r;
}
ulong g65816::convert_offset(byte read_mode, ulong addr, bool mirror) {
byte db;
switch(read_mode) {
case MEMMODE_DP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
break;
case MEMMODE_DPX:
addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff;
break;
case MEMMODE_DPY:
addr = (regs.d + regs.y + (addr & 0xffff)) & 0xffff;
break;
case MEMMODE_IDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr);
addr |= (regs.db << 16);
break;
case MEMMODE_IDPX:
addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff;
addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr);
addr |= (regs.db << 16);
break;
case MEMMODE_IDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr);
addr += (regs.db << 16) + regs.y;
break;
case MEMMODE_ILDP:
addr = (regs.d + (addr & 0xffff));
addr = mem_read(MEMMODE_LONG, MEMSIZE_LONG, addr);
break;
case MEMMODE_ILDPY:
addr = (regs.d + (addr & 0xffff));
addr = mem_read(MEMMODE_LONG, MEMSIZE_LONG, addr);
addr += regs.y;
break;
case MEMMODE_ADDR:
addr = addr & 0xffff;
addr |= (regs.db << 16);
break;
case MEMMODE_ADDR_PC:
addr = addr & 0xffff;
addr |= (regs.pc & 0xff0000);
break;
case MEMMODE_ADDRX:
addr = (regs.db << 16) + (addr & 0xffff);
addr += regs.x;
break;
case MEMMODE_ADDRY:
addr = (regs.db << 16) + (addr & 0xffff);
addr += regs.y;
break;
case MEMMODE_IADDRX:
addr += regs.x;
addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, (addr & 0x00ffff));
addr |= (regs.pc & 0xff0000);
break;
case MEMMODE_ILADDR:
addr = mem_read(MEMMODE_LONG, MEMSIZE_LONG, addr);
break;
case MEMMODE_IADDR_PC:
addr |= (regs.pc & 0xff0000);
break;
case MEMMODE_IADDRX_PC:
addr += regs.x;
addr |= (regs.pc & 0xff0000);
break;
case MEMMODE_ILADDR_PC:
break;
case MEMMODE_LONG:
break;
case MEMMODE_LONGX:
addr += regs.x;
break;
case MEMMODE_SR:
addr = (regs.s + (addr & 0xff)) & 0xffff;
break;
case MEMMODE_ISRY:
addr = (regs.s + (addr & 0xff)) & 0xffff;
addr = mem_read(MEMMODE_LONG, MEMSIZE_WORD, addr);
addr += (regs.db << 16) + regs.y;
break;
case OPMODE_ADDR:
addr &= 0xffff;
break;
case OPMODE_LONG:
addr &= 0xffffff;
break;
case OPMODE_DBR:
addr = (regs.db << 16) + addr;
break;
case OPMODE_PBR:
addr = (regs.pc & 0xff0000) | (addr & 0xffff);
break;
case OPMODE_DP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
break;
case OPMODE_SP:
addr = (regs.s + (addr & 0xffff)) & 0xffff;
break;
}
if(mirror == true) {
return mirror_offset(addr);
} else {
return addr;
}
}
ulong g65816::read_operand(byte size) {
ulong r;
r = gx816->mem_read(MEMMODE_NONE, size, gx816->regs.pc + 1);
//add size + 1 cycles. the extra cycle is for the actual opcode
//byte itself being read in by the main cpu emulation routine.
snes_time->add_cpu_pcycles(size + 1);
return r;
}
byte g65816::mem_getbyte_direct(ulong addr, byte access_mode) {
byte db;
word a;
db = (addr >> 16) & 0xff;
a = (addr & 0xffff);
if(db == 0x00 && a >= 0x2000 && a <= 0x5fff) {
if(access_mode == MEMACCESS_DEBUGGER) {
return 0x00;
} else {
return mmio_read(addr);
}
}
if(db == 0x7e || db == 0x7f) {
return wram[addr & 0x01ffff];
} else if(db != 0x7e && db != 0x7f && a >= 0x8000 && a <= 0xffff) {
return rom_read(addr, MEMSIZE_BYTE);
} else if(db >= 0x30 && db <= 0x3f) {
if(a >= 0x6000 && a <= 0x7fff) {
addr = ((db - 0x30) * 0x2000) + (a - 0x6000);
addr &= (sram_size - 1);
return sram[addr];
}
} else if(db >= 0x70 && db <= 0x7d) {
addr -= 0x700000;
addr &= (sram_size - 1);
return sram[addr];
} else if(db >= 0xc0 && db <= 0xff) {
return rom_read(addr, MEMSIZE_BYTE);
}
return 0;
}
byte g65816::mem_getbyte(ulong addr, byte access_mode) {
int i;
byte r;
r = mem_getbyte_direct(addr, access_mode);
if(debug_get_state() == DEBUGMODE_DISABLED)return r;
if(access_mode == MEMACCESS_DEBUGGER)return r; //don't report breakpoint hits from debugger
debug_test_bp(BPSRC_MEM, BP_READ, addr, r);
return r;
}
void g65816::mem_putbyte_direct(ulong addr, byte value, byte access_mode) {
byte db;
word a;
db = (addr >> 16) & 0xff;
a = (addr & 0xffff);
if(db == 0x00 && a >= 0x2000 && a <= 0x5fff) {
mmio_write(a, value);
} else if(db == 0x7e || db == 0x7f) {
wram[addr & 0x01ffff] = value;
} else if(db >= 0x30 && db <= 0x3f) {
if(a >= 0x6000 && a <= 0x7fff) {
addr = ((db - 0x30) * 0x2000) + (a - 0x6000);
addr &= (sram_size - 1);
sram[addr] = value;
}
} else if(db >= 0x70 && db <= 0x7d) {
addr -= 0x700000;
addr &= (sram_size - 1);
sram[addr] = value;
}
if(access_mode == MEMACCESS_DEBUGGER) {
if(gx816->map == MEMMAP_LOROM) {
if((db >= 0x00 && db <= 0x5f) || (db >= 0x80 && db <= 0xdf)) {
if(addr >= 0x8000 && addr <= 0xffff) {
rom_write(addr, value, MEMSIZE_BYTE);
}
}
} else if(gx816->map == MEMMAP_HIROM) {
if(db >= 0xc0 && db <= 0xff) {
rom_write(addr, value, MEMSIZE_BYTE);
}
}
}
}
void g65816::mem_putbyte(ulong addr, byte value, byte access_mode) {
int i;
mem_putbyte_direct(addr, value, access_mode);
if(debug_get_state() == DEBUGMODE_DISABLED)return;
if(access_mode == MEMACCESS_DEBUGGER)return; //don't report breakpoint hits from debugger
debug_test_bp(BPSRC_MEM, BP_WRITE, addr, value);
}
ulong g65816::mem_read(byte read_mode, byte read_size, ulong addr, byte access_mode) {
ulong r;
addr = convert_offset(read_mode, addr);
switch(read_size) {
case MEMSIZE_BYTE:
r = mem_getbyte(addr, access_mode);
break;
case MEMSIZE_WORD:
r = mem_getbyte(addr, access_mode) |
mem_getbyte(addr+1, access_mode)<<8;
break;
case MEMSIZE_LONG:
r = mem_getbyte(addr, access_mode) |
mem_getbyte(addr+1, access_mode)<<8 |
mem_getbyte(addr+2, access_mode)<<16;
break;
}
return r;
}
void g65816::mem_write(byte write_mode, byte write_size, ulong addr, ulong value, byte access_mode) {
addr = convert_offset(write_mode, addr);
switch(write_size) {
case MEMSIZE_BYTE:
mem_putbyte(addr, value, access_mode);
break;
case MEMSIZE_WORD:
mem_putbyte(addr, value, access_mode);
mem_putbyte(addr+1, value>>8, access_mode);
break;
case MEMSIZE_LONG:
mem_putbyte(addr, value, access_mode);
mem_putbyte(addr+1, value>>8, access_mode);
mem_putbyte(addr+2, value>>16, access_mode);
break;
}
debugger.refresh_mem = true;
}
/*
todo: move address mirroring into mem_getbyte
in case there are different memory speeds depending
on pre-mirrored addresses.
*/
byte g65816::op_read(byte mode, ulong addr) {
byte r;
addr = convert_offset(mode, addr);
r = mem_getbyte(addr);
snes_time->add_cpu_mcycles(1, addr);
return r;
}
void g65816::op_write(byte mode, ulong addr, byte value) {
mem_putbyte(convert_offset(mode, addr), value);
snes_time->add_cpu_mcycles(1, addr);
}
byte g65816::stack_read(void) {
byte r;
gx816->regs.s++;
if(gx816->regs.e == true) {
gx816->regs.s = 0x0100 | (gx816->regs.s & 0xff);
}
r = mem_getbyte(convert_offset(OPMODE_SP, 0));
snes_time->add_cpu_mcycles(1, gx816->regs.s);
return r;
}
void g65816::stack_write(byte value) {
mem_putbyte(convert_offset(OPMODE_SP, 0), value);
gx816->regs.s--;
if(gx816->regs.e == true) {
gx816->regs.s = 0x0100 | (gx816->regs.s & 0xff);
}
snes_time->add_cpu_mcycles(1, gx816->regs.s);
}
/*
note: case 4 (write) condition is handled directly
in the opcode, since it is always true.
*/
void g65816::op_cond(byte c, ulong n0, ulong n1) {
switch(c) {
case 2: //dl != 0
if((regs.d & 0xff) != 0x00) {
snes_time->add_cpu_icycles(1);
}
break;
case 4: //read across page boundaries, write, or x=0
if((n0 & 0xff00) != (n1 & 0xff00) || !(gx816->regs.p & PF_X)) {
snes_time->add_cpu_icycles(1);
}
break;
}
}
ulong g65816::rom_read(ulong addr, byte read_size) {
ulong r;
if(map == MEMMAP_LOROM) {
if(read_size == MEMSIZE_BYTE) {
r = rom[((addr & 0x7f0000) >> 1) | (addr & 0x7fff)];
} else if(read_size == MEMSIZE_WORD) {
r = rom[((addr & 0x7f0000) >> 1) | (addr & 0x7fff)] |
rom[(((addr + 1) & 0x7f0000) >> 1) | ((addr + 1) & 0x7fff)] << 8;
} else if(read_size == MEMSIZE_LONG) {
r = rom[((addr & 0x7f0000) >> 1) | (addr & 0x7fff)] |
rom[(((addr + 1) & 0x7f0000) >> 1) | ((addr + 1) & 0x7fff)] << 8 |
rom[(((addr + 2) & 0x7f0000) >> 1) | ((addr + 2) & 0x7fff)] << 16;
}
} else if(map == MEMMAP_HIROM) {
if(read_size == MEMSIZE_BYTE) {
r = rom[addr & 0x3fffff];
} else if(read_size == MEMSIZE_WORD) {
r = rom[addr & 0x3fffff] |
rom[(addr + 1) & 0x3fffff] << 8;
} else if(read_size == MEMSIZE_LONG) {
r = rom[addr & 0x3fffff] |
rom[(addr + 1) & 0x3fffff] << 8 |
rom[(addr + 2) & 0x3fffff] << 16;
}
}
return r;
}
void g65816::rom_write(ulong addr, ulong v, byte write_size) {
if(map == MEMMAP_LOROM) {
if(write_size == MEMSIZE_BYTE) {
rom[((addr & 0x7f0000) >> 1) | (addr & 0x7fff)] = v;
} else if(write_size == MEMSIZE_WORD) {
rom[((addr & 0x7f0000) >> 1) | (addr & 0x7fff)] = v;
rom[(((addr + 1) & 0x7f0000) >> 1) | ((addr + 1) & 0x7fff)] = v >> 8;
} else if(write_size == MEMSIZE_LONG) {
rom[((addr & 0x7f0000) >> 1) | (addr & 0x7fff)] = v;
rom[(((addr + 1) & 0x7f0000) >> 1) | ((addr + 1) & 0x7fff)] = v >> 8;
rom[(((addr + 2) & 0x7f0000) >> 1) | ((addr + 2) & 0x7fff)] = v >> 16;
}
} else if(map == MEMMAP_HIROM) {
if(write_size == MEMSIZE_BYTE) {
rom[addr & 0x3fffff] = v;
} else if(write_size == MEMSIZE_WORD) {
rom[addr & 0x3fffff] = v;
rom[(addr + 1) & 0x3fffff] = v >> 8;
} else if(write_size == MEMSIZE_LONG) {
rom[addr & 0x3fffff] = v;
rom[(addr + 1) & 0x3fffff] = v >> 8;
rom[(addr + 2) & 0x3fffff] = v >> 16;
}
}
}
+393
View File
@@ -0,0 +1,393 @@
#include "../base.h"
#include "libvlist.cpp"
typedef struct {
char *s;
ulong size;
}string;
typedef struct {
vectorlist list;
ulong count;
}stringlist;
/***********************
string library functions
***********************/
void strresize(string *str, ulong size) {
char *t;
int sl;
if(str->size == size)return;
sl = strlen(str->s);
t = (char*)malloc(size + 1);
strncpy(t, str->s, size);
free(str->s);
str->s = t;
str->size = size;
}
string *newstr(void) {
string *s;
s = (string*)malloc(sizeof(string));
s->size = 16;
s->s = (char*)malloc(s->size + 1);
*s->s = 0;
return s;
}
void memfree(string *s) {
if(s->s)free(s->s);
free(s);
}
/***************************
stringlist library functions
***************************/
void stradd(stringlist *sl, ulong num) {
int i;
string *s;
while(sl->count < (num + 1)) {
s = newstr();
sl->list.add((ulong)s);
sl->count++;
}
}
string *strget(stringlist *sl, ulong num) {
string *s;
if(sl->count < (num + 1)) { stradd(sl, num); }
s = (string*)sl->list.get(num);
return s;
}
stringlist *newstrlist(void) {
stringlist *sl;
sl = (stringlist*)malloc(sizeof(stringlist));
sl->count = 0;
stradd(sl, 1);
return sl;
}
ulong count(stringlist *sl) {
return sl->count;
}
/****************************
string manipulation functions
****************************/
char *strptr(string *s) { return s->s; }
char *strptr(stringlist *sl, ulong num) { return strget(sl, num)->s; }
void strcpy(string *dest, char *src) {
int srclen = strlen(src);
if(srclen > dest->size) { strresize(dest, srclen); }
strncpy(dest->s, src, dest->size);
}
void strcpy(string *dest, string *src) { strcpy(dest, src->s); }
void strcpy(stringlist *dest, ulong num, char *src) { strcpy(strget(dest, num), src); }
void strcpy(stringlist *dest, ulong num, string *src) { strcpy(strget(dest, num), src->s); }
void strcpy(stringlist *dest, ulong destnum, stringlist *src, ulong srcnum) { strcpy(strget(dest, destnum), strptr(src, srcnum)); }
void strset(string *dest, ulong pos, byte c) {
char *s;
if(pos > dest->size) { strresize(dest, pos); }
dest->s[pos] = c;
}
void strset(stringlist *dest, ulong num, ulong pos, byte c) { strset(strget(dest, num), pos, c); }
void strcat(string *dest, char *src) {
int srclen, destlen;
srclen = strlen(src);
destlen = strlen(dest->s);
if(srclen + destlen > dest->size) { strresize(dest, srclen + destlen); }
strncat(dest->s, src, srclen + destlen);
}
void strcat(string *dest, string *src) { strcat(dest, src->s); }
void strcat(stringlist *dest, ulong num, char *src) { strcat(strget(dest, num), src); }
void strcat(stringlist *dest, ulong num, string *src) { strcat(strget(dest, num), src->s); }
void strcat(stringlist *dest, ulong destnum, stringlist *src, ulong srcnum) { strcat(strget(dest, destnum), strptr(src, srcnum)); }
ulong strlen(string *s) { return strlen(s->s); }
ulong strlen(stringlist *sl, ulong num) { return strlen(strget(sl, num)->s); }
void strinsert(string *dest, char *src, ulong pos) {
string *s = newstr();
strcpy(s, strptr(dest)+pos);
strset(dest, pos, 0);
strcat(dest, src);
strcat(dest, s);
memfree(s);
}
void strinsert(string *dest, string *src, ulong pos) { strinsert(dest, src->s, pos); }
void strinsert(stringlist *dest, ulong num, char *src, ulong pos) { strinsert(strget(dest, num), src, pos); }
void strinsert(stringlist *dest, ulong num, string *src, ulong pos) { strinsert(strget(dest, num), src->s, pos); }
void strinsert(stringlist *dest, ulong destnum, stringlist *src, ulong srcnum, ulong pos) { strinsert(strget(dest, destnum), strptr(src, srcnum), pos); }
void strremove(string *dest, ulong start, ulong length = 0) {
int destlen;
char *s;
int i, sl = strlen(dest->s);
if(start > dest->size) { strresize(dest, start); }
if(!length) {
strset(dest, start, 0);
return;
}
s = strptr(dest);
for(i=start;i<sl;i++) { s[i] = s[i+length]; }
s[i] = 0;
}
void strremove(stringlist *sl, ulong num, ulong start, ulong length = 0) { strremove(strget(sl, num), start, length); }
ulong strcmp(string *dest, char *src) { return strcmp(dest->s, src); }
ulong strcmp(string *dest, string *src) { return strcmp(dest->s, src->s); }
ulong strcmp(stringlist *dest, ulong num, char *src) { return strcmp(strget(dest, num)->s, src); }
ulong strcmp(stringlist *dest, ulong num, string *src) { return strcmp(strget(dest, num)->s, src->s); }
ulong strcmp(stringlist *dest, ulong destnum, stringlist *src, ulong srcnum) { return strcmp(strget(dest, destnum)->s, strptr(src, srcnum)); }
ulong stricmp(char *dest, char *src) {
int i, sl = strlen(dest);
if(sl != strlen(src))return 1;
for(i=0;i<sl;i++) {
if(dest[i] >= 'A' && dest[i] <= 'Z') {
if(dest[i]!=src[i] && dest[i]+0x20!=src[i])return 1;
} else if(dest[i] >='a' && dest[i] <= 'z') {
if(dest[i]!=src[i] && dest[i]-0x20!=src[i])return 1;
} else {
if(dest[i] != src[i])return 1;
}
}
return 0;
}
ulong stricmp(string *dest, char *src) { return stricmp(dest->s, src); }
ulong stricmp(string *dest, string *src) { return stricmp(dest->s, src->s); }
ulong stricmp(stringlist *dest, ulong num, char *src) { return stricmp(strget(dest, num)->s, src); }
ulong stricmp(stringlist *dest, ulong num, string *src) { return stricmp(strget(dest, num)->s, src->s); }
ulong stricmp(stringlist *dest, ulong destnum, stringlist *src, ulong srcnum) { return stricmp(strget(dest, destnum)->s, strptr(src, srcnum)); }
void strlower(char *str) {
int i, sl = strlen(str);
for(i=0;i<sl;i++) { if(str[i] >= 'A' && str[i] <= 'Z')str[i] += 0x20; }
}
void strlower(string *str) { strlower(str->s); }
void strlower(stringlist *sl, ulong num) { strlower(strptr(sl, num)); }
void strupper(char *str) {
int i, sl = strlen(str);
for(i=0;i<sl;i++) { if(str[i] >='a' && str[i] <='z')str[i] -= 0x20; }
}
void strupper(string *str) { strupper(str->s); }
void strupper(stringlist *sl, ulong num) { strupper(strptr(sl, num)); }
ulong strpos(char *str, char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return null;
for(i=0;i<=ssl-ksl;i++) {
if(!memcmp(str+i, key, ksl))return i;
}
return null;
}
ulong strpos(string *dest, char *src) { return strpos(dest->s, src); }
ulong strpos(string *dest, string *src) { return strpos(dest->s, src->s); }
ulong strpos(stringlist *dest, ulong num, char *src) { return strpos(strget(dest, num)->s, src); }
ulong strpos(stringlist *dest, ulong num, string *src) { return strpos(strget(dest, num)->s, src->s); }
ulong strpos(stringlist *dest, ulong destnum, stringlist *src, ulong srcnum) { return strpos(strget(dest, destnum)->s, strptr(src, srcnum)); }
ulong strpos_q(char *str, char *key) {
int i, z, ssl = strlen(str), ksl = strlen(key);
byte x;
if(ksl > ssl)return null;
for(i=0;i<=ssl-ksl;) {
x = str[i];
if(x == '\"' || x == '\'') {
z = i++;
while(str[i] != x && i < ssl)i++;
if(i >= ssl)i = z;
}
if(!memcmp(str+i, key, ksl)) {
return i;
} else {
i++;
}
}
return null;
}
ulong strpos_q(string *dest, char *src) { return strpos_q(dest->s, src); }
ulong strpos_q(string *dest, string *src) { return strpos_q(dest->s, src->s); }
ulong strpos_q(stringlist *dest, ulong num, char *src) { return strpos_q(strget(dest, num)->s, src); }
ulong strpos_q(stringlist *dest, ulong num, string *src) { return strpos_q(strget(dest, num)->s, src->s); }
ulong strpos_q(stringlist *dest, ulong destnum, stringlist *src, ulong srcnum) { return strpos_q(strget(dest, destnum)->s, strptr(src, srcnum)); }
void strtr(char *dest, char *before, char *after) {
int i, l, sl = strlen(dest), bsl = strlen(before), asl = strlen(after);
if((bsl != asl) || bsl == 0)return;
for(i=0;i<sl;i++) {
for(l=0;l<bsl;l++) {
if(dest[i] == before[l])dest[i] = after[l];
}
}
}
void strtr(string *dest, char *before, char *after) { strtr(dest->s, before, after); }
void strtr(stringlist *dest, ulong num, char *before, char *after) { strtr(strptr(dest, num), before, after); }
ulong strbegin(char *str, char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return 1;
if(!memcmp(str, key, ksl))return 0;
return 1;
}
ulong strbegin(string *str, char *key) { return strbegin(str->s, key); }
ulong strbegin(stringlist *str, ulong num, char *key) { return strbegin(strptr(str, num), key); }
ulong stribegin(char *str, char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return 1;
for(i=0;i<ksl;i++) {
if(str[i] >= 'A' && str[i] <= 'Z') {
if(str[i] != key[i] && str[i]+0x20 != key[i])return 1;
} else if(str[i] >= 'a' && str[i] <= 'z') {
if(str[i] != key[i] && str[i]-0x20 != key[i])return 1;
} else {
if(str[i] != key[i])return 1;
}
}
return 0;
}
ulong stribegin(string *str, char *key) { return stribegin(str->s, key); }
ulong stribegin(stringlist *str, ulong num, char *key) { return stribegin(strptr(str, num), key); }
ulong strend(char *str, char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return 1;
if(!memcmp(str + ssl - ksl, key, ksl))return 0;
return 1;
}
ulong strend(string *str, char *key) { return strend(str->s, key); }
ulong strend(stringlist *str, ulong num, char *key) { return strend(strptr(str, num), key); }
ulong striend(char *str, char *key) {
int i, z, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return 1;
for(i=ssl-ksl, z=0;i<ssl;i++, z++) {
if(str[i] >= 'A' && str[i] <= 'Z') {
if(str[i] != key[z] && str[i]+0x20 != key[z])return 1;
} else if(str[i] >= 'a' && str[i] <= 'z') {
if(str[i] != key[z] && str[i]-0x20 != key[z])return 1;
} else {
if(str[i] != key[z])return 1;
}
}
return 0;
}
ulong striend(string *str, char *key) { return striend(str->s, key); }
ulong striend(stringlist *str, ulong num, char *key) { return striend(strptr(str, num), key); }
void strltrim(char *str, char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return;
if(!strbegin(str, key)) {
for(i=0;i<ssl-ksl;i++)str[i] = str[i + ksl];
str[i] = 0;
}
}
void strltrim(string *str, char *key) { strltrim(str->s, key); }
void strltrim(stringlist *str, ulong num, char *key) { strltrim(strptr(str, num), key); }
void striltrim(char *str, char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return;
if(!stribegin(str, key)) {
for(i=0;i<ssl-ksl;i++)str[i] = str[i + ksl];
str[i] = 0;
}
}
void striltrim(string *str, char *key) { striltrim(str->s, key); }
void striltrim(stringlist *str, ulong num, char *key) { striltrim(strptr(str, num), key); }
void strrtrim(char *str, char *key) {
int ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return;
if(!strend(str, key)) {
str[ssl - ksl] = 0;
}
}
void strrtrim(string *str, char *key) { strrtrim(str->s, key); }
void strrtrim(stringlist *str, ulong num, char *key) { strrtrim(strptr(str, num), key); }
void strirtrim(char *str, char *key) {
int ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return;
if(!striend(str, key)) {
str[ssl - ksl] = 0;
}
}
void strirtrim(string *str, char *key) { strirtrim(str->s, key); }
void strirtrim(stringlist *str, ulong num, char *key) { strirtrim(strptr(str, num), key); }
ulong strhex(char *str) {
ulong r = 0, m = 0;
int i, ssl = strlen(str);
byte x;
for(i=0;i<ssl;i++) {
if(str[i] >= '0' && str[i] <= '9');
else if(str[i] >= 'A' && str[i] <= 'F');
else if(str[i] >= 'a' && str[i] <= 'f');
else break;
}
for(--i;i>=0;i--, m+=4) {
x = str[i];
if(x >= '0' && x <= '9')x -= '0';
else if(x >= 'A' && x <= 'F')x -= 'A' - 0x0a;
else if(x >= 'a' && x <= 'f')x -= 'a' - 0x0a;
else return r;
r |= x << m;
}
return r;
}
ulong strhex(string *str) { return strhex(str->s); }
ulong strhex(stringlist *str, ulong num) { return strhex(strptr(str, num)); }
ulong strdec(char *str) {
ulong r = 0, m = 1;
int i, ssl = strlen(str);
byte x;
for(i=0;i<ssl;i++) {
if(str[i] >= '0' && str[i] <= '9');
else break;
}
for(--i;i>=0;i--, m*=10) {
x = str[i];
if(x >= '0' && x <= '9')x -= '0';
else return r;
r += x * m;
}
return r;
}
ulong strdec(string *str) { return strdec(str->s); }
ulong strdec(stringlist *str, ulong num) { return strdec(strptr(str, num)); }
ulong strbin(char *str) {
ulong r = 0, m = 0;
int i, ssl = strlen(str);
byte x;
for(i=0;i<ssl;i++) {
if(str[i] == '0' || str[i] == '1');
else break;
}
for(--i;i>=0;i--, m++) {
x = str[i];
if(str[i] == '0' || str[i] == '1')x -= '0';
else return r;
r |= x << m;
}
return r;
}
ulong strbin(string *str) { return strbin(str->s); }
ulong strbin(stringlist *str, ulong num) { return strbin(strptr(str, num)); }
#include "libstr_math.cpp"
#include "libstr_split.cpp"
#include "libstr_replace.cpp"
#include "libstr_sprintf.cpp"
+181
View File
@@ -0,0 +1,181 @@
#define STRMATH_ADD 1
#define STRMATH_SUB 2
#define STRMATH_MUL 3
#define STRMATH_DIV 4
#define STRMATH_MOD 5
#define STRMATH_AND 6
#define STRMATH_OR 7
#define STRMATH_XOR 8
#define STRMATH_SHL 9
#define STRMATH_SHR 10
#define STRMATH_LINKED 64
#define STRMATHMODE_NEG 1
#define STRMATHMODE_NOT 2
#define __strunktonum() \
if (s1[0] == '0' && s1[1] == 'x')r = strhex(s1 + 2); \
else if(s1[0] == '0' && s1[1] == 'b')r = strbin(s1 + 2); \
else r = strdec(s1)
#define __strmath_setmode() \
if (str[i] == '-') { mode = STRMATHMODE_NEG; i++; } \
else if(str[i] == '~') { mode = STRMATHMODE_NOT; i++; } \
else if(str[i] == '+') { i++; } \
else mode=0
#define __strmath_modeset() \
if (mode == STRMATHMODE_NEG)r *= -1; \
else if(mode == STRMATHMODE_NOT)r =~ r
#define __strmath_set(__x) \
s1[z] = 0; \
z = 0; \
__strunktonum(); \
__strmath_modeset(); \
array[array_size++] = r; \
array_gate[array_size] = __x
/***************************************
strmath(str)
resolves all math entities from within
str, and returns numerical result
example: strmath("5+5")=10
***************************************/
ulong p_strmath(char *str) {
int i = 0, ssl = strlen(str);
byte x, mode = 0;
ulong r, array[128], array_size = 0, z = 0;
byte array_gate[128];
char *s1;
if(!ssl)return 0;
s1 = (char*)malloc(ssl + 1);
__strmath_setmode();
while(i < ssl) {
x = str[i++];
if (x == '+') { __strmath_set(STRMATH_ADD); __strmath_setmode(); }
else if(x == '-') { __strmath_set(STRMATH_SUB); __strmath_setmode(); }
else if(x == '*') { __strmath_set(STRMATH_MUL); __strmath_setmode(); }
else if(x == '/') { __strmath_set(STRMATH_DIV); __strmath_setmode(); }
else if(x == '%') { __strmath_set(STRMATH_MOD); __strmath_setmode(); }
else if(x == '&') { __strmath_set(STRMATH_AND); __strmath_setmode(); }
else if(x == '|') { __strmath_set(STRMATH_OR ); __strmath_setmode(); }
else if(x == '^') { __strmath_set(STRMATH_XOR); __strmath_setmode(); }
else if(x == '<' && str[i] == '<') { __strmath_set(STRMATH_SHL); i++; __strmath_setmode(); }
else if(x == '>' && str[i] == '>') { __strmath_set(STRMATH_SHR); i++; __strmath_setmode(); }
else s1[z++] = x;
}
s1[z] = 0;
__strunktonum();
__strmath_modeset();
array[array_size++] = r;
free(s1);
for(i=1;i<array_size;i++) {
if (array_gate[i] == STRMATH_SHL) { array[i-1] <<= array[i]; array_gate[i] = STRMATH_LINKED; }
else if(array_gate[i] == STRMATH_SHR) { array[i-1] >>= array[i]; array_gate[i] = STRMATH_LINKED; }
}
for(i=1;i<array_size;i++) {
if (array_gate[i] == STRMATH_MUL) { array[i-1] *= array[i]; array_gate[i] = STRMATH_LINKED; }
else if(array_gate[i] == STRMATH_DIV) { array[i-1] /= array[i]; array_gate[i] = STRMATH_LINKED; }
}
r = array[0];
for(i=1;i<array_size;i++) {
if (array_gate[i] == STRMATH_ADD)r += array[i];
else if(array_gate[i] == STRMATH_SUB)r -= array[i];
else if(array_gate[i] == STRMATH_MOD)r %= array[i];
else if(array_gate[i] == STRMATH_AND)r &= array[i];
else if(array_gate[i] == STRMATH_OR )r |= array[i];
else if(array_gate[i] == STRMATH_XOR)r ^= array[i];
}
return r;
}
ulong strmath(char *in_str) {
ulong r = 0;
ulong pdepth = 0, cpdepth, maxpdepth = 0;
ulong pstart, pend, spos;
int i, sc, sl = strlen(in_str);
char *str = (char*)malloc(sl + 1), *str0;
char *pstr;
char num[64];
strcpy(str, in_str);
for(i=0;i<sl;i++) {
if(str[i]=='(') {
pdepth++;
if(pdepth > maxpdepth)maxpdepth = pdepth;
} else if(str[i]==')') {
if(pdepth == 0) {
free(str);
return null; //error! too many )'s
}
pdepth --;
}
}
if(pdepth != 0) {
free(str);
return null; //error! unequal ('s to )'s
}
pdepth = maxpdepth;
while(pdepth) {
cpdepth = 0;
for(i=0;i<sl;) {
if(str[i] == '(')cpdepth++;
if(str[i] == ')')cpdepth--;
i++;
if(cpdepth == pdepth) {
pstart = i;
while(str[i] != ')')i++;
pend = i;
pstr = (char*)malloc(pend-pstart+1);
memcpy(pstr, str+pstart, pend-pstart);
pstr[pend-pstart]=0;
r = p_strmath(pstr);
free(pstr);
sprintf(num, "%d", r);
str0 = (char*)malloc(sl + strlen(num) + 1);
memcpy(str0, str, pstart - 1);
spos = pstart - 1;
memcpy(str0+spos, num, strlen(num));
spos += strlen(num);
sc = spos;
memcpy(str0+spos, str+pend+1, sl-pend-1);
spos += sl - pend - 1;
sl = spos;
str0[sl] = 0;
free(str);
str = str0;
cpdepth--;
i = sc;
}
}
pdepth--;
}
r = p_strmath(str);
free(str);
return r;
}
ulong strmath(string *str) { return strmath(str->s); }
ulong strmath(stringlist *str, ulong num) { return strmath(strptr(str, num)); }
ulong strmathentity(char *str) {
int i, ssl = strlen(str);
for(i=0;i<ssl;i++) {
if(str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/' ||
str[i] == '%' || str[i] == '&' || str[i] == '|' || str[i] == '^' ||
(str[i] == '<' && str[i+1] == '<') || (str[i] == '>' && str[i+1] == '>'))return 1;
}
return 0;
}
ulong strmathentity(string *str) { return strmathentity(str->s); }
ulong strmathentity(stringlist *str, ulong num) { return strmathentity(strptr(str, num)); }
+82
View File
@@ -0,0 +1,82 @@
void replace(string *str, char *key, char *token) {
int i, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str);
ulong replace_count = 0, size;
char *data;
if(ksl > ssl)return;
if(tsl > ksl) { //the new string may be longer than the old string...
for(i=0;i<=ssl-ksl;) { //so let's find out how big of a string we'll need...
if(!memcmp(str->s + i, key, ksl)) {
replace_count++;
i += ksl;
} else i++;
}
size = ssl + ((tsl - ksl) * replace_count);
if(size > str->size)strresize(str, size);
}
data = (char*)malloc(size + 1);
for(i=z=0;i<ssl;) {
if(i <= ssl - ksl) {
if(!memcmp(str->s + i, key, ksl)) {
memcpy(data + z, token, tsl);
z += tsl;
i += ksl;
} else data[z++] = str->s[i++];
} else data[z++] = str->s[i++];
}
data[z] = 0;
strcpy(str, data);
free(data);
}
void replace_q(string *str, char *key, char *token) {
int i, l, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str);
byte x;
ulong replace_count = 0, size;
char *data;
if(ksl > ssl)return;
if(tsl > ksl) {
for(i=0;i<=ssl-ksl;) {
x = str->s[i];
if(x == '\"' || x == '\'') {
l = i;
i++;
while(str->s[i++] != x) {
if(i == ssl) {
i = l;
break;
}
}
}
if(!memcmp(str->s + i, key, ksl)) {
replace_count++;
i += ksl;
} else i++;
}
size = ssl + ((tsl - ksl) * replace_count);
if(size > str->size)strresize(str, size);
}
data = (char*)malloc(size + 1);
for(i=z=0;i<ssl;) {
x = str->s[i];
if(x == '\"' || x == '\'') {
l = i++;
while(str->s[i] != x && i < ssl)i++;
if(i >= ssl)i = l;
else {
memcpy(data + z, str->s + l, i - l);
z += i - l;
}
}
if(i <= ssl - ksl) {
if(!memcmp(str->s + i, key, ksl)) {
memcpy(data + z, token, tsl);
z += tsl;
i += ksl;
replace_count++;
} else data[z++] = str->s[i++];
} else data[z++] = str->s[i++];
}
data[z] = 0;
strcpy(str, data);
free(data);
}
+41
View File
@@ -0,0 +1,41 @@
void split(stringlist *dest, char *key, char *src) {
int i, ssl = strlen(src), ksl = strlen(key);
byte x;
ulong lp = 0, split_count = 0;
for(i=0;i<=ssl-ksl;) {
if(!memcmp(src + i, key, ksl)) {
x = src[i];
src[i] = 0;
strcpy(dest, split_count++, src + lp);
src[i] = x;
i += ksl;
lp = i;
} else i++;
}
strcpy(dest, split_count++, src + lp);
}
void split(stringlist *dest, char *key, string *src) { split(dest, key, src->s); }
void split_q(stringlist *dest, char *key, char *src) {
int i, z, ssl = strlen(src), ksl = strlen(key);
byte x;
ulong lp = 0, split_count = 0;
for(i=0;i<=ssl-ksl;) {
x = src[i];
if(x=='\"' || x=='\'') {
z = i++;
while(src[i] != x && i < ssl)i++;
if(i >= ssl)i = z;
}
if(!memcmp(src + i, key, ksl)) {
x = src[i];
src[i] = 0;
strcpy(dest, split_count++, src + lp);
src[i] = x;
i += ksl;
lp = i;
} else i++;
}
strcpy(dest, split_count++, src + lp);
}
void split_q(stringlist *dest, char *key, string *src) { split_q(dest, key, src->s); }
+130
View File
@@ -0,0 +1,130 @@
void numtobin(char *s, ulong num) {
ulong mask = 0x80000000, len = 0, z = 0;
for(;mask;mask>>=1,len++) { if(num&mask)break; }
len = 32 - len;
do {
if(num&(1<<(len-1)))s[z++] = '1';
else s[z++] = '0';
}while(--len);
s[z] = 0;
}
void sprintf(string *str, char *s, ...) {
va_list args;
char t[2], n[256];
int i, l, sl, z;
byte pad_type, pad_len;
ulong num;
char *r;
va_start(args, s);
strcpy(str, "");
for(i=0;i<strlen(s);i++) {
if(s[i] == '%') {
i++;
if(s[i] == '0' && s[i+1] == '.' && (s[i+2] >= '0' && s[i+2] <= '9')) {
pad_type = 1;
if(s[i+3] >= '0' && s[i+3] <= '9') { pad_len = (s[i+2]-'0')*10 + (s[i+3]-'0'); i+=4; }
else { pad_len = (s[i+2]-'0'); i+=3; }
}
else if(s[i] >= '0' && s[i] <= '9') {
pad_type = 2;
if(s[i+1] >= '0' && s[i+1] <= '9') { pad_len = (s[i]-'0')*10 + (s[i+1]-'0'); i+=2; }
else { pad_len = (s[i]-'0'); i+=1; }
}
else { pad_type = 0; }
if(s[i] == 'd') {
num = va_arg(args, ulong);
sprintf(n, "%d", num);
} else if(s[i] == 'x') {
num = va_arg(args, ulong);
sprintf(n, "%x", num);
} else if(s[i] == 'b') {
num = va_arg(args, ulong);
numtobin(n, num);
} else if(s[i] == 's') {
r = va_arg(args, char*);
}
if(pad_type != 0) {
if(s[i] == 's')sl = strlen(r);
else sl = strlen(n);
if(sl < pad_len) {
while(sl < pad_len) {
strcat(str, (pad_type == 1)?"0":" ");
sl++;
}
}
}
if(s[i] == 's')strcat(str, r);
else strcat(str, n);
} else {
t[0] = s[i];
t[1] = 0;
strcat(str, t);
}
}
va_end(args);
}
void sprintf(stringlist *str_list, ulong str_num, char *s, ...) {
va_list args;
char t[2], n[256];
int i, l, sl, z;
byte pad_type, pad_len;
ulong num;
char *r;
string *str = strget(str_list, str_num);
va_start(args, s);
strcpy(str, "");
for(i=0;i<strlen(s);i++) {
if(s[i] == '%') {
i++;
if(s[i] == '0' && s[i+1] == '.' && (s[i+2] >= '0' && s[i+2] <= '9')) {
pad_type = 1;
if(s[i+3] >= '0' && s[i+3] <= '9') { pad_len = (s[i+2]-'0')*10 + (s[i+3]-'0'); i+=4; }
else { pad_len = (s[i+2]-'0'); i+=3; }
}
else if(s[i] >= '0' && s[i] <= '9') {
pad_type = 2;
if(s[i+1] >= '0' && s[i+1] <= '9') { pad_len = (s[i]-'0')*10 + (s[i+1]-'0'); i+=2; }
else { pad_len = (s[i]-'0'); i+=1; }
}
else { pad_type = 0; }
if(s[i] == 'd') {
num = va_arg(args, ulong);
sprintf(n, "%d", num);
} else if(s[i] == 'x') {
num = va_arg(args, ulong);
sprintf(n, "%x", num);
} else if(s[i] == 'b') {
num = va_arg(args, ulong);
numtobin(n, num);
} else if(s[i] == 's') {
r = va_arg(args, char*);
}
if(pad_type != 0) {
if(s[i] == 's')sl = strlen(r);
else sl = strlen(n);
if(sl < pad_len) {
while(sl < pad_len) {
strcat(str, (pad_type == 1)?"0":" ");
sl++;
}
}
}
if(s[i] == 's')strcat(str, r);
else strcat(str, n);
} else {
t[0] = s[i];
t[1] = 0;
strcat(str, t);
}
}
va_end(args);
}
+55
View File
@@ -0,0 +1,55 @@
ulong __vector_resize(ulong val)
{
int i;
for(i=0;i<32;i++) {
if((1<<i) >= val)break;
}
//if the value is >2 million, this will fail, in which case,
//just use value. otherwise, use the power of 2.
if((1<<i) > val)val = 1<<i;
return val;
}
class vectorlist {
public:
ulong *list, *newlist, size, newsize, max_size;
void alloc(ulong size) {
if(size < max_size)return;
newsize = __vector_resize(size);
newlist = (ulong*)malloc(newsize*4);
memcpy(newlist, list, max_size*4);
free(list);
list = newlist;
max_size = newsize;
}
void add(ulong val) {
size++;
if(size > max_size)alloc(size + 1);
list[size - 1] = val;
}
void set(ulong num, ulong val) {
if(num >= max_size)alloc(num + 1);
list[num] = val;
if(++num > size)size = num;
}
ulong get(ulong num) {
if(num >= max_size)return 0;
return list[num];
}
vectorlist() {
list = 0;
size = 0;
max_size = 8;
list = (ulong*)malloc(8*4);
}
~vectorlist() {
if(list)free(list);
}
};
+260
View File
@@ -0,0 +1,260 @@
#include "../base.h"
#include "../timing/timing.h"
#include "../cpu/g65816.h"
#include "../bridge/bridge.h"
extern g65816 *gx816;
extern snes_timer *snes_time;
extern videostate render;
extern debugstate debugger;
extern port_bridge *cpu_apu_bridge;
ppustate ppu;
#include "ppu_cache.cpp"
#include "ppu_spc.cpp"
#include "ppu_dma.cpp"
#include "ppu_screen.cpp"
#include "ppu_vram.cpp"
#include "ppu_palette.cpp"
#include "ppu_timing.cpp"
#include "ppu_oam.cpp"
#include "ppu_wram.cpp"
#include "ppu_mode7.cpp"
#include "ppu_scroll.cpp"
#include "ppu_muldiv.cpp"
#include "ppu_window.cpp"
#include "ppu_addsub.cpp"
#include "ppu_joypad.cpp"
#include "ppu_misc.cpp"
#include "ppu.cpp"
byte mmio_read(word addr) {
snes_time->update_timer();
if((snes_time->hscan_pos >= 274 || snes_time->vscan_pos >= (ppu.visible_scanlines + 1)) || ppu.display_disable == true) {
switch(addr) {
case 0x2139:return mmio_r2139();
case 0x213a:return mmio_r213a();
case 0x213b:return mmio_r213b();
}
}
switch(addr) {
case 0x2134:return mmio_r2134();
case 0x2135:return mmio_r2135();
case 0x2136:return mmio_r2136();
case 0x2137:return mmio_r2137();
case 0x2138:return mmio_r2138();
case 0x213c:return mmio_r213c();
case 0x213d:return mmio_r213d();
case 0x213e:return mmio_r213e();
case 0x213f:return mmio_r213f();
}
switch(addr) {
case 0x2140:case 0x2141:case 0x2142:case 0x2143:
case 0x2144:case 0x2145:case 0x2146:case 0x2147:
case 0x2148:case 0x2149:case 0x214a:case 0x214b:
case 0x214c:case 0x214d:case 0x214e:case 0x214f:
case 0x2150:case 0x2151:case 0x2152:case 0x2153:
case 0x2154:case 0x2155:case 0x2156:case 0x2157:
case 0x2158:case 0x2159:case 0x215a:case 0x215b:
case 0x215c:case 0x215d:case 0x215e:case 0x215f:
case 0x2160:case 0x2161:case 0x2162:case 0x2163:
case 0x2164:case 0x2165:case 0x2166:case 0x2167:
case 0x2168:case 0x2169:case 0x216a:case 0x216b:
case 0x216c:case 0x216d:case 0x216e:case 0x216f:
case 0x2170:case 0x2171:case 0x2172:case 0x2173:
case 0x2174:case 0x2175:case 0x2176:case 0x2177:
case 0x2178:case 0x2179:case 0x217a:case 0x217b:
case 0x217c:case 0x217d:case 0x217e:case 0x217f:
return mmio_rspc((addr & 3));
break;
case 0x2180:return mmio_r2180();
case 0x21c2:return mmio_r21c2();
case 0x21c3:return mmio_r21c3();
case 0x4016:return mmio_r4016();
case 0x4210:return mmio_r4210();
case 0x4211:return mmio_r4211();
case 0x4212:return mmio_r4212();
case 0x4214:return mmio_r4214();
case 0x4215:return mmio_r4215();
case 0x4216:return mmio_r4216();
case 0x4217:return mmio_r4217();
case 0x4218:return mmio_r4218();
case 0x4219:return mmio_r4219();
default:
/*
dprintf("* mmio: unknown read [%0.4x]", addr);
debug_set_state(DEBUGMODE_WAIT);
disas_g65816_op();
*/
break;
}
if(addr >= 0x4300 && addr <= 0x437f) {
if((addr & 0xf) == 0x8)return mmio_r43x8((addr >> 4) & 7);
if((addr & 0xf) == 0x9)return mmio_r43x9((addr >> 4) & 7);
if((addr & 0xf) == 0xa)return mmio_r43xa((addr >> 4) & 7);
return ppu.mmio_mem_43xx[addr & 0x7f];
}
return 0x00;
}
void mmio_write(word addr, byte value) {
snes_time->update_timer();
if((snes_time->hscan_pos >= 274 || snes_time->vscan_pos >= (ppu.visible_scanlines + 1)) || ppu.display_disable == true) {
switch(addr) {
case 0x2118:mmio_w2118(value);break;
case 0x2119:mmio_w2119(value);break;
case 0x2122:mmio_w2122(value);break;
}
}
switch(addr) {
case 0x2100:mmio_w2100(value);break;
case 0x2101:mmio_w2101(value);break;
case 0x2102:mmio_w2102(value);break;
case 0x2103:mmio_w2103(value);break;
case 0x2104:mmio_w2104(value);break;
case 0x2105:mmio_w2105(value);break;
case 0x2106:mmio_w2106(value);break;
case 0x2107:mmio_w2107(value);break;
case 0x2108:mmio_w2108(value);break;
case 0x2109:mmio_w2109(value);break;
case 0x210a:mmio_w210a(value);break;
case 0x210b:mmio_w210b(value);break;
case 0x210c:mmio_w210c(value);break;
case 0x210d:mmio_w210d(value);break;
case 0x210e:mmio_w210e(value);break;
case 0x210f:mmio_w210f(value);break;
case 0x2110:mmio_w2110(value);break;
case 0x2111:mmio_w2111(value);break;
case 0x2112:mmio_w2112(value);break;
case 0x2113:mmio_w2113(value);break;
case 0x2114:mmio_w2114(value);break;
case 0x2115:mmio_w2115(value);break;
case 0x2116:mmio_w2116(value);break;
case 0x2117:mmio_w2117(value);break;
case 0x211a:mmio_w211a(value);break;
case 0x211b:mmio_w211b(value);break;
case 0x211c:mmio_w211c(value);break;
case 0x211d:mmio_w211d(value);break;
case 0x211e:mmio_w211e(value);break;
case 0x211f:mmio_w211f(value);break;
case 0x2120:mmio_w2120(value);break;
case 0x2121:mmio_w2121(value);break;
case 0x2123:mmio_w2123(value);break;
case 0x2124:mmio_w2124(value);break;
case 0x2125:mmio_w2125(value);break;
case 0x2126:mmio_w2126(value);break;
case 0x2127:mmio_w2127(value);break;
case 0x2128:mmio_w2128(value);break;
case 0x2129:mmio_w2129(value);break;
case 0x212a:mmio_w212a(value);break;
case 0x212b:mmio_w212b(value);break;
case 0x212c:mmio_w212c(value);break;
case 0x212d:mmio_w212d(value);break;
case 0x212e:mmio_w212e(value);break;
case 0x212f:mmio_w212f(value);break;
case 0x2130:mmio_w2130(value);break;
case 0x2131:mmio_w2131(value);break;
case 0x2132:mmio_w2132(value);break;
case 0x2133:mmio_w2133(value);break;
}
if(addr >= 0x2140 && addr <= 0x217f) {
mmio_wspc(addr & 3, value);
}
switch(addr) {
case 0x2180:mmio_w2180(value);break;
case 0x2181:mmio_w2181(value);break;
case 0x2182:mmio_w2182(value);break;
case 0x2183:mmio_w2183(value);break;
}
switch(addr) {
case 0x4016:mmio_w4016(value);break;
case 0x4200:mmio_w4200(value);break;
case 0x4201:mmio_w4201(value);break;
case 0x4202:mmio_w4202(value);break;
case 0x4203:mmio_w4203(value);break;
case 0x4204:mmio_w4204(value);break;
case 0x4205:mmio_w4205(value);break;
case 0x4206:mmio_w4206(value);break;
case 0x4207:mmio_w4207(value);break;
case 0x4208:mmio_w4208(value);break;
case 0x4209:mmio_w4209(value);break;
case 0x420a:mmio_w420a(value);break;
case 0x420b:mmio_w420b(value);break;
case 0x420c:mmio_w420c(value);break;
case 0x420d:mmio_w420d(value);break;
case 0x4300:case 0x4310:case 0x4320:case 0x4330:
case 0x4340:case 0x4350:case 0x4360:case 0x4370:
mmio_w43x0((addr >> 4) & 7, value);
break;
case 0x4301:case 0x4311:case 0x4321:case 0x4331:
case 0x4341:case 0x4351:case 0x4361:case 0x4371:
mmio_w43x1((addr >> 4) & 7, value);
break;
case 0x4302:case 0x4312:case 0x4322:case 0x4332:
case 0x4342:case 0x4352:case 0x4362:case 0x4372:
mmio_w43x2((addr >> 4) & 7, value);
break;
case 0x4303:case 0x4313:case 0x4323:case 0x4333:
case 0x4343:case 0x4353:case 0x4363:case 0x4373:
mmio_w43x3((addr >> 4) & 7, value);
break;
case 0x4304:case 0x4314:case 0x4324:case 0x4334:
case 0x4344:case 0x4354:case 0x4364:case 0x4374:
mmio_w43x4((addr >> 4) & 7, value);
break;
case 0x4305:case 0x4315:case 0x4325:case 0x4335:
case 0x4345:case 0x4355:case 0x4365:case 0x4375:
mmio_w43x5((addr >> 4) & 7, value);
break;
case 0x4306:case 0x4316:case 0x4326:case 0x4336:
case 0x4346:case 0x4356:case 0x4366:case 0x4376:
mmio_w43x6((addr >> 4) & 7, value);
break;
case 0x4307:case 0x4317:case 0x4327:case 0x4337:
case 0x4347:case 0x4357:case 0x4367:case 0x4377:
mmio_w43x7((addr >> 4) & 7, value);
break;
case 0x4308:case 0x4318:case 0x4328:case 0x4338:
case 0x4348:case 0x4358:case 0x4368:case 0x4378:
mmio_w43x8((addr >> 4) & 7, value);
break;
case 0x4309:case 0x4319:case 0x4329:case 0x4339:
case 0x4349:case 0x4359:case 0x4369:case 0x4379:
mmio_w43x9((addr >> 4) & 7, value);
break;
case 0x430a:case 0x431a:case 0x432a:case 0x433a:
case 0x434a:case 0x435a:case 0x436a:case 0x437a:
mmio_w43xa((addr >> 4) & 7, value);
break;
}
if(addr >= 0x4300 && addr <= 0x437f) {
ppu.mmio_mem_43xx[addr & 0x7f] = value;
}
}
+412
View File
@@ -0,0 +1,412 @@
#define RENDER_MAIN 0
#define RENDER_SUB 1
#include "ppu_render.cpp"
byte layer_bg_lookup_mode0[12] = {
BG4, BG3, OAM, BG4, BG3, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
void ppu_render_line_mode0(void) {
ppu_render_line_bg (7, 10, COLORDEPTH_4, BG1);
ppu_render_line_bg (6, 9, COLORDEPTH_4, BG2);
ppu_render_line_bg (1, 4, COLORDEPTH_4, BG3);
ppu_render_line_bg (0, 3, COLORDEPTH_4, BG4);
ppu_render_line_oam(2, 5, 8, 11);
ppu_set_layer_pixels(12, layer_bg_lookup_mode0);
}
byte layer_bg_lookup_mode1_pri0[10] = {
BG3, OAM, BG3, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
byte layer_bg_lookup_mode1_pri1[10] = {
BG3, OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM, BG3
};
void ppu_render_line_mode1(void) {
switch(ppu.bg_priority_mode) {
case 0:
ppu_render_line_bg (5, 8, COLORDEPTH_16, BG1);
ppu_render_line_bg (4, 7, COLORDEPTH_16, BG2);
ppu_render_line_bg (0, 2, COLORDEPTH_4, BG3);
ppu_render_line_oam(1, 3, 6, 9);
ppu_set_layer_pixels(10, layer_bg_lookup_mode1_pri0);
break;
case 1:
ppu_render_line_bg (4, 7, COLORDEPTH_16, BG1);
ppu_render_line_bg (3, 6, COLORDEPTH_16, BG2);
ppu_render_line_bg (0, 9, COLORDEPTH_4, BG3);
ppu_render_line_oam(1, 2, 5, 8);
ppu_set_layer_pixels(10, layer_bg_lookup_mode1_pri1);
break;
}
}
byte layer_bg_lookup_mode2[8] = {
OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
void ppu_render_line_mode2(void) {
ppu_render_line_bg (3, 6, COLORDEPTH_16, BG1);
ppu_render_line_bg (2, 5, COLORDEPTH_16, BG2);
ppu_render_line_oam(0, 1, 4, 7);
ppu_set_layer_pixels(8, layer_bg_lookup_mode2);
}
byte layer_bg_lookup_mode3[8] = {
OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
void ppu_render_line_mode3(void) {
ppu_render_line_bg (3, 6, COLORDEPTH_256, BG1);
ppu_render_line_bg (2, 5, COLORDEPTH_16, BG2);
ppu_render_line_oam(0, 1, 4, 7);
ppu_set_layer_pixels(8, layer_bg_lookup_mode3);
}
byte layer_bg_lookup_mode4[8] = {
OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
void ppu_render_line_mode4(void) {
ppu_render_line_bg (3, 6, COLORDEPTH_256, BG1);
ppu_render_line_bg (2, 5, COLORDEPTH_4, BG2);
ppu_render_line_oam(0, 1, 4, 7);
ppu_set_layer_pixels(8, layer_bg_lookup_mode4);
}
byte layer_bg_lookup_mode5[8] = {
OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
void ppu_render_line_mode5(void) {
ppu_render_line_bg (3, 6, COLORDEPTH_16, BG1);
ppu_render_line_bg (2, 5, COLORDEPTH_4, BG2);
ppu_render_line_oam(0, 1, 4, 7);
ppu_set_layer_pixels(8, layer_bg_lookup_mode5);
}
byte layer_bg_lookup_mode6[6] = {
OAM, OAM, BG1, OAM, BG1, OAM
};
void ppu_render_line_mode6(void) {
ppu_render_line_bg (2, 4, COLORDEPTH_16, BG1);
ppu_render_line_oam(0, 1, 3, 5);
ppu_set_layer_pixels(8, layer_bg_lookup_mode6);
}
byte layer_bg_lookup_mode7[5] = {
OAM, BG1, OAM, OAM, OAM
};
byte layer_bg_lookup_mode7_extbg[6] = {
BG2, OAM, OAM, BG2, OAM, OAM
};
void ppu_render_line_mode7(void) {
if(ppu.mode7_extbg == false) {
ppu_render_line_m7 (1, 0, 0); //bg2 priorities are ignored
ppu_render_line_oam(0, 2, 3, 4);
ppu_set_layer_pixels(5, layer_bg_lookup_mode7);
} else {
ppu_render_line_m7 (0, 0, 3); //bg1 priority is ignored
ppu_render_line_oam(1, 2, 4, 5);
ppu_set_layer_pixels(6, layer_bg_lookup_mode7_extbg);
}
}
void ppu_render_scanline(void) {
int x, y;
ppu.vline_pos = snes_time->vscan_pos;
ppu.hirq_triggered = false;
//new screen initialize
if(ppu.vline_pos == 0) {
hdma_initialize();
ppu.virq_triggered = false;
gx816->nmi_pin = 1;
}
//screen refresh
if(ppu.vline_pos == ppu.visible_scanlines) {
if(render.frame_count == 0) {
UpdateDisplay();
}
render.frame_count++;
if(render.frame_count >= render.frame_skip) {
render.frame_count = 0;
}
}
//automatic joypad read
if(ppu.vline_pos == (ppu.visible_scanlines + 1) && ppu.auto_joypad_read == true) {
UpdateJoypad();
}
y = ppu.vline_pos;
if(y > 0 && y < ppu.visible_scanlines && (render.frame_skip == 0 || render.frame_count == 0)) {
if(ppu.display_disable == true) {
memset(ppu.screen + (y << 1) * 512, 0, 2048);
} else {
ppu_clear_layer_cache();
ppu_clear_pixel_cache();
switch(ppu.bg_mode) {
case 0:ppu_render_line_mode0();break;
case 1:ppu_render_line_mode1();break;
case 2:ppu_render_line_mode2();break;
case 3:ppu_render_line_mode3();break;
case 4:ppu_render_line_mode4();break;
case 5:ppu_render_line_mode5();break;
case 6:ppu_render_line_mode6();break;
case 7:ppu_render_line_mode7();break;
}
ppu_render_line_to_screen();
}
}
}
void ppu_update_scanline(void) {
static bool hdma_triggered = false;
word current_vscan_pos;
//starting a new screen?
if(snes_time->vscan_wrapped == true) {
snes_time->vscan_wrapped = false;
}
if(snes_time->hscan_wrapped == true) {
snes_time->hscan_wrapped = false;
hdma_triggered = false;
ppu_render_scanline();
}
if(snes_time->hscan_pos >= 278 && hdma_triggered == false) {
hdma_update();
hdma_triggered = true;
}
if(gx816->cpu_state == CPUSTATE_STP)return;
if(!(gx816->regs.p & PF_I)) {
if(ppu.vcounter_enabled == true && ppu.hcounter_enabled == true) {
if(snes_time->vscan_pos == ppu.virq_pos && ppu.virq_triggered == false) {
if(snes_time->hscan_pos >= ppu.hirq_pos && ppu.hirq_triggered == false) {
ppu.irq_triggered = true;
ppu.virq_triggered = true;
ppu.hirq_triggered = true;
gx816->InvokeIRQ(0xffee);
}
}
} else if(ppu.vcounter_enabled == true) {
if(snes_time->vscan_pos == ppu.virq_pos && ppu.virq_triggered == false) {
ppu.irq_triggered = true;
ppu.virq_triggered = true;
gx816->InvokeIRQ(0xffee);
}
} else if(ppu.hcounter_enabled == true) {
if(snes_time->hscan_pos >= ppu.hirq_pos && ppu.hirq_triggered == false) {
ppu.irq_triggered = true;
ppu.hirq_triggered = true;
gx816->InvokeIRQ(0xffee);
}
}
}
}
byte oam_read(word addr) {
byte r;
addr &= 1023;
if(addr >= 512) {
addr &= 31;
r = ppu.oam[addr + 512];
debug_test_bp(BPSRC_OAM, BP_READ, addr + 512, r);
} else {
r = ppu.oam[addr];
debug_test_bp(BPSRC_OAM, BP_READ, addr, r);
}
return r;
}
void oam_write(word addr, byte value) {
addr &= 1023;
if(addr >= 512) {
addr &= 31;
ppu.oam[addr + 512] = value;
debug_test_bp(BPSRC_OAM, BP_WRITE, addr + 512, value);
} else {
ppu.oam[addr] = value;
debug_test_bp(BPSRC_OAM, BP_WRITE, addr, value);
}
}
void PPUInit(byte first_time) {
int i, l;
byte r, g, b;
double m;
word *ptr;
if(first_time == 1) {
ppu.screen = (word*)malloc(512 * 478 * 2);
ppu.vram = (byte*)malloc(0x10000);
ppu.cgram = (byte*)malloc(512);
ppu.oam = (byte*)malloc(544);
ppu.light_table = (word*)malloc(16 * 65536 * 2);
ppu_init_tiledata_cache();
for(l=0;l<16;l++) {
ppu.mosaic_table[l] = (word*)malloc(4096 * 2);
for(i=0;i<4096;i++) {
ppu.mosaic_table[l][i] = (i / (l + 1)) * (l + 1);
}
}
ptr = (word*)ppu.light_table;
for(l=0;l<16;l++) {
m = (double)l / 15.0;
for(i=0;i<65536;i++) {
r = (i ) & 31;
g = (i >> 5) & 31;
b = (i >> 10) & 31;
if(l == 0) { r = g = b = 0; }
else if(l == 15);
else {
r = (double)r * m;
g = (double)g * m;
b = (double)b * m;
}
*ptr++ = (r) | (g << 5) | (b << 10);
}
}
}
ppu_clear_tiledata_cache();
memset(ppu.screen, 0, 512 * 478 * 2);
memset(ppu.vram, 0, 0x10000);
memset(ppu.cgram, 0, 512);
memset(ppu.oam, 0, 544);
ppu.ppu_cycles = 0;
ppu.ppu_prev_cycles = 0;
ppu.display_disable = true;
ppu.display_brightness = 15;
//ppu.interlace/ppu.interlace_frame initialized in timing/timing.cpp
ppu.overscan = false;
ppu.visible_scanlines = 224;
ppu.sprite_halve = false;
ppu.hline_pos = 0;
ppu.vline_pos = 0;
ppu.irq_triggered = false;
ppu.virq_triggered = false;
ppu.hirq_triggered = false;
ppu.vram_write_pos = 0;
ppu.vram_read_buffer = 0;
ppu.vram_write_buffer = 0;
ppu.cgram_write_pos = 0;
ppu.wram_write_pos = 0;
ppu.vram_remap_mode = 0;
ppu.vram_inc_size = 2;
ppu.vram_inc_reg = 0;
ppu.oam_write_pos = 0;
ppu.oam_tiledata_loc = 0;
ppu.bg_enabled[OAM] = false;
ppu.ss_bg_enabled[OAM] = false;
ppu.mosaic_size = 0;
ppu.mosaic_enabled[BG4] = false;
ppu.mosaic_enabled[BG3] = false;
ppu.mosaic_enabled[BG2] = false;
ppu.mosaic_enabled[BG1] = false;
ppu.bg_windowing_enabled[OAM] = false;
ppu.ss_bg_windowing_enabled[OAM] = false;
ppu.bg_window1_enabled[OAM] = false;
ppu.bg_window2_enabled[OAM] = false;
ppu.bg_window1_clipmode[OAM] = false;
ppu.bg_window2_clipmode[OAM] = false;
ppu.bg_window_mask[OAM] = false;
for(i=0;i<4;i++) {
ppu.bg_enabled[i] = false;
ppu.ss_bg_enabled[i] = false;
ppu.bg_window1_enabled[i] = false;
ppu.bg_window2_enabled[i] = false;
ppu.bg_windowing_enabled[i] = false;
ppu.ss_bg_windowing_enabled[i] = false;
ppu.bg_window1_clipmode[i] = 0;
ppu.bg_window2_clipmode[i] = 0;
ppu.bg_window_mask[i] = 0;
ppu.bg_tilemap_loc[i] = 0;
ppu.bg_tiledata_loc[i] = 0;
ppu.bg_hscroll_pos[i] = 0;
ppu.bg_vscroll_pos[i] = 0;
}
ppu.bg_priority_mode = 0;
ppu.oam_base_size = 0;
ppu.oam_name_sel = 0;
ppu.bg_mode = 0;
ppu.mul_a = 0;
ppu.mul_b = 0;
ppu.div_a = 0;
ppu.div_b = 0;
ppu.r_4214 = 0;
ppu.r_4216 = 0;
ppu.r_2134 = 0;
ppu.window1_left = 0;
ppu.window1_right = 0;
ppu.window2_left = 0;
ppu.window2_right = 0;
ppu.color_window1_enabled = 0;
ppu.color_window2_enabled = 0;
ppu.color_window1_clipmode = 0;
ppu.color_window2_clipmode = 0;
ppu.color_window_mask = 0;
ppu.color_mask = 0;
ppu.ss_color_mask = 0;
ppu.addsub_mode = 0;
ppu.color_mode = 0;
ppu.color_halve = 0;
for(i=0;i<6;i++) {
ppu.bg_color_enabled[i] = false;
}
ppu.color_r = 0;
ppu.color_g = 0;
ppu.color_b = 0;
ppu.active_hdma_channels = 0;
for(i=0;i<8;i++) {
memset(&dma_channel[i], 0, sizeof(dmachannel));
ppu.hdma_completed[i] = false;
ppu.hdma_scanlines_remaining[i] = 0;
ppu.hdma_index_pointer[i] = 0;
}
hdma_initialize();
ppu.vcounter_enabled = false;
ppu.hcounter_enabled = false;
ppu.hirq_pos = 0;
ppu.virq_pos = 0;
ppu.auto_joypad_read = false;
ppu.joypad_strobe_value = 0;
ppu.latch_toggle = 0;
ppu.latch_vpos = 0;
ppu.latch_hpos = 0;
ppu.m7a = ppu.m7b =
ppu.m7c = ppu.m7d =
ppu.m7x = ppu.m7y = 0;
ppu.m7hofs = ppu.m7vofs = 0x0000;
ppu.mode7_repeat = 0;
ppu.mode7_extbg = false;
ppu.mode7_hflip = false;
ppu.mode7_vflip = false;
ppu.io4201 = 0xff;
ppu.counter_latched = false;
memset(ppu.mmio_mem_43xx, 0, 0x80);
}
+60
View File
@@ -0,0 +1,60 @@
/*
$2130 : fixed color / screen add sub
abcd--ef
ab: main
cd: subscreen
00: all the time
01: inside window only
10: outside window only
11: all the time
e: 0 = enable addsub for fixed color
1 = enable addsub for sub screen
f: color / chardata = direct color
(mode3, 4, 7 only)
*/
void mmio_w2130(byte value) {
ppu.color_mask = (value >> 6) & 3;
ppu.ss_color_mask = (value >> 4) & 3;
ppu.addsub_mode = (value & 0x02)?1:0;
}
/*
$2131 : addsub designation
mrgsdcba
m: 0 = enable add color data mode
1 = enable sub color data mode
r: 1/2 color mode
g: Backarea enable
s: OAM enable
d: BG4 enable
c: BG3 enable
b: BG2 enable
a: BG1 enable
*/
void mmio_w2131(byte value) {
ppu.color_mode = (value & 0x80)?COLORMODE_SUB:COLORMODE_ADD;
ppu.color_halve = (value & 0x40)?1:0;
ppu.bg_color_enabled[BACK] = (value & 0x20)?true:false;
ppu.bg_color_enabled[OAM] = (value & 0x10)?true:false;
ppu.bg_color_enabled[BG4] = (value & 0x08)?true:false;
ppu.bg_color_enabled[BG3] = (value & 0x04)?true:false;
ppu.bg_color_enabled[BG2] = (value & 0x02)?true:false;
ppu.bg_color_enabled[BG1] = (value & 0x01)?true:false;
}
/*
$2132 : addsub settings
bgrddddd
b: affect blue
g: affect green
r: affect red
d: color constant
*/
void mmio_w2132(byte value) {
if(value & 0x80)ppu.color_b = (value & 0x1f);
if(value & 0x40)ppu.color_g = (value & 0x1f);
if(value & 0x20)ppu.color_r = (value & 0x1f);
}
+58
View File
@@ -0,0 +1,58 @@
#define BLENDTYPE_BACK 0
#define BLENDTYPE_MAIN 1
#define BLENDTYPE_SUB 2
#define BLENDTYPE_COMBINE 3
#define COLORDEPTH_4 0
#define COLORDEPTH_16 1
#define COLORDEPTH_256 2
struct {
byte color_main, color_sub;
byte src_main, src_sub;
byte blend_type;
}ppu_pixel_cache[512];
byte ppu_layer_cache[512 * 12];
#define TILE_2BIT 0
#define TILE_4BIT 1
#define TILE_8BIT 2
byte *ppu_bg_tiledata[3];
byte *ppu_bg_tiledata_state[3];
//this should be reset once every scanline
void ppu_clear_pixel_cache(void) {
int i;
for(i=0;i<render.snes_width;i++) {
ppu_pixel_cache[i].color_main =
ppu_pixel_cache[i].color_sub = 0;
ppu_pixel_cache[i].src_main =
ppu_pixel_cache[i].src_sub = BACK;
ppu_pixel_cache[i].blend_type = BLENDTYPE_BACK;
}
}
//this should be reset once every scanline
void ppu_clear_layer_cache(void) {
memset(&ppu_layer_cache, 0, render.snes_width * 12);
}
void ppu_init_tiledata_cache(void) {
ppu_bg_tiledata[TILE_2BIT] = (byte*)malloc(262144);
ppu_bg_tiledata[TILE_4BIT] = (byte*)malloc(131072);
ppu_bg_tiledata[TILE_8BIT] = (byte*)malloc( 65536);
ppu_bg_tiledata_state[TILE_2BIT] = (byte*)malloc( 4096);
ppu_bg_tiledata_state[TILE_4BIT] = (byte*)malloc( 2048);
ppu_bg_tiledata_state[TILE_8BIT] = (byte*)malloc( 1024);
}
void ppu_clear_tiledata_cache(void) {
memset(ppu_bg_tiledata[TILE_2BIT], 0, 262144);
memset(ppu_bg_tiledata[TILE_4BIT], 0, 131072);
memset(ppu_bg_tiledata[TILE_4BIT], 0, 65536);
memset(ppu_bg_tiledata_state[TILE_2BIT], 0, 4096);
memset(ppu_bg_tiledata_state[TILE_4BIT], 0, 2048);
memset(ppu_bg_tiledata_state[TILE_8BIT], 0, 1024);
}
+392
View File
@@ -0,0 +1,392 @@
#define DMATRANSFER_CPUTOMMIO 0
#define DMATRANSFER_MMIOTOCPU 1
#define DMAINDEX_ABSOLUTE 0
#define DMAINDEX_INDIRECT 1
#define DMAWRITE_INC 0
#define DMAWRITE_DEC 1
#define HDMAMODE_NORMAL 0
#define HDMAMODE_CONTINUOUS 1
typedef struct {
bool active;
byte transfer_mode;
bool indirect;
bool fixed_address;
int write_dir;
byte transfer_type;
byte dest_addr;
ulong src_addr;
word transfer_size;
byte indirect_bank;
byte hdma_mode;
word hdma_indirect_pointer;
//hdma specific
bool first_line;
bool repeat;
bool completed;
byte line_counter;
ulong address, iaddress;
word r43x8;
}dmachannel;
dmachannel dma_channel[8];
/*
$43x0 : DMA control
da-ifttt
d: (dma only)
0=read from cpu mem, write to $21xx
1=read from $21xx, write to cpu mem
a: (hdma only)
0=absolute addressing
1=indirect addressing
i: 0=increment address, 1=decrement address
f: 1=fixed address, 0=inc/dec address
t: transfer type
*/
void mmio_w43x0(byte c, byte value) {
dma_channel[c].transfer_mode = (value & 0x80)?DMATRANSFER_MMIOTOCPU:DMATRANSFER_CPUTOMMIO;
dma_channel[c].indirect = (value & 0x40)?true:false;
dma_channel[c].write_dir = (value & 0x10)?-1:1;
dma_channel[c].fixed_address = (value & 0x08)?true:false;
dma_channel[c].transfer_type = (value & 0x07);
}
/*
$43x1 : DMA destination address
bbbbbbbb
b: $2100 | b = destination register - limited to $21xx regs only
*/
void mmio_w43x1(byte c, byte value) {
dma_channel[c].dest_addr = value;
}
/*
$43x2-$43x4 : 24-bit DMA source address
after a dma transfer, this address must be incremented
*/
void mmio_w43x2(byte c, byte value) {
dma_channel[c].src_addr = (dma_channel[c].src_addr & 0xffff00) | value;
}
void mmio_w43x3(byte c, byte value) {
dma_channel[c].src_addr = (dma_channel[c].src_addr & 0xff00ff) | (value << 8);
}
void mmio_w43x4(byte c, byte value) {
dma_channel[c].src_addr = (dma_channel[c].src_addr & 0x00ffff) | (value << 16);
}
/*
$43x5/$43x6 : DMA transfer size
*/
void mmio_w43x5(byte c, byte value) {
dma_channel[c].transfer_size = (dma_channel[c].transfer_size & 0xff00) | value;
}
void mmio_w43x6(byte c, byte value) {
dma_channel[c].transfer_size = (dma_channel[c].transfer_size & 0x00ff) | (value << 8);
}
/*
$43x7 : HDMA indirect bank address
*/
void mmio_w43x7(byte c, byte value) {
dma_channel[c].indirect_bank = value;
}
void dma_mmio_write(byte reg, byte value) {
mmio_write(0x2100 | reg, value);
}
byte dma_mmio_read(byte reg) {
return mmio_read(0x2100 | reg);
}
word dma_cputommio(byte c, byte a) {
byte x;
x = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dma_channel[c].src_addr);
dma_mmio_write(dma_channel[c].dest_addr + a, x);
if(dma_channel[c].fixed_address == false) {
dma_channel[c].src_addr = (dma_channel[c].src_addr & 0xff0000) | ((dma_channel[c].src_addr + dma_channel[c].write_dir) & 0xffff);
}
snes_time->add_cpu_cycles(1, 8);
return --dma_channel[c].transfer_size;
}
word dma_mmiotocpu(byte c, byte a) {
byte x;
x = dma_mmio_read(dma_channel[c].dest_addr + a);
gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, dma_channel[c].src_addr, x);
if(dma_channel[c].fixed_address == false) {
dma_channel[c].src_addr = (dma_channel[c].src_addr & 0xff0000) | ((dma_channel[c].src_addr + dma_channel[c].write_dir) & 0xffff);
}
snes_time->add_cpu_cycles(1, 8);
return --dma_channel[c].transfer_size;
}
void dma_transfer_type0(byte c) {
if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) {
if(dma_cputommio(c, 0) == 0)return;
} else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) {
if(dma_mmiotocpu(c, 0) == 0)return;
}
}
void dma_transfer_type1(byte c) {
if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) {
if(dma_cputommio(c, 0) == 0)return;
if(dma_cputommio(c, 1) == 0)return;
} else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) {
if(dma_mmiotocpu(c, 0) == 0)return;
if(dma_mmiotocpu(c, 1) == 0)return;
}
}
void dma_transfer_type2(byte c) {
if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) {
if(dma_cputommio(c, 0) == 0)return;
} else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) {
if(dma_mmiotocpu(c, 0) == 0)return;
}
}
void dma_transfer_type3(byte c) {
if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) {
if(dma_cputommio(c, 0) == 0)return;
if(dma_cputommio(c, 0) == 0)return;
if(dma_cputommio(c, 1) == 0)return;
if(dma_cputommio(c, 1) == 0)return;
} else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) {
if(dma_mmiotocpu(c, 0) == 0)return;
if(dma_mmiotocpu(c, 0) == 0)return;
if(dma_mmiotocpu(c, 1) == 0)return;
if(dma_mmiotocpu(c, 1) == 0)return;
}
}
void dma_transfer_type4(byte c) {
if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) {
if(dma_cputommio(c, 0) == 0)return;
if(dma_cputommio(c, 1) == 0)return;
if(dma_cputommio(c, 2) == 0)return;
if(dma_cputommio(c, 3) == 0)return;
} else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) {
if(dma_mmiotocpu(c, 0) == 0)return;
if(dma_mmiotocpu(c, 1) == 0)return;
if(dma_mmiotocpu(c, 2) == 0)return;
if(dma_mmiotocpu(c, 3) == 0)return;
}
}
void dma_transfer_type5(byte c) {
if(dma_channel[c].transfer_mode == DMATRANSFER_CPUTOMMIO) {
if(dma_cputommio(c, 0) == 0)return;
if(dma_cputommio(c, 1) == 0)return;
if(dma_cputommio(c, 0) == 0)return;
if(dma_cputommio(c, 1) == 0)return;
} else if(dma_channel[c].transfer_mode == DMATRANSFER_MMIOTOCPU) {
if(dma_mmiotocpu(c, 0) == 0)return;
if(dma_mmiotocpu(c, 1) == 0)return;
if(dma_mmiotocpu(c, 0) == 0)return;
if(dma_mmiotocpu(c, 1) == 0)return;
}
}
/*
This function is called consecutively until all DMA transfers are completed.
Rather than transfer all of the DMA data immediately, control is returned to
the main loop after each DMA transfer so that the APU, PPU, renderer, etc.
can keep in sync. Otherwise, a transfer of 65536 bytes could prevent the renderer
from drawing all scanlines, for example.
Each DMA channel must be completed incrementally. The entire transfer from channel 0
must complete before any data is transferred for channel 1, etc.
*/
void ppu_update_dma(void) {
int i, z;
z = 0;
for(i=0;i<8;i++) {
if(dma_channel[i].active == false)continue;
switch(dma_channel[i].transfer_type) {
case 0:dma_transfer_type0(i);break;
case 1:dma_transfer_type1(i);break;
case 2:dma_transfer_type2(i);break;
case 3:dma_transfer_type3(i);break;
case 4:dma_transfer_type4(i);break;
case 5:dma_transfer_type5(i);break;
case 6:dma_transfer_type2(i);break; //6 is the same as 2
case 7:dma_transfer_type3(i);break; //7 is the same as 3
}
if(dma_channel[i].transfer_size == 0) {
dma_channel[i].active = false;
}
return;
}
gx816->cpu_state = CPUSTATE_RUN;
}
/*
$420b : DMA enable
$420c : HDMA enable
Each bit corresponds to the respecting DMA channel (7,6,5,4,3,2,1,0)
Setting a bit in this register will perform the DMA transfer. Multiple
transfers can be done at once. Requires one cycle per byte transferred.
*/
void mmio_w420b(byte value) {
int i;
ppu.active_hdma_channels &= ~value;
for(i=0;i<8;i++) {
if(value & (1 << i)) {
dma_channel[i].active = true;
gx816->cpu_state = CPUSTATE_DMA;
}
}
}
void mmio_w420c(byte value) {
ppu.active_hdma_channels = value;
}
byte hdma_transfer_lentbl[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
void hdma_write_byte(byte i, byte l, byte x) {
switch(dma_channel[i].transfer_type) {
case 0:
dma_mmio_write(dma_channel[i].dest_addr, x);
break;
case 1:
dma_mmio_write(dma_channel[i].dest_addr + l, x);
break;
case 2:
dma_mmio_write(dma_channel[i].dest_addr, x);
break;
case 3:
dma_mmio_write(dma_channel[i].dest_addr + (l >> 1), x);
break;
case 4:
dma_mmio_write(dma_channel[i].dest_addr + l, x);
break;
case 5:
dma_mmio_write(dma_channel[i].dest_addr + (l & 1), x);
break;
case 6:
dma_mmio_write(dma_channel[i].dest_addr, x);
break;
case 7:
dma_mmio_write(dma_channel[i].dest_addr + (l >> 1), x);
break;
}
}
void hdma_update(void) {
int i, l;
byte x, channels_active = 0;
if(snes_time->vscan_pos > ppu.visible_scanlines)return;
for(i=0;i<8;i++) {
if(dma_channel[i].completed == true)continue;
snes_time->add_cpu_cycles(1, 8);
channels_active++;
if(dma_channel[i].line_counter == 0) {
dma_channel[i].line_counter = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dma_channel[i].address++);
dma_channel[i].r43x8 = dma_channel[i].address;
if(dma_channel[i].line_counter == 0) {
dma_channel[i].completed = true;
continue;
}
if(dma_channel[i].line_counter > 0x80) {
dma_channel[i].repeat = true;
dma_channel[i].line_counter -= 0x80;
} else {
dma_channel[i].repeat = false;
}
dma_channel[i].first_line = true;
if(dma_channel[i].indirect == false) {
dma_channel[i].iaddress = dma_channel[i].address;
} else {
dma_channel[i].iaddress = gx816->mem_read(MEMMODE_NONE, MEMSIZE_WORD, dma_channel[i].address);
dma_channel[i].iaddress |= (dma_channel[i].indirect_bank << 16);
dma_channel[i].address += 2;
snes_time->add_cpu_cycles(1, 16);
}
}
dma_channel[i].line_counter--;
if(dma_channel[i].first_line == false && dma_channel[i].repeat == false)continue;
dma_channel[i].first_line = false;
if(dma_channel[i].indirect == false) {
dma_channel[i].iaddress = dma_channel[i].address;
}
for(l=0;l<hdma_transfer_lentbl[dma_channel[i].transfer_type];l++) {
x = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, dma_channel[i].iaddress++);
if(dma_channel[i].indirect == false) {
dma_channel[i].address++;
}
hdma_write_byte(i, l, x);
snes_time->add_cpu_cycles(1, 8);
}
}
if(channels_active != 0) {
snes_time->add_cpu_cycles(1, 18);
}
}
void hdma_initialize(void) {
int i, active_channels = 0;
for(i=0;i<8;i++) {
if((ppu.active_hdma_channels & (1 << i)) == 0) {
dma_channel[i].completed = true;
continue;
}
active_channels++;
dma_channel[i].first_line = true;
dma_channel[i].repeat = false;
dma_channel[i].line_counter = 0;
dma_channel[i].address = dma_channel[i].src_addr;
dma_channel[i].completed = false;
if(dma_channel[i].indirect == false) {
snes_time->add_cpu_cycles(1, 8);
} else {
snes_time->add_cpu_cycles(1, 24);
}
}
if(active_channels != 0) {
snes_time->add_cpu_cycles(1, 18);
}
}
byte mmio_r43x8(byte c) {
return (dma_channel[c].r43x8);
}
byte mmio_r43x9(byte c) {
return (dma_channel[c].r43x8 >> 8);
}
byte mmio_r43xa(byte c) {
return (dma_channel[c].line_counter + 1);
}
void mmio_w43x8(byte c, byte x) {
dma_channel[c].address = (dma_channel[c].address & 0xff00) | x;
}
void mmio_w43x9(byte c, byte x) {
dma_channel[c].address = (dma_channel[c].address & 0x00ff) | (x << 8);
}
void mmio_w43xa(byte c, byte x) {
dma_channel[c].line_counter = x;
}
+67
View File
@@ -0,0 +1,67 @@
joypad_state joypad1;
/*
*1 - 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.
*/
byte mmio_r4016(void) {
byte r = 0;
if(ppu.joypad_strobe_value == 1) { //*1
r |= joypad1.b;
} else {
if (joypad1.read_pos == 0)r |= joypad1.b;
else if(joypad1.read_pos == 1)r |= joypad1.y;
else if(joypad1.read_pos == 2)r |= joypad1.select;
else if(joypad1.read_pos == 3)r |= joypad1.start;
else if(joypad1.read_pos == 4)r |= joypad1.up;
else if(joypad1.read_pos == 5)r |= joypad1.down;
else if(joypad1.read_pos == 6)r |= joypad1.left;
else if(joypad1.read_pos == 7)r |= joypad1.right;
else if(joypad1.read_pos == 8)r |= joypad1.a;
else if(joypad1.read_pos == 9)r |= joypad1.x;
else if(joypad1.read_pos == 10)r |= joypad1.l;
else if(joypad1.read_pos == 11)r |= joypad1.r;
else if(joypad1.read_pos == 16)r |= 1; //joypad connected bit (1=yes, 0=no)
else r |= 1; //after 16th read, all subsequent reads return 1
if(++joypad1.read_pos > 17)joypad1.read_pos = 17;
}
return r;
}
byte mmio_r4218(void) {
byte r;
if(ppu.auto_joypad_read == false) return 0x00; //cannot read joypad if auto joypad read not enabled
if(ppu.vline_pos >= 225 && ppu.vline_pos <= 227)return 0x00; //cannot read joypad while SNES is polling the joypad data
r = joypad1.a << 7 |
joypad1.x << 6 |
joypad1.l << 5 |
joypad1.r << 4;
return r;
}
byte mmio_r4219(void) {
byte r;
if(ppu.auto_joypad_read == false) return 0x00; //cannot read joypad if auto joypad read not enabled
if(ppu.vline_pos >= 225 && ppu.vline_pos <= 227)return 0x00; //cannot read joypad while SNES is polling the joypad data
r = joypad1.b << 7 |
joypad1.y << 6 |
joypad1.select << 5 |
joypad1.start << 4 |
joypad1.up << 3 |
joypad1.down << 2 |
joypad1.left << 1 |
joypad1.right;
return r;
}
void mmio_w4016(byte value) {
ppu.joypad_strobe_value = value;
if(value == 1)UpdateJoypad();
if(value == 0)joypad1.read_pos = 0;
}
+15
View File
@@ -0,0 +1,15 @@
/*
$21c2/$21c3
These seem to be version information registers... I don't know
what their purpose is, but I do know that the SNES demo rom
expects these values to be returned in order to proceed through
the character test.
*/
byte mmio_r21c2(void) {
return 0x20;
}
byte mmio_r21c3(void) {
return 0x00;
}
+59
View File
@@ -0,0 +1,59 @@
/*
$211a : mode7 settings register
ab0000yx
ab:
00 = use screen repetition if outside screen area
01 = ???
10 = use character 0x00 repetition if outside screen area
11 = use back color if outside screen area
y: vertical screen flip
x: horizontal screen flip
*/
void mmio_w211a(byte value) {
ppu.mode7_repeat = (value >> 6) & 3;
ppu.mode7_vflip = (value & 0x02)?true:false;
ppu.mode7_hflip = (value & 0x01)?true:false;
}
/*
$211b : m7a / 16-bit source operand for signed multiplication
*/
void mmio_w211b(byte value) {
ppu.m7a = (value << 8) | (ppu.m7a >> 8);
}
/*
$211c : m7b / 8-bit source operand for signed multiplication
*/
void mmio_w211c(byte value) {
ppu.m7b = (value << 8) | (ppu.m7b >> 8);
}
/*
$211d : m7c
*/
void mmio_w211d(byte value) {
ppu.m7c = (value << 8) | (ppu.m7c >> 8);
}
/*
$211e : m7d
*/
void mmio_w211e(byte value) {
ppu.m7d = (value << 8) | (ppu.m7d >> 8);
}
/*
$211f : m7x
*/
void mmio_w211f(byte value) {
ppu.m7x = (value << 8) | (ppu.m7x >> 8);
}
/*
$2120 : m7y
*/
void mmio_w2120(byte value) {
ppu.m7y = (value << 8) | (ppu.m7y >> 8);
}
+54
View File
@@ -0,0 +1,54 @@
byte mmio_r2134(void) {
ulong r = ((signed short)ppu.m7a * (signed char)(ppu.m7b >> 8));
return (r);
}
byte mmio_r2135(void) {
ulong r = ((signed short)ppu.m7a * (signed char)(ppu.m7b >> 8));
return (r >> 8);
}
byte mmio_r2136(void) {
ulong r = ((signed short)ppu.m7a * (signed char)(ppu.m7b >> 8));
return (r >> 16);
}
void mmio_w4202(byte value) {
ppu.mul_a = value;
}
void mmio_w4203(byte value) {
ppu.mul_b = value;
ppu.r_4216 = ppu.mul_a * ppu.mul_b;
}
void mmio_w4204(byte value) {
ppu.div_a = (ppu.div_a & 0xff00) | value;
}
void mmio_w4205(byte value) {
ppu.div_a = (ppu.div_a & 0x00ff) | (value << 8);
}
void mmio_w4206(byte value) {
ppu.div_b = value;
ppu.r_4214 = (ppu.div_b)?ppu.div_a / ppu.div_b : 0;
ppu.r_4216 = (ppu.div_b)?ppu.div_a % ppu.div_b : 0;
}
byte mmio_r4214(void) {
return ppu.r_4214;
}
byte mmio_r4215(void) {
return ppu.r_4214 >> 8;
}
byte mmio_r4216(void) {
return ppu.r_4216;
}
byte mmio_r4217(void) {
return ppu.r_4216 >> 8;
}
+86
View File
@@ -0,0 +1,86 @@
/*
$2101 : OAM settings
sssnnbbb
s: base sprite size
small : large
000: 8x8 : 16x16
001: 8x8 : 32x32
010: 8x8 : 64x64
011: 16x16 : 32x32
100: 16x16 : 64x64
101: 32x32 : 64x64
110: 16x32 : 32x64
111: 16x32 : 32x32
small/large is determined by oam size bit
n: name selection (0-3)
b: oam tiledata location (>>14) -- highest bit ignored
*/
void mmio_w2101(byte value) {
ppu.oam_base_size = (value >> 5);
ppu.oam_name_sel = (value >> 3) & 3;
ppu.oam_tiledata_loc = (value & 3) << 14;
}
/*
$2102/$2103 : OAM access address
$2102: llllllll
$2103: ???????h
9-bit address, h = bit 8, l = bits 7-0
*/
byte ppu_oam_write_posl = 0x00, ppu_oam_write_posh = 0x00;
void mmio_w2102(byte value) {
ppu_oam_write_posl = value;
ppu.oam_write_pos = ((ppu_oam_write_posh << 8) | (ppu_oam_write_posl)) * 2;
}
void mmio_w2103(byte value) {
ppu_oam_write_posh = value & 0x01;
ppu.oam_write_pos = ((ppu_oam_write_posh << 8) | (ppu_oam_write_posl)) * 2;
}
byte ppu_oam_latch_data = 0;
/*
$2104 : OAM write
write one byte to OAM data. even writes (bit 0 = 0) are cached
to the OAM latch, and no data is transferred to OAM ram. odd writes
(bit 0 = 1) write the latch value, and then the requested value (2 bytes)
to oam data. writes to OAM address 0x0200 and above (priority / x bit 8 table)
always write, but even writes still update the latch data.
*/
void mmio_w2104(byte value) {
if(ppu.oam_write_pos >= 0x0200) {
if((ppu.oam_write_pos & 1) == 0) {
ppu_oam_latch_data = value;
}
oam_write(ppu.oam_write_pos, value);
} else if((ppu.oam_write_pos & 1) == 0) {
ppu_oam_latch_data = value;
} else {
oam_write((ppu.oam_write_pos & 0x03fe), ppu_oam_latch_data);
oam_write((ppu.oam_write_pos & 0x03fe) + 1, value);
}
ppu.oam_write_pos++;
ppu.oam_write_pos &= 0x03ff;
}
/*
$2138 : OAM read
read one byte from OAM data. if address is even (bit 0 = 0),
latch data is updated.
*/
byte mmio_r2138(void) {
byte r;
r = oam_read(ppu.oam_write_pos);
if((ppu.oam_write_pos & 1) == 0) {
ppu_oam_latch_data = r;
}
ppu.oam_write_pos++;
ppu.oam_write_pos &= 0x03ff;
return r;
}
+39
View File
@@ -0,0 +1,39 @@
/*
$2121 : cgram write position
takes an 8-bit value that indexes into color palette cgram data.
multiply value by 2 to get actual offset into ppu.cgram
*/
void mmio_w2121(byte value) {
ppu.cgram_write_pos = value << 1;
}
/*
$2122 : cgram write
writes to cgram using cgram_write_pos * 2 as an index
*/
void mmio_w2122(byte value) {
ppu.cgram[ppu.cgram_write_pos] = value;
debug_test_bp(BPSRC_CGRAM, BP_WRITE, ppu.cgram_write_pos, value);
ppu.cgram_write_pos++;
ppu.cgram_write_pos &= 0x01ff;
}
/*
$213b : cgram read
read from cgram using cgram_write_pos * 2 as an index
*/
byte mmio_r213b(void) {
byte r;
r = ppu.cgram[ppu.cgram_write_pos];
debug_test_bp(BPSRC_CGRAM, BP_READ, ppu.cgram_write_pos, r);
ppu.cgram_write_pos++;
ppu.cgram_write_pos &= 0x01ff;
return r;
}
+901
View File
@@ -0,0 +1,901 @@
byte ppu_addsub_adjust_buffer_full[96] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 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
};
byte ppu_addsub_adjust_buffer_half[96] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
};
#define ppu_pal_pixel(__i) \
(*((word*)ppu.cgram + __i))
word ppu_addsub_pixels(byte x, byte cdest_index, byte cdest_bg, byte csrc_index, byte csrc_bg) {
int r, g, b;
word cdest = ppu_pal_pixel(cdest_index);
word csrc = ppu_pal_pixel(csrc_index);
word res;
//oam palettes 0-3 are not affected by color add/sub
if(cdest_bg == OAM) {
if(cdest_index < 192) {
return cdest;
}
}
switch(ppu.color_mode) {
case COLORMODE_ADD:
if(ppu.bg_color_enabled[cdest_bg] == true && ppu.color_halve == 1) {
r = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )) >> 1;
g = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) )) >> 1;
b = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) )) >> 1;
} else {
r = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) ));
g = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) ));
b = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) ));
}
break;
case COLORMODE_SUB:
if(ppu.bg_color_enabled[cdest_bg] == true && ppu.color_halve == 1) {
r = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )) >> 1;
g = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) )) >> 1;
b = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) )) >> 1;
} else {
r = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest ) & 31) - ((csrc ) & 31) ));
g = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest >> 5) & 31) - ((csrc >> 5) & 31) ));
b = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest >> 10) & 31) - ((csrc >> 10) & 31) ));
}
break;
}
return ((r) | (g << 5) | (b << 10));
}
word ppu_addsub_pixel(byte x, byte cdest_index, byte cdest_bg) {
int r, g, b;
word cdest = ppu_pal_pixel(cdest_index);
word csrc = (ppu.color_r) | (ppu.color_g << 5) | (ppu.color_b << 10);
word res;
//only oam palettes 4-7 are affected by color add/sub
if(cdest_bg == OAM) {
if(cdest_index < 192) {
return cdest;
}
}
switch(ppu.color_mode) {
case COLORMODE_ADD:
if(ppu.bg_color_enabled[cdest_bg] == true && ppu.color_halve == 1 && ppu.addsub_mode == 0) {
r = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )) >> 1;
g = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) )) >> 1;
b = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) )) >> 1;
} else {
r = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) ));
g = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) ));
b = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) ));
}
break;
case COLORMODE_SUB:
if(ppu.bg_color_enabled[cdest_bg] == true && ppu.color_halve == 1 && ppu.addsub_mode == 0) {
r = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )) >> 1;
g = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) )) >> 1;
b = *(ppu_addsub_adjust_buffer_half + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) )) >> 1;
} else {
r = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest ) & 31) - ((csrc ) & 31) ));
g = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest >> 5) & 31) - ((csrc >> 5) & 31) ));
b = *(ppu_addsub_adjust_buffer_full + 32 + ( ((cdest >> 10) & 31) - ((csrc >> 10) & 31) ));
}
break;
}
return ((r) | (g << 5) | (b << 10));
}
#define ppu_render_bg_tile_line_4(__m) \
col = 0; \
if(d0 & __m)col += 1; \
if(d1 & __m)col += 2; \
*dest++ = col
#define ppu_render_bg_tile_line_16(__m) \
col = 0; \
if(d0 & __m)col += 1; \
if(d1 & __m)col += 2; \
if(d2 & __m)col += 4; \
if(d3 & __m)col += 8; \
*dest++ = col
#define ppu_render_bg_tile_line_256(__m) \
col = 0; \
if(d0 & __m)col += 1; \
if(d1 & __m)col += 2; \
if(d2 & __m)col += 4; \
if(d3 & __m)col += 8; \
if(d4 & __m)col += 16; \
if(d5 & __m)col += 32; \
if(d6 & __m)col += 64; \
if(d7 & __m)col += 128; \
*dest++ = col
void ppu_render_bg_tile(byte color_depth, byte bg, word tile_num) {
byte mask, d0, d1, d2, d3, d4, d5, d6, d7, col;
int x, y;
ulong pos;
byte *dest;
switch(color_depth) {
case COLORDEPTH_4:
dest = (byte*)ppu_bg_tiledata[TILE_2BIT] + tile_num * 64;
pos = tile_num * 16;
y = 8;
while(y--) {
d0 = ppu.vram[pos ];
d1 = ppu.vram[pos + 1];
ppu_render_bg_tile_line_4(0x80);
ppu_render_bg_tile_line_4(0x40);
ppu_render_bg_tile_line_4(0x20);
ppu_render_bg_tile_line_4(0x10);
ppu_render_bg_tile_line_4(0x08);
ppu_render_bg_tile_line_4(0x04);
ppu_render_bg_tile_line_4(0x02);
ppu_render_bg_tile_line_4(0x01);
pos += 2;
}
ppu_bg_tiledata_state[TILE_2BIT][tile_num] = 0;
break;
case COLORDEPTH_16:
dest = (byte*)ppu_bg_tiledata[TILE_4BIT] + tile_num * 64;
pos = tile_num * 32;
y = 8;
while(y--) {
d0 = ppu.vram[pos ];
d1 = ppu.vram[pos + 1];
d2 = ppu.vram[pos + 16];
d3 = ppu.vram[pos + 17];
ppu_render_bg_tile_line_16(0x80);
ppu_render_bg_tile_line_16(0x40);
ppu_render_bg_tile_line_16(0x20);
ppu_render_bg_tile_line_16(0x10);
ppu_render_bg_tile_line_16(0x08);
ppu_render_bg_tile_line_16(0x04);
ppu_render_bg_tile_line_16(0x02);
ppu_render_bg_tile_line_16(0x01);
pos += 2;
}
ppu_bg_tiledata_state[TILE_4BIT][tile_num] = 0;
break;
case COLORDEPTH_256:
dest = (byte*)ppu_bg_tiledata[TILE_8BIT] + tile_num * 64;
pos = tile_num * 64;
y = 8;
while(y--) {
d0 = ppu.vram[pos ];
d1 = ppu.vram[pos + 1];
d2 = ppu.vram[pos + 16];
d3 = ppu.vram[pos + 17];
d4 = ppu.vram[pos + 32];
d5 = ppu.vram[pos + 33];
d6 = ppu.vram[pos + 48];
d7 = ppu.vram[pos + 49];
ppu_render_bg_tile_line_256(0x80);
ppu_render_bg_tile_line_256(0x40);
ppu_render_bg_tile_line_256(0x20);
ppu_render_bg_tile_line_256(0x10);
ppu_render_bg_tile_line_256(0x08);
ppu_render_bg_tile_line_256(0x04);
ppu_render_bg_tile_line_256(0x02);
ppu_render_bg_tile_line_256(0x01);
pos += 2;
}
ppu_bg_tiledata_state[TILE_8BIT][tile_num] = 0;
break;
}
}
#define PPU_MAIN 0
#define PPU_SUB 1
bool windows_not_obstructing(byte layer, byte bg, word x);
bool color_windows_not_obstructing(word x, byte color_mask_type);
void ppu_render_line_to_screen(void) {
int x, x1;
word *ptr, *ptri, *light_table, *light_tablei;
word c, cx, cy;
word screen_width = render.snes_width;
if(ppu.interlace == false) {
ptr = (word*)ppu.screen + ((ppu.vline_pos << 1) ) * 512;
ptri = (word*)ppu.screen + ((ppu.vline_pos << 1) + 1) * 512;
} else {
ptr = (word*)ppu.screen + ((ppu.vline_pos << 1) + ppu.interlace_frame) * 512;
}
light_table = (word*)ppu.light_table + (ppu.display_brightness * 65536);
for(x=x1=0;x<screen_width;x++) {
switch(ppu_pixel_cache[x].blend_type) {
case BLENDTYPE_BACK:
if(color_windows_not_obstructing(x, PPU_MAIN) == true) {
cx = 0x0000;
} else if(ppu.bg_color_enabled[BACK] == true && color_windows_not_obstructing(x, PPU_SUB) == false) {
cx = ppu_addsub_pixel(x, 0, BACK);
} else {
cx = ppu_pal_pixel(0);
}
break;
case BLENDTYPE_MAIN:
if(ppu.bg_color_enabled[ppu_pixel_cache[x].src_main] == true && color_windows_not_obstructing(x, PPU_MAIN) == true) {
cx = 0x0000;
} else if(ppu.bg_color_enabled[ppu_pixel_cache[x].src_main] == true && color_windows_not_obstructing(x, PPU_SUB) == false) {
cx = ppu_addsub_pixel(x, ppu_pixel_cache[x].color_main, ppu_pixel_cache[x].src_main);
} else {
cx = ppu_pal_pixel(ppu_pixel_cache[x].color_main);
}
break;
case BLENDTYPE_SUB:
if(ppu.bg_color_enabled[BACK] && color_windows_not_obstructing(x, PPU_SUB) == false) {
cx = ppu_addsub_pixels(x, 0, BACK, ppu_pixel_cache[x].color_sub, ppu_pixel_cache[x].src_sub);
} else {
cx = ppu_pal_pixel(ppu_pixel_cache[x].color_sub);
}
break;
case BLENDTYPE_COMBINE:
if(color_windows_not_obstructing(x, PPU_SUB) == false) {
if(ppu_pixel_cache[x].src_sub == BACK) {
cx = ppu_addsub_pixels(x, ppu_pixel_cache[x].color_main, ppu_pixel_cache[x].src_main, 0, BACK);
} else {
cx = ppu_addsub_pixels(x, ppu_pixel_cache[x].color_main, ppu_pixel_cache[x].src_main,
ppu_pixel_cache[x].color_sub, ppu_pixel_cache[x].src_sub);
}
} else {
cx = ppu_pal_pixel(ppu_pixel_cache[x].color_main);
}
break;
}
if(ppu.interlace == false) {
*(ptr + (x1 )) = *(light_table + cx);
*(ptri + (x1++)) = *(light_table + cx);
if(screen_width != 256)continue;
*(ptr + (x1 )) = *(light_table + cx);
*(ptri + (x1++)) = *(light_table + cx);
} else {
*(ptr + (x1++)) = *(light_table + cx);
if(screen_width != 256)continue;
*(ptr + (x1++)) = *(light_table + cx);
}
}
}
void ppu_set_pixel(byte bg, word x, byte pal_index) {
if(ppu.bg_enabled[bg] == true && ppu.ss_bg_enabled[bg] == true) {
if(windows_not_obstructing(PPU_MAIN, bg, x) == false)return;
ppu_pixel_cache[x].blend_type = BLENDTYPE_MAIN;
ppu_pixel_cache[x].src_main = bg;
ppu_pixel_cache[x].color_main = pal_index;
if(color_windows_not_obstructing(x, PPU_SUB) == false) {
ppu_pixel_cache[x].src_sub = bg;
ppu_pixel_cache[x].color_sub = pal_index;
}
} else if(ppu.bg_enabled[bg] == true && bg == OAM && pal_index < 192) {
if(windows_not_obstructing(PPU_MAIN, bg, x) == false)return;
ppu_pixel_cache[x].blend_type = BLENDTYPE_MAIN;
ppu_pixel_cache[x].src_main = bg;
ppu_pixel_cache[x].color_main = pal_index;
} else if(ppu.bg_enabled[bg] == true) {
if(windows_not_obstructing(PPU_MAIN, bg, x) == false)return;
if(ppu.bg_color_enabled[bg] == true && ppu_pixel_cache[x].src_sub != BACK) {
ppu_pixel_cache[x].blend_type = BLENDTYPE_COMBINE;
} else {
ppu_pixel_cache[x].blend_type = BLENDTYPE_MAIN;
}
ppu_pixel_cache[x].src_main = bg;
ppu_pixel_cache[x].color_main = pal_index;
} else if(ppu.ss_bg_enabled[bg] == true) {
if(windows_not_obstructing(PPU_SUB, bg, x) == false)return;
ppu_pixel_cache[x].src_sub = bg;
ppu_pixel_cache[x].color_sub = pal_index;
if(ppu_pixel_cache[x].blend_type == BLENDTYPE_BACK) {
ppu_pixel_cache[x].blend_type = BLENDTYPE_SUB;
} else if(ppu_pixel_cache[x].blend_type == BLENDTYPE_MAIN) {
if(ppu_pixel_cache[x].src_main != OAM || (ppu_pixel_cache[x].src_main == OAM && ppu_pixel_cache[x].color_main >= 192)) {
if(ppu.bg_color_enabled[ppu_pixel_cache[x].src_main] == true) {
ppu_pixel_cache[x].blend_type = BLENDTYPE_COMBINE;
}
}
}
}
}
void ppu_set_layer_pixels(byte layer_count, byte *layer_bg_lookup) {
int layer, x = 0, x1;
byte pal;
do {
layer = 0;
x1 = x * 12;
do {
pal = ppu_layer_cache[x1 + layer];
if(pal) {
ppu_set_pixel(layer_bg_lookup[layer], x, pal);
}
layer++;
} while(layer < layer_count);
x++;
} while(x < render.snes_width);
}
#define ppu_set_layer_pixel(__x, __c) ppu_layer_cache[(__x) * 12 + layer_pos] = __c
struct {
byte num;
byte width, height;
word x, y;
word character;
byte v_flip, h_flip;
byte palette;
byte priority;
}current_sprite;
void ppu_set_sprite_attributes(byte sprite_num) {
ulong t;
byte size, b;
word x;
t = *((ulong*)ppu.oam + sprite_num);
b = ppu.oam[512 + (sprite_num >> 2)];
switch(sprite_num & 3) {
case 0: size = (b & 0x02)?1:0; x = (b & 0x01)?0x100:0; break;
case 1: size = (b & 0x08)?1:0; x = (b & 0x04)?0x100:0; break;
case 2: size = (b & 0x20)?1:0; x = (b & 0x10)?0x100:0; break;
case 3: size = (b & 0x80)?1:0; x = (b & 0x40)?0x100:0; break;
}
current_sprite.num = sprite_num;
current_sprite.priority = (t >> 28) & 3;
current_sprite.x = x | (t & 0xff);
current_sprite.y = ((t >> 8) + 1) & 0xff;
current_sprite.v_flip = (t & 0x80000000)?1:0;
current_sprite.h_flip = (t & 0x40000000)?1:0;
current_sprite.palette = (t >> 25) & 7;
current_sprite.character = (t >> 16) & 0x01ff;
//size: 0 = small, 1 = large
switch(ppu.oam_base_size) {
case 0:
if(!size) { current_sprite.width = 8; current_sprite.height = 8; }
else { current_sprite.width = 16; current_sprite.height = 16; }
break;
case 1:
if(!size) { current_sprite.width = 8; current_sprite.height = 8; }
else { current_sprite.width = 32; current_sprite.height = 32; }
break;
case 2:
if(!size) { current_sprite.width = 8; current_sprite.height = 8; }
else { current_sprite.width = 64; current_sprite.height = 64; }
break;
case 3:
if(!size) { current_sprite.width = 16; current_sprite.height = 16; }
else { current_sprite.width = 32; current_sprite.height = 32; }
break;
case 4:
if(!size) { current_sprite.width = 16; current_sprite.height = 16; }
else { current_sprite.width = 64; current_sprite.height = 64; }
break;
case 5:
if(!size) { current_sprite.width = 32; current_sprite.height = 32; }
else { current_sprite.width = 64; current_sprite.height = 64; }
break;
case 6:
if(!size) { current_sprite.width = 16; current_sprite.height = 32; }
else { current_sprite.width = 32; current_sprite.height = 64; }
break;
case 7:
if(!size) { current_sprite.width = 16; current_sprite.height = 32; }
else { current_sprite.width = 32; current_sprite.height = 32; }
break;
}
}
bool windows_not_obstructing(byte layer, byte bg, word x) {
byte w1_mask, w2_mask; //1 = masked, 0 = not masked
word window1_left, window1_right, window2_left, window2_right;
if(layer == PPU_MAIN) {
if(ppu.bg_windowing_enabled[bg] == false)return true;
} else if(layer == PPU_SUB) {
if(ppu.ss_bg_windowing_enabled[bg] == false)return true;
}
window1_left = ppu.window1_left;
window1_right = ppu.window1_right;
window2_left = ppu.window2_left;
window2_right = ppu.window2_right;
if(ppu.bg_mode == 5 || ppu.bg_mode == 6) {
window1_left <<= 1;
window1_right <<= 1;
window2_left <<= 1;
window2_right <<= 1;
}
if(ppu.bg_window1_enabled[bg] == true && ppu.bg_window2_enabled[bg] == false) {
if(ppu.bg_window1_clipmode[bg] == CLIPMODE_IN) {
if(x >= window1_left && x <= window1_right)return false;
return true;
} else {
if(x < window1_left || x > window1_right)return false;
return true;
}
} else if(ppu.bg_window2_enabled[bg] == true && ppu.bg_window1_enabled[bg] == false) {
if(ppu.bg_window2_clipmode[bg] == CLIPMODE_IN) {
if(x >= window2_left && x <= window2_right)return false;
return true;
} else {
if(x < window2_left || x > window2_right)return false;
return true;
}
} else if(ppu.bg_window1_enabled[bg] == true && ppu.bg_window2_enabled[bg] == true) {
if(ppu.bg_window1_clipmode[bg] == CLIPMODE_IN) {
if(x >= window1_left && x <= window1_right)w1_mask = 1;
else w1_mask = 0;
} else {
if(x < window1_left || x > window1_right)w1_mask = 1;
else w1_mask = 0;
}
if(ppu.bg_window2_clipmode[bg] == CLIPMODE_IN) {
if(x >= window2_left && x <= window2_right)w2_mask = 1;
else w2_mask = 0;
} else {
if(x < window2_left || x > window2_right)w2_mask = 1;
else w2_mask = 0;
}
switch(ppu.bg_window_mask[bg]) {
case WINDOWMASK_OR:
if((w1_mask | w2_mask) == 1)return false;
return true;
case WINDOWMASK_AND:
if((w1_mask & w2_mask) == 1)return false;
return true;
case WINDOWMASK_XOR:
if((w1_mask ^ w2_mask) == 1)return false;
return true;
case WINDOWMASK_XNOR:
if((w1_mask ^ w2_mask) == 0)return false;
return true;
}
}
return true;
}
bool color_windows_not_obstructing(word x, byte color_mask_type) {
byte w1_mask, w2_mask; //1 = masked, 0 = not masked
byte color_mask;
bool r;
word window1_left, window1_right, window2_left, window2_right;
if(color_mask_type == PPU_MAIN)color_mask = ppu.color_mask;
else color_mask = ppu.ss_color_mask;
if(color_mask == 0)return false;
if(color_mask == 3)return true;
window1_left = ppu.window1_left;
window1_right = ppu.window1_right;
window2_left = ppu.window2_left;
window2_right = ppu.window2_right;
if(ppu.bg_mode == 5 || ppu.bg_mode == 6) {
window1_left <<= 1;
window1_right <<= 1;
window2_left <<= 1;
window2_right <<= 1;
}
if(ppu.color_window1_enabled == false && ppu.color_window2_enabled == false) {
r = true;
} else if(ppu.color_window1_enabled == true && ppu.color_window2_enabled == false) {
if(ppu.color_window1_clipmode == CLIPMODE_IN) {
if(x >= window1_left && x <= window1_right)r = false;
else r = true;
} else {
if(x < window1_left || x > window1_right)r = false;
else r = true;
}
} else if(ppu.color_window1_enabled == false && ppu.color_window2_enabled == true) {
if(ppu.color_window2_clipmode == CLIPMODE_IN) {
if(x >= window2_left && x <= window2_right)r = false;
else r = true;
} else {
if(x < window2_left || x > window2_right)r = false;
else r = true;
}
} else if(ppu.color_window1_enabled == true && ppu.color_window2_enabled == true) {
if(ppu.color_window1_clipmode == CLIPMODE_IN) {
if(x >= window1_left && x <= window1_right)w1_mask = 1;
else w1_mask = 0;
} else {
if(x < window1_left || x > window1_right)w1_mask = 1;
else w1_mask = 0;
}
if(ppu.color_window2_clipmode == CLIPMODE_IN) {
if(x >= window2_left && x <= window2_right)w2_mask = 1;
else w2_mask = 0;
} else {
if(x < window2_left || x > window2_right)w2_mask = 1;
else w2_mask = 0;
}
switch(ppu.color_window_mask) {
case WINDOWMASK_OR:
if((w1_mask | w2_mask) == 1)r = false;
else r = true;
break;
case WINDOWMASK_AND:
if((w1_mask & w2_mask) == 1)r = false;
else r = true;
break;
case WINDOWMASK_XOR:
if((w1_mask ^ w2_mask) == 1)r = false;
else r = true;
break;
case WINDOWMASK_XNOR:
if((w1_mask ^ w2_mask) == 0)r = false;
else r = true;
break;
}
}
if(color_mask == 2) {
r = (r == true)?false:true;
}
return r;
}
/*
*1 - When bit 8 of a sprite's character number is set, such that character data
is read from the upper half (upper 8k) of sprite vram, bits 4-3 of $2101
are added to bits 14-13 of the tiledata location. The address wraps around
the 64k bank. Why this happens, or what it's for, I have no idea.
*2 - The sprite tiledata is stored with 16 tiles making up the first row, followed
by 16 tiles making up the second row, and so on. Therefore, to get the
correct y tile, y / 8 * 1 row (16 tiles) must be used.
*/
#define OAM_PRI_NONE 4
byte ppu_oam_line_pal[512], ppu_oam_line_pri[512];
void ppu_render_oam_sprite(void) {
word pos, col, chr, tiledata_inc;
byte d0, d1, d2, d3, pal_index;
int x, y, z, x1, mx, mask, p;
int tile_width;
if(ppu.bg_enabled[OAM] == false && ppu.ss_bg_enabled[OAM] == false)return;
tile_width = current_sprite.width >> SH_8; //e.x. 16x16 sprite = 2x2 tiles
if(ppu.interlace == true && (ppu.bg_mode == 5 || ppu.bg_mode == 6)) {
y = (ppu.vline_pos << SH_2) + ppu.interlace_frame;
} else {
y = ppu.vline_pos;
}
x = current_sprite.x;
if(render.snes_width == 512) {
x <<= SH_2;
}
if(current_sprite.v_flip) {
y = ((current_sprite.height - 1) - (ppu.vline_pos - current_sprite.y));
} else {
y = (ppu.vline_pos - current_sprite.y);
}
y &= 255;
if(ppu.sprite_halve == true) {
y <<= 1;
y += ppu.interlace_frame;
}
chr = current_sprite.character;
tiledata_inc = (chr & 0x100)?(ppu.oam_name_sel << 13):0; //*1
chr += (y >> SH_8) << SH_16; //*2
pal_index = (current_sprite.palette << SH_16);
for(x1=0;x1<tile_width;x1++) {
if(current_sprite.h_flip)mx = (tile_width - 1) - x1;
else mx = x1;
pos = ppu.oam_tiledata_loc + ((chr + mx) << SH_32) + ((y & 7) << SH_2) + tiledata_inc;
d0 = ppu.vram[pos ];
d1 = ppu.vram[pos + 1];
d2 = ppu.vram[pos + 16];
d3 = ppu.vram[pos + 17];
for(z=0;z<8;z++) {
if(current_sprite.h_flip) {
mask = 0x01 << z;
} else {
mask = 0x80 >> z;
}
x &= 511;
if(x < render.snes_width) {
col = 0;
if(d0 & mask)col += 1;
if(d1 & mask)col += 2;
if(d2 & mask)col += 4;
if(d3 & mask)col += 8;
if(col) {
col += pal_index;
col += 128;
if(ppu_oam_line_pri[x] == OAM_PRI_NONE) {
ppu_oam_line_pal[x] = col;
ppu_oam_line_pri[x] = current_sprite.priority;
}
if(render.snes_width == 512) {
if(ppu_oam_line_pri[x + 1] == OAM_PRI_NONE) {
ppu_oam_line_pal[x + 1] = col;
ppu_oam_line_pri[x + 1] = current_sprite.priority;
}
}
}
}
x++;
if(render.snes_width == 512) {
x++;
}
}
}
}
/*
*/
void ppu_render_line_oam(byte layer_pos_pri0, byte layer_pos_pri1, byte layer_pos_pri2, byte layer_pos_pri3) {
int i, s;
byte layer_pos;
if(ppu.bg_enabled[OAM] != true && ppu.ss_bg_enabled[OAM] != true)return;
memset(ppu_oam_line_pri, OAM_PRI_NONE, 512);
for(s=0;s<128;s++) {
ppu_set_sprite_attributes(s);
if(ppu.sprite_halve == false) {
if(ppu.vline_pos >= current_sprite.y && ppu.vline_pos < (current_sprite.y + current_sprite.height)) {
ppu_render_oam_sprite();
} else if((current_sprite.y + current_sprite.height) >= 256 && ppu.vline_pos < ((current_sprite.y + current_sprite.height) & 255)) {
ppu_render_oam_sprite();
}
} else {
if(ppu.vline_pos >= current_sprite.y && ppu.vline_pos < (current_sprite.y + (current_sprite.height >> 1))) {
ppu_render_oam_sprite();
} else if((current_sprite.y + current_sprite.height) >= 256 && ppu.vline_pos < ((current_sprite.y + (current_sprite.height >> 1)) & 255)) {
ppu_render_oam_sprite();
}
}
}
for(i=0;i<render.snes_width;i++) {
if(ppu_oam_line_pri[i] != OAM_PRI_NONE) {
switch(ppu_oam_line_pri[i]) {
case 0:layer_pos = layer_pos_pri0;break;
case 1:layer_pos = layer_pos_pri1;break;
case 2:layer_pos = layer_pos_pri2;break;
case 3:layer_pos = layer_pos_pri3;break;
}
ppu_set_layer_pixel(i, ppu_oam_line_pal[i]);
}
}
}
/*
*1 - map_index
The tilemap can be 32x32, 64x32, 32x64, or 64x64. Rather than expanding the width
and height of the tilemap, the game instead stores duplicate tilemaps immediately
following the previous ones. For example, if you were in 64x64 mode, there would
be four tilemaps. Each tilemap would be 2048 bytes in size
(32 tiles * 32 tiles * 2 bytes/tile), the first tilemap would make the top left
corner, the second the top right, the third the bottom left, and the fourth, the
bottom right. Because x / y are divided by the tile size, the tile size setting
(8x8 or 16x16) does not affect the result.
*2 - pos = ppu.bg_tilemap_loc[bg] + map_index + ((y1 / tile_size) & 31) * 64 + ( ((x / tile_size) & 31) * 2);
Format: tilemap start location +
map index (either map 0 or map 1; see *1) +
((y tile #) mapped to tilemap boundary) * # of bytes per tilemap line +
(((x tile #) mapped to tilemap boundary) * 2 (# of bytes per tilemap entry));
*/
void ppu_render_line_bg(byte layer_pos_pri0, byte layer_pos_pri1, byte color_depth, byte bg) {
int x, y, z, x1, y1;
int mirror_x, mirror_y, p;
int screen_x, screen_y;
int bg_x, bg_y;
int xpos, ypos, mosaic_x, mosaic_y;
word t, base_xpos, base_pos, pos, ppos = 0;
word col;
byte *src, *bg_tiledata, *bg_tiledata_state, *tile_ptr;
byte tiledata_size;
byte tile_size, tile_width, tile_height, tile_x;
byte mask, pal_index, pal_size;
word tile_num, screen_width, screen_height, screen_width_mask, screen_height_mask, map_index;
word *mosaic_table;
byte layer_pos;
word opt_valid_bit, voffset, hoffset, vscroll, hscroll;
if(ppu.bg_enabled[bg] == false && ppu.ss_bg_enabled[bg] == false)return;
if (bg == BG1)opt_valid_bit = 0x2000;
else if(bg == BG2)opt_valid_bit = 0x4000;
else opt_valid_bit = 0x0000;
switch(color_depth) {
case COLORDEPTH_4:
pal_size = 4;
tiledata_size = SH_16;
break;
case COLORDEPTH_16:
pal_size = 16;
tiledata_size = SH_32;
break;
case COLORDEPTH_256:
pal_size = 256;
tiledata_size = SH_64;
break;
}
bg_tiledata = (byte*)ppu_bg_tiledata[color_depth];
bg_tiledata_state = (byte*)ppu_bg_tiledata_state[color_depth];
screen_width = render.snes_width;
screen_height = render.snes_width; //this is correct -- ppu tilemap is based around 256x256, etc.
tile_size = (ppu.bg_tile_size[bg])?SH_16:SH_8;
tile_width = tile_size;
tile_height = tile_size;
if(ppu.interlace == true && (ppu.bg_mode == 5 || ppu.bg_mode == 6)) {
screen_y = (ppu.vline_pos << SH_2) + ppu.interlace_frame;
} else {
screen_y = ppu.vline_pos;
}
//Modes 5 and 6 seem to force 16-width tiles due to having twice the resolution.
//The tile size attribute in $2105 has no effect on tile width.
if(ppu.bg_mode == 5 || ppu.bg_mode == 6) {
tile_width = SH_16;
}
if(tile_size == SH_16) {
screen_width <<= SH_2;
screen_height <<= SH_2;
}
if(ppu.bg_tilemap_size[bg] & 0x01)screen_width <<= SH_2;
if(ppu.bg_tilemap_size[bg] & 0x02)screen_height <<= SH_2;
screen_width_mask = screen_width - 1;
screen_height_mask = screen_height - 1;
if(render.snes_width == 512) {
hscroll = (ppu.bg_hscroll_pos[bg] << SH_2) & screen_width_mask;
} else {
hscroll = ppu.bg_hscroll_pos[bg] & screen_width_mask;
}
bg_x = hscroll;
if(render.snes_height == 448) {
vscroll = (ppu.bg_vscroll_pos[bg] << SH_2) & screen_height_mask;
} else {
vscroll = ppu.bg_vscroll_pos[bg] & screen_height_mask;
}
bg_y = (screen_y + vscroll) & screen_height_mask;
if(ppu.mosaic_enabled[bg] == true) {
mosaic_table = (word*)ppu.mosaic_table[ppu.mosaic_size];
} else {
mosaic_table = (word*)ppu.mosaic_table[0];
}
mosaic_x = mosaic_table[bg_x];
mosaic_y = mosaic_table[bg_y];
for(screen_x=0;screen_x<render.snes_width;screen_x++) {
if(ppu.bg_mode == 2 || ppu.bg_mode == 4 || ppu.bg_mode == 6) {
if(ppu.bg_mode == 6) {
tile_x = (mosaic_table[screen_x + (hscroll & 15)] >> SH_16);
} else {
tile_x = (mosaic_table[screen_x + (hscroll & 7)] >> SH_8);
}
hoffset = hscroll;
voffset = vscroll;
if(tile_x != 0) {
tile_x = (tile_x - 1) & 31;
if(ppu.bg_mode == 4) {
pos = ppu.bg_tilemap_loc[BG3] + (tile_x << SH_2);
t = *((word*)ppu.vram + (pos >> SH_2));
if(t & opt_valid_bit) {
if(!(t & 0x8000)) {
hoffset = ((t & 0x1ff8) | (hscroll & 7)) & screen_width_mask;
} else {
voffset = (t & 0x1fff) & screen_height_mask;
}
}
} else {
pos = ppu.bg_tilemap_loc[BG3] + (tile_x << SH_2);
t = *((word*)ppu.vram + (pos >> SH_2));
if(t & opt_valid_bit) {
hoffset = ((t & 0x1ff8) | (hscroll & 7)) & screen_width_mask;
}
pos = ppu.bg_tilemap_loc[BG3] + 64 + (tile_x << SH_2);
t = *((word*)ppu.vram + (pos >> SH_2));
if(t & opt_valid_bit) {
voffset = (t & 0x1fff) & screen_height_mask;
}
}
}
mosaic_x = mosaic_table[(screen_x + hoffset) & screen_width_mask ];
mosaic_y = mosaic_table[(screen_y + voffset) & screen_height_mask];
}
switch(ppu.bg_tilemap_size[bg]) {
case 0:
map_index = 0;
break;
case 1:
map_index = ((mosaic_x >> tile_size) >> SH_32) << SH_2048;
break;
case 2:
map_index = ((mosaic_y >> tile_size) >> SH_32) << SH_2048;
break;
case 3:
map_index = ((mosaic_x >> tile_size) >> SH_32) << SH_2048 |
((mosaic_y >> tile_size) >> SH_32) << SH_4096;
break;
}
base_xpos = ((mosaic_x >> SH_8) & 31);
base_pos = (((mosaic_y >> tile_height) & 31) << SH_32) + ((mosaic_x >> tile_width) & 31);
pos = ppu.bg_tilemap_loc[bg] + map_index + (base_pos << SH_2);
t = *((word*)ppu.vram + (pos >> SH_2));
mirror_y = (t & 0x8000)?1:0;
mirror_x = (t & 0x4000)?1:0;
if((t & 0x2000) == 0) {
layer_pos = layer_pos_pri0;
} else {
layer_pos = layer_pos_pri1;
}
tile_num = t & 0x03ff;
if(tile_width == SH_16) {
if(((mosaic_x & 15) >= 8 && !mirror_x) ||
((mosaic_x & 15) < 8 && mirror_x))tile_num++;
tile_num &= 0x03ff;
}
if(tile_height == SH_16) {
if(((mosaic_y & 15) >= 8 && !mirror_y) ||
((mosaic_y & 15) < 8 && mirror_y))tile_num += 16;
tile_num &= 0x03ff;
}
tile_num += (ppu.bg_tiledata_loc[bg] >> tiledata_size);
if(bg_tiledata_state[tile_num] == 1) {
ppu_render_bg_tile(color_depth, bg, tile_num);
}
pal_index = ((t >> 10) & 7) * pal_size;
if(mirror_y) { ypos = (7 - (mosaic_y & 7)); }
else { ypos = ( (mosaic_y & 7)); }
//loop while we are rendering from the same tile, as there's no need to do all of the above work
//unless we have rendered all of the visible tile, taking mosaic into account.
tile_ptr = (byte*)bg_tiledata + (tile_num << SH_64) + (ypos << SH_8);
while(1) {
if(mirror_x) { xpos = (7 - (mosaic_x & 7)); }
else { xpos = ( (mosaic_x & 7)); }
col = *(tile_ptr + xpos);
if(col) {
ppu_set_layer_pixel(screen_x, col + pal_index);
}
bg_x++;
bg_x &= screen_width_mask;
mosaic_x = mosaic_table[bg_x];
if(base_xpos != ((mosaic_x >> SH_8) & 31))break;
screen_x++;
if(screen_x >= render.snes_width)break;
}
}
}
#include "ppu_render_mode7.cpp"
+121
View File
@@ -0,0 +1,121 @@
/*
The algorithm in this file was derived from the snes9x source code.
The snes9x source code is not public domain. If you wish to use this
code, you must abide by the terms of the snes9x license. If you do not
wish to abide by the snes9x licensing terms, please define the precompiler
variable PUBLIC_DOMAIN so that ppu_render_mode7f.cpp is used instead of
this file. You must also remove this file from any work that you release
that does not follow the snes9x license.
See license.txt for more info on the license of this software and snes9x.
*/
#define CLIP_10BIT_SIGNED(x) \
((x) & ((1 << 10) - 1)) + (((((x) & (1 << 13)) ^ (1 << 13)) - (1 << 13)) >> 3)
#define CAST_WORDTOINT(x) \
(int)(((x & 0x8000)?(x | 0xffff0000):(x & 0x00007fff)))
void ppu_render_line_m7(byte layer_pos_bg1, byte layer_pos_bg2_pri0, byte layer_pos_bg2_pri1) {
int x;
int step_m7a, step_m7c, m7a, m7b, m7c, m7d;
int hoffset, voffset;
int centerx, centery;
int xx, yy;
int px, py;
int tx, ty, tile, palette, priority;
byte layer_pos;
hoffset = (CAST_WORDTOINT(ppu.m7hofs) << 7) >> 7;
voffset = (CAST_WORDTOINT(ppu.m7vofs) << 7) >> 7;
centerx = (CAST_WORDTOINT(ppu.m7x) << 7) >> 7;
centery = (CAST_WORDTOINT(ppu.m7y) << 7) >> 7;
if(ppu.mode7_vflip == true) {
yy = 223 - ppu.vline_pos;
} else {
yy = ppu.vline_pos;
}
yy += CLIP_10BIT_SIGNED(voffset - centery);
m7b = CAST_WORDTOINT(ppu.m7b) * yy + (centerx << 8);
m7d = CAST_WORDTOINT(ppu.m7d) * yy + (centery << 8);
step_m7a = CAST_WORDTOINT(ppu.m7a);
step_m7c = CAST_WORDTOINT(ppu.m7c);
xx = CLIP_10BIT_SIGNED(hoffset - centerx);
m7a = CAST_WORDTOINT(ppu.m7a) * xx;
m7c = CAST_WORDTOINT(ppu.m7c) * xx;
for(x=0;x<256;x++) {
px = ((m7a + m7b) >> 8);
py = ((m7c + m7d) >> 8);
switch(ppu.mode7_repeat) {
case 0: //screen repitition outside of screen area
case 1: //same as case 0
px &= 1023;
py &= 1023;
tx = ((px >> SH_8) & 127);
ty = ((py >> SH_8) & 127);
tile = ppu.vram[(ty * 128 + tx) << 1];
palette = ppu.vram[(((tile << SH_64) + ((py & 7) << SH_8) + (px & 7)) << 1) + 1];
break;
case 2: //character 0 repetition outside of screen area
if(px < 0 || px > 1023 || py < 0 || py > 1023) {
tx = 0;
ty = 0;
} else {
px &= 1023;
py &= 1023;
tx = ((px >> SH_8) & 127);
ty = ((py >> SH_8) & 127);
}
tile = ppu.vram[(ty * 128 + tx) << 1];
palette = ppu.vram[(((tile << SH_64) + ((py & 7) << SH_8) + (px & 7)) << 1) + 1];
break;
case 3: //palette color 0 outside of screen area
if(px < 0 || px > 1023 || py < 0 || py > 1023) {
palette = 0;
} else {
px &= 1023;
py &= 1023;
tx = ((px >> SH_8) & 127);
ty = ((py >> SH_8) & 127);
tile = ppu.vram[(ty * 128 + tx) << 1];
palette = ppu.vram[(((tile << SH_64) + ((py & 7) << SH_8) + (px & 7)) << 1) + 1];
}
break;
}
if(ppu.mode7_extbg == false) {
if(palette) {
layer_pos = layer_pos_bg1;
if(ppu.mode7_hflip == true) {
ppu_set_layer_pixel(255 - x, palette);
} else {
ppu_set_layer_pixel(x, palette);
}
}
} else {
priority = (palette >> 7);
palette &= 0x7f;
if(palette) {
if(priority == 0) {
layer_pos = layer_pos_bg2_pri0;
} else {
layer_pos = layer_pos_bg2_pri1;
}
if(ppu.mode7_hflip == true) {
ppu_set_layer_pixel(255 - x, palette);
} else {
ppu_set_layer_pixel(x, palette);
}
}
}
m7a += step_m7a;
m7c += step_m7c;
}
}
+101
View File
@@ -0,0 +1,101 @@
/*
$2100 : screen brightness / enable
d---bbbb
d: display (0=on, 1=off)
b: brightness (0-15)
*/
extern emustate emu_state;
void mmio_w2100(byte value) {
ppu.display_disable = (value & 0x80)?true:false;
ppu.display_brightness = (value & 0x0f);
}
/*
$2105 : screen mode register
dcbapmmm
d: bg4 tile size (0=8x8, 1=16x16)
c: bg3 tile size (0=8x8, 1=16x16)
b: bg2 tile size (0=8x8, 1=16x16)
a: bg1 tile size (0=8x8, 1=16x16)
p: bg priority mode
m: screen mode
*/
void mmio_w2105(byte value) {
static byte prev_mode = 0x00;
ppu.bg_tile_size[BG4] = (value & 0x80)?1:0;
ppu.bg_tile_size[BG3] = (value & 0x40)?1:0;
ppu.bg_tile_size[BG2] = (value & 0x20)?1:0;
ppu.bg_tile_size[BG1] = (value & 0x10)?1:0;
ppu.bg_priority_mode = (value & 0x08)?1:0;
ppu.bg_mode = (value & 0x07);
if(prev_mode != ppu.bg_mode) {
video_setsnesmode();
prev_mode = ppu.bg_mode;
}
}
/*
$2106 : mosaic
ssssdcba
s: size (0=smallest, 15=largest)
d: affect bg4
c: affect bg3
b: affect bg2
a: affect bg1
*/
void mmio_w2106(byte value) {
ppu.mosaic_size = (value >> 4) & 15;
ppu.mosaic_enabled[BG4] = (value & 0x08)?true:false;
ppu.mosaic_enabled[BG3] = (value & 0x04)?true:false;
ppu.mosaic_enabled[BG2] = (value & 0x02)?true:false;
ppu.mosaic_enabled[BG1] = (value & 0x01)?true:false;
}
/*
$212c : main screen desgination
$212d : sub screen designation
---sdcba
s: oam enable
d: bg4 enable
c: bg3 enable
b: bg2 enable
a: bg1 enable
*/
void mmio_w212c(byte value) {
ppu.bg_enabled[OAM] = (value & 0x10)?true:false;
ppu.bg_enabled[BG4] = (value & 0x08)?true:false;
ppu.bg_enabled[BG3] = (value & 0x04)?true:false;
ppu.bg_enabled[BG2] = (value & 0x02)?true:false;
ppu.bg_enabled[BG1] = (value & 0x01)?true:false;
}
void mmio_w212d(byte value) {
ppu.ss_bg_enabled[OAM] = (value & 0x10)?true:false;
ppu.ss_bg_enabled[BG4] = (value & 0x08)?true:false;
ppu.ss_bg_enabled[BG3] = (value & 0x04)?true:false;
ppu.ss_bg_enabled[BG2] = (value & 0x02)?true:false;
ppu.ss_bg_enabled[BG1] = (value & 0x01)?true:false;
}
/*
$2133 : screen mode settings
?m???ohi
m: mode7 extbg (0 = off, 1 = on)
o: overscan (0 = off, 1 = on)
h: sprite halve (0 = off, 1 = on)
i: interlace (0 = off, 1 = on)
*/
void mmio_w2133(byte value) {
ppu.mode7_extbg = (value & 0x40)?true:false;
ppu.overscan = (value & 0x04)?true:false;
ppu.visible_scanlines = (value & 0x04)?239:224;
ppu.sprite_halve = (value & 0x02)?true:false;
ppu.toggle_interlace = (value & 0x01)?true:false;
video_setsnesmode();
}
+44
View File
@@ -0,0 +1,44 @@
/*
$210d-$2114 : Scroll registers
210d/210e: bg1 hscroll/bg1 vscroll
210f/2110: bg2 hscroll/bg2 vscroll
2111/2112: bg3 hscroll/bg3 vscroll
2113/2114: bg4 hscroll/bg4 vscroll
you must write to this register twice to write the full address.
starting positions are 0, 0. only 11 bits of the address are used.
*/
void mmio_w210d(byte value) {
ppu.bg_hscroll_pos[BG1] = (value << 8) | (ppu.bg_hscroll_pos[BG1] >> 8);
ppu.m7hofs = (value << 8) | (ppu.m7hofs >> 8);
}
void mmio_w210e(byte value) {
ppu.bg_vscroll_pos[BG1] = (value << 8) | (ppu.bg_vscroll_pos[BG1] >> 8);
ppu.m7vofs = (value << 8) | (ppu.m7vofs >> 8);
}
void mmio_w210f(byte value) {
ppu.bg_hscroll_pos[BG2] = (value << 8) | (ppu.bg_hscroll_pos[BG2] >> 8);
}
void mmio_w2110(byte value) {
ppu.bg_vscroll_pos[BG2] = (value << 8) | (ppu.bg_vscroll_pos[BG2] >> 8);
}
void mmio_w2111(byte value) {
ppu.bg_hscroll_pos[BG3] = (value << 8) | (ppu.bg_hscroll_pos[BG3] >> 8);
}
void mmio_w2112(byte value) {
ppu.bg_vscroll_pos[BG3] = (value << 8) | (ppu.bg_vscroll_pos[BG3] >> 8);
}
void mmio_w2113(byte value) {
ppu.bg_hscroll_pos[BG4] = (value << 8) | (ppu.bg_hscroll_pos[BG4] >> 8);
}
void mmio_w2114(byte value) {
ppu.bg_vscroll_pos[BG4] = (value << 8) | (ppu.bg_vscroll_pos[BG4] >> 8);
}
+34
View File
@@ -0,0 +1,34 @@
byte mmio_rspc(byte port) {
#ifndef NO_SPC700
return cpu_apu_bridge->cpu_read(port);
#else
static byte t = 0, counter = 0;
byte x;
if(rand() & 1) {
x = rand() & 7;
if(x == 0) {
if(!(port & 1))t = gx816->regs.a.w;
else t = gx816->regs.a.w >> 8;
}
else if(x == 1) {
if(!(port & 1))t = gx816->regs.x;
else t = gx816->regs.x >> 8;
}
else if(x == 2) {
if(!(port & 1))t = gx816->regs.y;
else t = gx816->regs.y >> 8;
}
else if(x == 3)t = 0xaa;
else if(x == 4)t = 0xbb;
else if(x == 5)t = 0xcc;
else { t = counter++; }
}
return t;
#endif
}
void mmio_wspc(byte port, byte value) {
#ifndef NO_SPC700
cpu_apu_bridge->cpu_write(port, value);
#endif
}
+238
View File
@@ -0,0 +1,238 @@
/*
$2137 : counter latch
reading from this register will latch the x/y
counter positions, but only if bit 7 of $4201
is set. the default state of this register is
$ff on snes power on/reset.
*/
byte mmio_r2137(void) {
if(ppu.io4201 & 0x80) {
snes_time->set_scan_pos(snes_time->master_cycles, false);
ppu.latch_toggle = 0;
ppu.latch_vpos = snes_time->vscan_pos;
ppu.latch_hpos = snes_time->hscan_pos;
ppu.counter_latched = true;
}
return 0x00;
}
byte mmio_r213c(void) {
word r;
r = ppu.latch_hpos;
if(ppu.latch_toggle)r >>= 8;
ppu.latch_toggle ^= 1;
return r;
}
byte mmio_r213d(void) {
word r;
r = ppu.latch_vpos;
if(ppu.latch_toggle)r >>= 8;
ppu.latch_toggle ^= 1;
return r;
}
/*
$213e : ppu1 status register
trm-vvvv
t: time over (?)
r: range over (?)
m: master/slave mode select (?)
-: open bus (?)
v: PPU1 (5c77) version number [1]
*/
byte mmio_r213e(void) {
byte r = 0x00;
r |= 0x01; //ppu1 version #
return r;
}
/*
$213f : ppu2 status register
ilcmvvvv
i: interlace frame (0=even, 1=odd)
l: counter latched
c: open bus complement
m: ntsc/pal mode (0=ntsc, 1=pal)
v: PPU2 (5c78) version number [3]
notes:
bit 6 (l): counter is latched by reading $2137,
or a 1->0 transition of $4201 bit 7.
bit 5 (c): this is not implemented correctly. basically,
my copier (super ufo 8.3j) breaks the snes open bus.
as a result, 0x00 is always returned instead of the
open bus values. since this is the complement of that
value, 1 is always returned. I am emulating what my
copier returns until I can get a copier that supports
open bus correctly.
*/
byte mmio_r213f(void) {
byte r = 0x00;
r |= ppu.interlace_frame << 7;
if(!(ppu.io4201 & 0x80)) {
r |= 1 << 6;
} else if(ppu.counter_latched == true) {
r |= 1 << 6;
ppu.counter_latched = false;
}
r |= 1 << 5;
r |= 0x03; //ppu2 version #
return r;
}
/*
$4200 : counter enable
n-vh---j
n: nmi enable
v: vertical counter enable
h: horizontal counter enable
j: automatic joypad enable
the v/h counters must be enabled to invoke IRQs. the vertical
counter will override the horizontal counter. in other words,
if both v+h are set, only vertical IRQs will be performed.
*/
void mmio_w4200(byte value) {
gx816->nmi_enabled = (value & 0x80)?true:false;
ppu.vcounter_enabled = (value & 0x20)?true:false;
ppu.hcounter_enabled = (value & 0x10)?true:false;
ppu.auto_joypad_read = (value & 0x01)?true:false;
}
/*
$4201 : programmable i/o port
l???????
l: counter latch
upon power on/reset, this value is set to 0xff.
clearing bit 7 will result in the x/y dot position
being set in $213c/$213d. the counters cannot be
latched again by writing a 0 to bit 7 until a 1 is
written to this bit first. reading $2137 while bit 7
is cleared will not latch the counters.
examples (+ = counter latched, - = counter not latched):
$00->$4201+
$80->$4201-
$00->$4201+ $00->$4201- $80->$4201- $00->$4201+
$2137->a+ $00->$4201+ $2137->a-
*/
void mmio_w4201(byte value) {
if((ppu.io4201 & 0x80) && !(value & 0x80)) {
snes_time->set_scan_pos(snes_time->master_cycles + 4, false);
ppu.latch_toggle = 0;
ppu.latch_vpos = snes_time->vscan_pos;
ppu.latch_hpos = snes_time->hscan_pos;
ppu.counter_latched = true;
}
ppu.io4201 = value;
}
/*
$4207/$4208 : horizontal counter position
9-bit value, used to invoke horizontal IRQs
horizontal range: 0-339
*/
void mmio_w4207(byte value) {
ppu.hirq_pos = (ppu.hirq_pos & 0x0100) | value;
}
void mmio_w4208(byte value) {
ppu.hirq_pos = (ppu.hirq_pos & 0x00ff) | (value & 1) << 8;
}
/*
$4209/$420a : vertical counter position
9-bit value, used to invoke vertical IRQs
vertical range: 0-261
*/
void mmio_w4209(byte value) {
ppu.virq_pos = (ppu.virq_pos & 0x0100) | value;
}
void mmio_w420a(byte value) {
ppu.virq_pos = (ppu.virq_pos & 0x00ff) | (value & 1) << 8;
}
/*
$420d : memory speed
0000000x
x: 0 = SlowROM
1 = FastROM
*/
void mmio_w420d(byte value) {
gx816->memory_speed = (value) & 0x01;
snes_time->set_speed_map(gx816->memory_speed);
}
/*
$4210 : nmi status
n---vvvv
n: nmi occurred (0=no, 1=yes)
-: open bus (?)
v: CPU (5a22) version number [2]
value is set/cleared regardless of whether or not
NMIs are enabled in $4200 bit 7.
*/
byte mmio_r4210(void) {
byte r = 0x00;
r |= (gx816->nmi_pin ^ 1)?0x80:0x00;
r |= 0x02; //cpu version #
gx816->nmi_pin = 1;
return r;
}
/*
$4211 : irq toggle
i?------
i: irq state (1=in irq, 0=not in irq)?
?: unknown, always return 1?
*/
byte mmio_r4211(void) {
byte r = 0x00;
r |= 0x40;
if(ppu.irq_triggered == true)r |= 0x80;
ppu.irq_triggered = false;
return r;
}
/*
$4212 : video status
vh-----j
v: vblank (0=no, 1=yes)
h: hblank (0=no, 1=yes)
j: joypad ready (for auto joypad mode)
*/
byte mmio_r4212(void) {
byte r;
r = 0x00;
//set when the SNES is updating the joypad data automatically
if(snes_time->vscan_pos >= (ppu.visible_scanlines + 1) && snes_time->vscan_pos <= (ppu.visible_scanlines + 3))r |= 0x01;
//set when the SNES is in hblank/vblank
if(snes_time->hcycle_pos <= 4 || snes_time->hcycle_pos >= 1098)r |= 0x40;
if(snes_time->vscan_pos == 0 || snes_time->vscan_pos >= (ppu.visible_scanlines + 1)) {
if(snes_time->vscan_pos == 0) {
if(snes_time->hcycle_pos < 2)r |= 0x80;
} else if(snes_time->vscan_pos == (ppu.visible_scanlines + 1)) {
if(snes_time->hcycle_pos >= 2)r |= 0x80;
} else {
r |= 0x80;
}
}
return r;
}
+166
View File
@@ -0,0 +1,166 @@
/*
$2107-$210a : bg1-4 tilemap location
bbbbbbss
b: location of bg tilemap - highest bit is ignored
s: tilemap size (00 = 32x32, 01 = 64x32, 10 = 32x64, 11 = 64x64)
*/
void mmio_w2107(byte value) {
ppu.bg_tilemap_loc[BG1] = (value & 0x7c) << 9;
ppu.bg_tilemap_size[BG1] = value & 3;
}
void mmio_w2108(byte value) {
ppu.bg_tilemap_loc[BG2] = (value & 0x7c) << 9;
ppu.bg_tilemap_size[BG2] = value & 3;
}
void mmio_w2109(byte value) {
ppu.bg_tilemap_loc[BG3] = (value & 0x7c) << 9;
ppu.bg_tilemap_size[BG3] = value & 3;
}
void mmio_w210a(byte value) {
ppu.bg_tilemap_loc[BG4] = (value & 0x7c) << 9;
ppu.bg_tilemap_size[BG4] = value & 3;
}
/*
$210b/$210c: bg1-4 tiledata location
bbbbaaaa
a: bg1/3 tiledata location (210b/210c)
b: bg2/4 tiledata location (210b/210c)
*/
void mmio_w210b(byte value) {
ppu.bg_tiledata_loc[BG1] = (value & 0x07) << 13;
ppu.bg_tiledata_loc[BG2] = (value & 0x70) << 9;
}
void mmio_w210c(byte value) {
ppu.bg_tiledata_loc[BG3] = (value & 0x07) << 13;
ppu.bg_tiledata_loc[BG4] = (value & 0x70) << 9;
}
/*
$2115 : vram write counter
i---mmrr
i: 0 = increment on $2118/$2139
1 = increment on $2119/$213a
m: address remapping
00 = no remapping
01 = aaaaaaaaBBBccccc -> aaaaaaaacccccBBB
10 = aaaaaaaBBBcccccc -> aaaaaaaccccccBBB
11 = aaaaaaBBBccccccc -> aaaaaacccccccBBB
r: increment rate
00 = increment by 1
01 = increment by 32
10 = increment by 128
11 = increment by 128
*/
void mmio_w2115(byte value) {
ppu.vram_inc_reg = (value & 0x80)?1:0;
ppu.vram_remap_mode = (value >> 2) & 3;
switch(value & 3) {
case 0x00:ppu.vram_inc_size = 1;break;
case 0x01:ppu.vram_inc_size = 32;break;
case 0x02:ppu.vram_inc_size = 128;break;
case 0x03:ppu.vram_inc_size = 128;break;
}
}
/*
$2116/$2117 : vram write position
15-bit value ($2116/$2117) determining position in vram to write to using $2118
this value is doubled to get true write position (0000-ffff)
*/
void mmio_w2116(byte value) {
ppu.vram_write_pos = ((ppu.vram_write_pos & 0xff00) | value);
}
void mmio_w2117(byte value) {
ppu.vram_write_pos = ((value << 8) | (ppu.vram_write_pos & 0xff));
}
word mmio_vram_remap(void) {
word addr, t;
addr = (ppu.vram_write_pos << 1);
switch(ppu.vram_remap_mode) {
case 0:
break;
case 1:
t = (addr >> 5) & 7;
addr = (addr & 0xff00) | ((addr & 0x001f) << 3) | t;
break;
case 2:
t = (addr >> 6) & 7;
addr = (addr & 0xfe00) | ((addr & 0x003f) << 3) | t;
break;
case 3:
t = (addr >> 7) & 7;
addr = (addr & 0xfc00) | ((addr & 0x007f) << 3) | t;
}
return addr;
}
/*
$2118/$2119 : vram write
$2118/$2119 write to vram using vram_write_pos, this is then incremented based on
the settings of $2115 (vram_inc_size / vram_inc_reg)
*/
void mmio_w2118(byte value) {
word w;
w = mmio_vram_remap();
ppu.vram[w] = value;
if(ppu.vram_inc_reg == 0) {
ppu.vram_write_pos += ppu.vram_inc_size;
}
ppu_bg_tiledata_state[TILE_2BIT][(w >> 4)] = 1;
ppu_bg_tiledata_state[TILE_4BIT][(w >> 5)] = 1;
ppu_bg_tiledata_state[TILE_8BIT][(w >> 6)] = 1;
debug_test_bp(BPSRC_VRAM, BP_WRITE, w, value);
}
void mmio_w2119(byte value) {
word w;
w = mmio_vram_remap() + 1;
ppu.vram[w] = value;
if(ppu.vram_inc_reg == 1) {
ppu.vram_write_pos += ppu.vram_inc_size;
}
ppu_bg_tiledata_state[TILE_2BIT][(w >> 4)] = 1;
ppu_bg_tiledata_state[TILE_4BIT][(w >> 5)] = 1;
ppu_bg_tiledata_state[TILE_8BIT][(w >> 6)] = 1;
debug_test_bp(BPSRC_VRAM, BP_WRITE, w, value);
}
/*
$2139/$213a : vram read
*/
byte mmio_r2139(void) {
byte r;
word w;
w = mmio_vram_remap();
r = ppu.vram_read_buffer;
if(ppu.vram_inc_reg == 0) {
ppu.vram_read_buffer = *((word*)ppu.vram + (w >> 1));
ppu.vram_write_pos += ppu.vram_inc_size;
}
debug_test_bp(BPSRC_VRAM, BP_READ, w, r);
return r;
}
byte mmio_r213a(void) {
byte r;
word w;
w = mmio_vram_remap() + 1;
r = ppu.vram_read_buffer >> 8;
if(ppu.vram_inc_reg == 1) {
ppu.vram_read_buffer = *((word*)ppu.vram + (w >> 1));
ppu.vram_write_pos += ppu.vram_inc_size;
}
debug_test_bp(BPSRC_VRAM, BP_READ, w, r);
return r;
}
+121
View File
@@ -0,0 +1,121 @@
/*
$2123/$2124/$2125 : window mask settings
$2123:
hgfedcba
(bg2)
h: enable window 2
g: clip window 2 (0=in, 1=out)
f: enable window 1
e: clip window 1 (0=in, 1=out)
(bg1)
h: enable window 2
g: clip window 2 (0=in, 1=out)
f: enable window 1
e: clip window 1 (0=in, 1=out)
$2124: same as $2123, but with bg4/3
$2125:
hgfedcba
h: enable color window 2
g: clip window 2 (0=in, 1=out)
f: enable color window 1
e: clip window 1 (0=in, 1=out)
d: enable OAM window 2
c: clip window 2 (0=in, 1=out)
b: enable OAM window 1
a: clip window 1 (0=in, 1=out)
*/
void mmio_w2123(byte value) {
ppu.bg_window2_enabled [BG2] = (value & 0x80)?true:false;
ppu.bg_window2_clipmode[BG2] = (value & 0x40)?CLIPMODE_OUT:CLIPMODE_IN;
ppu.bg_window1_enabled [BG2] = (value & 0x20)?true:false;
ppu.bg_window1_clipmode[BG2] = (value & 0x10)?CLIPMODE_OUT:CLIPMODE_IN;
ppu.bg_window2_enabled [BG1] = (value & 0x08)?true:false;
ppu.bg_window2_clipmode[BG1] = (value & 0x04)?CLIPMODE_OUT:CLIPMODE_IN;
ppu.bg_window1_enabled [BG1] = (value & 0x02)?true:false;
ppu.bg_window1_clipmode[BG1] = (value & 0x01)?CLIPMODE_OUT:CLIPMODE_IN;
}
void mmio_w2124(byte value) {
ppu.bg_window2_enabled [BG4] = (value & 0x80)?true:false;
ppu.bg_window2_clipmode[BG4] = (value & 0x40)?CLIPMODE_OUT:CLIPMODE_IN;
ppu.bg_window1_enabled [BG4] = (value & 0x20)?true:false;
ppu.bg_window1_clipmode[BG4] = (value & 0x10)?CLIPMODE_OUT:CLIPMODE_IN;
ppu.bg_window2_enabled [BG3] = (value & 0x08)?true:false;
ppu.bg_window2_clipmode[BG3] = (value & 0x04)?CLIPMODE_OUT:CLIPMODE_IN;
ppu.bg_window1_enabled [BG3] = (value & 0x02)?true:false;
ppu.bg_window1_clipmode[BG3] = (value & 0x01)?CLIPMODE_OUT:CLIPMODE_IN;
}
void mmio_w2125(byte value) {
ppu.color_window2_enabled = (value & 0x80)?true:false;
ppu.color_window2_clipmode = (value & 0x40)?CLIPMODE_OUT:CLIPMODE_IN;
ppu.color_window1_enabled = (value & 0x20)?true:false;
ppu.color_window1_clipmode = (value & 0x10)?CLIPMODE_OUT:CLIPMODE_IN;
ppu.bg_window2_enabled [OAM] = (value & 0x08)?true:false;
ppu.bg_window2_clipmode[OAM] = (value & 0x04)?CLIPMODE_OUT:CLIPMODE_IN;
ppu.bg_window1_enabled [OAM] = (value & 0x02)?true:false;
ppu.bg_window1_clipmode[OAM] = (value & 0x01)?CLIPMODE_OUT:CLIPMODE_IN;
}
/*
$2126-$2129 : window position settings
$2126: window 1 left
$2127: window 1 right
$2128: window 2 left
$2129: window 2 right
*/
void mmio_w2126(byte value) { ppu.window1_left = value; }
void mmio_w2127(byte value) { ppu.window1_right = value; }
void mmio_w2128(byte value) { ppu.window2_left = value; }
void mmio_w2129(byte value) { ppu.window2_right = value; }
/*
$212a/$212b : window mask settings
$212a: ddccbbaa (d=bg4, c=bg3, b=bg2, a=bg1)
$212b: ----ccss (c=color add/sub, s=oam)
00=or
01=and
10=xor
11=xnor
*/
void mmio_w212a(byte value) {
ppu.bg_window_mask[BG4] = (value >> 6) & 3;
ppu.bg_window_mask[BG3] = (value >> 4) & 3;
ppu.bg_window_mask[BG2] = (value >> 2) & 3;
ppu.bg_window_mask[BG1] = (value ) & 3;
}
void mmio_w212b(byte value) {
ppu.color_window_mask = (value >> 2) & 3;
ppu.bg_window_mask[OAM] = (value ) & 3;
}
/*
$212e/$212f : main window designation
---odcba
o: OAM enable
d: BG4 enable
c: BG3 enable
b: BG2 enable
a: BG1 enable
*/
void mmio_w212e(byte value) {
ppu.bg_windowing_enabled[OAM] = (value & 0x10)?true:false;
ppu.bg_windowing_enabled[BG4] = (value & 0x08)?true:false;
ppu.bg_windowing_enabled[BG3] = (value & 0x04)?true:false;
ppu.bg_windowing_enabled[BG2] = (value & 0x02)?true:false;
ppu.bg_windowing_enabled[BG1] = (value & 0x01)?true:false;
}
void mmio_w212f(byte value) {
ppu.ss_bg_windowing_enabled[OAM] = (value & 0x10)?true:false;
ppu.ss_bg_windowing_enabled[BG4] = (value & 0x08)?true:false;
ppu.ss_bg_windowing_enabled[BG3] = (value & 0x04)?true:false;
ppu.ss_bg_windowing_enabled[BG2] = (value & 0x02)?true:false;
ppu.ss_bg_windowing_enabled[BG1] = (value & 0x01)?true:false;
}
+32
View File
@@ -0,0 +1,32 @@
/*
$2180 : wram read/write
write byte to wram write pointer ($2181-$2183), then increment pointer.
always stays within 7e0000-7fffff, high 7 bits of 24-bit offset ignored.
*/
byte mmio_r2180(void) {
byte r;
r = gx816->mem_read(MEMMODE_NONE, MEMSIZE_BYTE, 0x7e0000 | ppu.wram_write_pos);
ppu.wram_write_pos++;
ppu.wram_write_pos &= 0x01ffff;
return r;
}
void mmio_w2180(byte value) {
gx816->mem_write(MEMMODE_NONE, MEMSIZE_BYTE, 0x7e0000 | ppu.wram_write_pos, value);
ppu.wram_write_pos++;
ppu.wram_write_pos &= 0x01ffff;
}
/*
$2181-$2183: wram write pointer set
*/
void mmio_w2181(byte value) {
ppu.wram_write_pos = ((ppu.wram_write_pos & 0xffff00) | value) & 0x01ffff;
}
void mmio_w2182(byte value) {
ppu.wram_write_pos = ((ppu.wram_write_pos & 0xff00ff) | (value << 8)) & 0x01ffff;
}
void mmio_w2183(byte value) {
ppu.wram_write_pos = ((ppu.wram_write_pos & 0x00ffff) | (value << 16)) & 0x01ffff;
}
+3
View File
@@ -0,0 +1,3 @@
del c:\root\bsnes_testrom\bsnes.exe
copy bsnes.exe c:\root\bsnes_testrom\bsnes.exe
@pause
+370
View File
@@ -0,0 +1,370 @@
#include "../base.h"
#include "../cpu/g65816.h"
#include "timing.h"
extern g65816 *gx816;
extern ppustate ppu;
extern debugstate debugger;
snes_timer *snes_time;
/*
apu_cycles is incremented to keep in sync with master_cycles.
(n << 5) is only a guess that one apu cycle is equivalent to
32 cpu cycles.
*/
void add_apu_cycles(int n) {
snes_time->apu_cycles += n;
snes_time->bridge.apu_cycles += (n << 5);
}
void snes_timer::add_cpu_cycles(byte count, byte speed) {
ulong cycles = count * speed;
master_cycles += cycles;
bridge.cpu_cycles += cycles;
}
void snes_timer::add_cpu_pcycles(byte count) {
ulong speed = mem_speed_map[(gx816->regs.pc & 0xffffff) >> 9];
ulong cycles = count * speed;
master_cycles += cycles;
bridge.cpu_cycles += cycles;
}
void snes_timer::add_cpu_mcycles(byte count, ulong addr) {
ulong speed = mem_speed_map[(addr & 0xffffff) >> 9];
ulong cycles = count * speed;
master_cycles += cycles;
bridge.cpu_cycles += cycles;
}
void snes_timer::add_cpu_scycles(byte count) {
ulong cycles = (count << 3); //count * 8
master_cycles += cycles;
bridge.cpu_cycles += cycles;
}
void snes_timer::add_cpu_icycles(byte count) {
ulong cycles = (count << 2) + (count << 1); //count * 6
master_cycles += cycles;
bridge.cpu_cycles += cycles;
}
void snes_timer::set_speed_map(byte speed) {
if(speed == MEMSPEED_SLOWROM) {
mem_speed_map = sm_slowrom;
} else { //speed == MEMSPEED_FASTROM
mem_speed_map = sm_fastrom;
}
}
void snes_timer::build_speed_map(void) {
int i;
byte db;
word addr;
ulong z;
sm_slowrom = (byte*)malloc(0x8000);
sm_fastrom = (byte*)malloc(0x8000);
for(i=0;i<0x8000;i++) {
z = (i << 9);
db = (z >> 16);
addr = (z & 0xffff);
if(db >= 0x00 && db <= 0x3f) {
if (addr >= 0x0000 && addr <= 0x1fff) {
sm_slowrom[i] = MEMSPEED_SLOW;
sm_fastrom[i] = MEMSPEED_SLOW;
}
else if(addr >= 0x2000 && addr <= 0x3fff) {
sm_slowrom[i] = MEMSPEED_FAST;
sm_fastrom[i] = MEMSPEED_FAST;
}
else if(addr >= 0x4000 && addr <= 0x41ff) {
sm_slowrom[i] = MEMSPEED_XSLOW;
sm_fastrom[i] = MEMSPEED_XSLOW;
}
else if(addr >= 0x4200 && addr <= 0x5fff) {
sm_slowrom[i] = MEMSPEED_FAST;
sm_fastrom[i] = MEMSPEED_FAST;
}
else { //(addr >= 0x6000 && addr <= 0xffff)
sm_slowrom[i] = MEMSPEED_SLOW;
sm_fastrom[i] = MEMSPEED_SLOW;
}
} else if(db >= 0x40 && db <= 0x7f) {
sm_slowrom[i] = MEMSPEED_SLOW;
sm_fastrom[i] = MEMSPEED_SLOW;
} else if(db >= 0x80 && db <= 0xbf) {
if (addr >= 0x0000 && addr <= 0x1fff) {
sm_slowrom[i] = MEMSPEED_SLOW;
sm_fastrom[i] = MEMSPEED_SLOW;
}
else if(addr >= 0x2000 && addr <= 0x3fff) {
sm_slowrom[i] = MEMSPEED_FAST;
sm_fastrom[i] = MEMSPEED_FAST;
}
else if(addr >= 0x4000 && addr <= 0x41ff) {
sm_slowrom[i] = MEMSPEED_XSLOW;
sm_fastrom[i] = MEMSPEED_XSLOW;
}
else if(addr >= 0x4200 && addr <= 0x5fff) {
sm_slowrom[i] = MEMSPEED_FAST;
sm_fastrom[i] = MEMSPEED_FAST;
}
else if(addr >= 0x6000 && addr <= 0x7fff) {
sm_slowrom[i] = MEMSPEED_SLOW;
sm_fastrom[i] = MEMSPEED_SLOW;
}
else { //(addr >= 0x8000 && addr <= 0xffff)
sm_slowrom[i] = MEMSPEED_SLOW;
sm_fastrom[i] = MEMSPEED_FAST;
}
} else { //(db >= 0xc0 && db <= 0xff)
sm_slowrom[i] = MEMSPEED_SLOW;
sm_fastrom[i] = MEMSPEED_FAST;
}
}
}
/*
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 }
latch_table_a is used for interlace-even, interlace-odd, and
non-interlace-even frames. this is done to conserve memory.
interlace-even frames have one extra scanline, but the
cycle-to-x/y positions are still identical.
latch_table_b is used for non-interlace-odd, because these
frames have one scanline that is 4 master cycles shorter than
the others. this would offset all x/y positions from (322,240)
and onward without a separate table.
both tables are one scanline longer than the snes allows so that
if the x/y positions are refreshed and the cycle position used
goes beyond the end of the frame, it won't access an invalid
memory address. the routine will then see that the y position
is higher than the current frame allows, and it will reset the
y position at that time.
*/
void snes_timer::build_dot_map(void) {
int x, y, cycle;
int ptr;
latch_table_a = (latch_pos*)malloc(264 * (1364 / 2) * sizeof(latch_pos));
latch_table_b = (latch_pos*)malloc(263 * (1364 / 2) * sizeof(latch_pos));
ptr = 0;
for(y=0;y<264;y++) {
for(x=cycle=0;x<340;x++) {
latch_table_a[ptr].cx = cycle;
latch_table_a[ptr].x = x;
latch_table_a[ptr].y = y;
ptr++;
cycle += 2;
latch_table_a[ptr].cx = cycle;
latch_table_a[ptr].x = x;
latch_table_a[ptr].y = y;
ptr++;
cycle += 2;
if(x == 322 || x == 326) {
latch_table_a[ptr].cx = cycle;
latch_table_a[ptr].x = x;
latch_table_a[ptr].y = y;
ptr++;
cycle += 2;
}
}
}
ptr = 0;
for(y=0;y<263;y++) {
for(x=cycle=0;x<340;x++) {
latch_table_b[ptr].cx = cycle;
latch_table_b[ptr].x = x;
latch_table_b[ptr].y = y;
ptr++;
cycle += 2;
latch_table_b[ptr].cx = cycle;
latch_table_b[ptr].x = x;
latch_table_b[ptr].y = y;
ptr++;
cycle += 2;
if(y != 240 && (x == 322 || x == 326)) {
latch_table_b[ptr].cx = cycle;
latch_table_b[ptr].x = x;
latch_table_b[ptr].y = y;
ptr++;
cycle += 2;
}
}
}
}
void snes_timer::reset_clock(void) {
mem_speed_map = sm_slowrom;
//upon SNES reset, starts at scanline 0 non-interlace
frame_cycles = 262 * 1364;
frame_lines = 262;
line_cycles = 1364;
ppu.interlace = false;
ppu.toggle_interlace = false;
ppu.interlace_frame = 0;
latch_table = latch_table_a;
vscan_pos = 0;
hscan_pos = 0;
hcycle_pos = 0;
dram_refresh_pos = 538;
dram_refreshed = false;
nmi_triggered = false;
apu_cycles = 0;
bridge.cpu_cycles = 0;
bridge.apu_cycles = 0;
/*
Initial latch values for $213c/$213d
0035:0000 (53.0 -> 212) [lda $2137]
0038:0000 (56.5 -> 226) [nop : lda $2137]
*/
master_cycles = 188;
prev_master_cycles = 0;
update_timer();
}
snes_timer::snes_timer() {
build_speed_map();
build_dot_map();
}
snes_timer::~snes_timer() {
if(mem_speed_map)free(mem_speed_map);
if(latch_table_a)free(latch_table_a);
if(latch_table_b)free(latch_table_b);
}
/*
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.
*/
void snes_timer::inc_vscan_pos(void) {
if(vscan_pos >= frame_lines) {
master_cycles -= frame_cycles;
vscan_pos = 0;
nmi_triggered = false;
ppu.interlace = ppu.toggle_interlace;
ppu.interlace_frame ^= 1;
if(ppu.interlace == true) {
if(ppu.interlace_frame == 0) {
frame_cycles = 263 * 1364;
frame_lines = 263;
} else {
frame_cycles = 262 * 1364;
frame_lines = 262;
}
latch_table = latch_table_a;
} else { //ppu.interlace == false
if(ppu.interlace_frame == 0) {
frame_cycles = 262 * 1364;
frame_lines = 262;
latch_table = latch_table_a;
} else {
frame_cycles = (262 * 1364) - 4;
frame_lines = 262;
latch_table = latch_table_b;
}
}
vscan_wrapped = true;
}
if(ppu.interlace == false && ppu.interlace_frame == 1 && vscan_pos == 240) {
line_cycles = 1360;
} else {
line_cycles = 1364;
}
hscan_wrapped = true;
dram_refreshed = false;
}
void snes_timer::update_dram_refresh_pos(void) {
if(ppu.interlace == false && ppu.interlace_frame == 1 && vscan_pos == 240) {
//dram refresh position doesn't change
} else {
if(dram_refresh_pos == 534) {
dram_refresh_pos = 538;
} else {
dram_refresh_pos = 534;
}
}
}
/*
this routine is *not* designed to seek to any scan position passed to it.
it is intended that cycle_pos is no more than 40 master cycles above the
previous cycle_pos given to this routine. the routine has two purposes,
one is to actually update the screen x/y positions and trigger system
events; the other is to allow the 4 master cycle difference between latching
the x/y counters from reading $2137 and writing $4201.
the former passes update_frame_info as true, as the changes should be permanent.
the latter passes update_frame_info as false, as the real cycle counter will
not be incremented at that time (that is handled within the opcodes themselves).
the cycle_pos passed is divided by 2 because the smallest possible cpu clock
frequency is 2 master cycles, and this allows the latch tables to consume only
half as much memory.
*/
void snes_timer::set_scan_pos(ulong cycle_pos, bool update_frame_info) {
int y;
y = vscan_pos;
cycle_pos >>= 1;
vscan_pos = latch_table[cycle_pos].y;
hscan_pos = latch_table[cycle_pos].x;
hcycle_pos = latch_table[cycle_pos].cx;
if(update_frame_info == true) {
if(vscan_pos > y) {
inc_vscan_pos();
}
} else {
if(vscan_pos >= frame_lines) {
vscan_pos -= frame_lines;
}
}
if(dram_refreshed == false && hcycle_pos >= dram_refresh_pos) {
if(update_frame_info == true) {
add_cpu_cycles(1, 40);
dram_refreshed = true;
update_dram_refresh_pos();
}
hcycle_pos += 40;
hscan_pos += 10;
}
}
void snes_timer::update_timer(void) {
set_scan_pos(master_cycles, true);
}
void snes_timer::update_timer_events(void) {
if(gx816->cpu_state == CPUSTATE_STP)return;
if(snes_time->vscan_pos == (ppu.visible_scanlines + 1) && snes_time->hcycle_pos >= 12 && nmi_triggered == false) {
nmi_triggered = true;
gx816->nmi_pin = 0;
if(gx816->nmi_enabled == true) {
gx816->InvokeIRQ(0xffea);
}
}
}
+43
View File
@@ -0,0 +1,43 @@
//mask table (powers of 2)
#define TIMING_NONE 0x00
#define TIMING_CONDITION2 0x01 //DL != 0
#define TIMING_CONDITION4 0x02 //crossed page boundary or p.x = 0
typedef struct {
word cx, x, y;
}latch_pos;
class snes_timer {
public:
ulong apu_cycles;
ulong master_cycles, prev_master_cycles;
struct {
ulong cpu_cycles, apu_cycles;
}bridge;
word hcycle_pos, vscan_pos, hscan_pos;
bool vscan_wrapped, hscan_wrapped;
bool dram_refreshed, nmi_triggered;
byte *mem_speed_map, *sm_slowrom, *sm_fastrom;
ulong frame_cycles, frame_lines, line_cycles;
word dram_refresh_pos;
latch_pos *latch_table_a, *latch_table_b, *latch_table;
void add_cpu_cycles (byte count, byte speed);
void add_cpu_pcycles(byte count);
void add_cpu_mcycles(byte count, ulong addr);
void add_cpu_scycles(byte count);
void add_cpu_icycles(byte count);
ulong get_master_cycle_count(ulong offset);
void build_speed_map(void);
void build_dot_map(void);
void reset_clock(void);
void inc_vscan_pos(void);
void set_scan_pos(ulong cycle_pos, bool update_frame_info);
void set_speed_map(byte speed);
void update_dram_refresh_pos(void);
void update_timer(void);
void update_timer_events(void);
snes_timer();
~snes_timer();
};
+459
View File
@@ -0,0 +1,459 @@
#include "../base.h"
#include "../timing/timing.h"
extern snes_timer *snes_time;
#include "../cpu/g65816.h"
#include "../apu/spc700.h"
extern g65816 *gx816;
extern sony_spc700 *spc700;
extern emustate emu_state;
extern debugstate debugger;
extern videostate render;
extern ppustate ppu;
#include <windows.h>
#define BSNES_TITLE "bsnes v0.0.005a"
enum {
MENU_FILE_LOAD = 100,
MENU_FILE_RESET,
MENU_FILE_EXIT,
MENU_SETTINGS_VIDEOMODE_256x224w,
MENU_SETTINGS_VIDEOMODE_512x448w,
MENU_SETTINGS_VIDEOMODE_640x480f,
MENU_SETTINGS_FRAMESKIP_OFF,
MENU_SETTINGS_FRAMESKIP_1,
MENU_SETTINGS_FRAMESKIP_2,
MENU_SETTINGS_FRAMESKIP_3,
MENU_SETTINGS_FRAMESKIP_4,
MENU_SETTINGS_FRAMESKIP_5,
MENU_SETTINGS_FRAMESKIP_6,
MENU_SETTINGS_FRAMESKIP_7,
MENU_SETTINGS_FRAMESKIP_8,
MENU_SETTINGS_FRAMESKIP_9,
MENU_SETTINGS_DEBUGGER,
MENU_HELP_ABOUT
};
HWND hwndMain = 0;
HMENU hmenuMain;
HFONT hFontFixed, hFont;
extern joypad_state joypad1;
#define KEY_UP VK_UP
#define KEY_DOWN VK_DOWN
#define KEY_LEFT VK_LEFT
#define KEY_RIGHT VK_RIGHT
#define KEY_SHIFT VK_RSHIFT
#define KEY_ENTER VK_RETURN
#define KEY_A 'A'
#define KEY_S 'S'
#define KEY_D 'D'
#define KEY_Z 'Z'
#define KEY_X 'X'
#define KEY_C 'C'
#define KeyState(key) ((GetAsyncKeyState(key) & 0x8000)?1:0)
void UpdateJoypad(void) {
joypad1.up = KeyState(KEY_UP );
joypad1.down = (joypad1.up)?0:KeyState(KEY_DOWN);
joypad1.left = KeyState(KEY_LEFT );
joypad1.right = (joypad1.left)?0:KeyState(KEY_RIGHT);
joypad1.select = KeyState(KEY_SHIFT);
joypad1.start = KeyState(KEY_ENTER);
joypad1.y = KeyState(KEY_A );
joypad1.b = KeyState(KEY_Z );
joypad1.x = KeyState(KEY_S );
joypad1.a = KeyState(KEY_X );
joypad1.l = KeyState(KEY_D );
joypad1.r = KeyState(KEY_C );
if(debugger_enabled() == false)return;
if(debugger.lock_up == true)joypad1.up = 1;
if(debugger.lock_down == true)joypad1.down = 1;
if(debugger.lock_left == true)joypad1.left = 1;
if(debugger.lock_right == true)joypad1.right = 1;
if(debugger.lock_a == true)joypad1.a = 1;
if(debugger.lock_b == true)joypad1.b = 1;
if(debugger.lock_x == true)joypad1.x = 1;
if(debugger.lock_y == true)joypad1.y = 1;
if(debugger.lock_l == true)joypad1.l = 1;
if(debugger.lock_r == true)joypad1.r = 1;
if(debugger.lock_select == true)joypad1.select = 1;
if(debugger.lock_start == true)joypad1.start = 1;
}
void alert(char *s, ...) {
char str[4096];
va_list args;
va_start(args, s);
vsprintf(str, s, args);
va_end(args);
MessageBox(0, str, "bsnes", MB_OK);
}
void FixWindowSize(HWND hwnd, ulong width, ulong height, ulong px = null, ulong py = null) {
RECT rc;
ulong x, y, wx, wy;
ShowWindow(hwnd, SW_HIDE);
SetWindowPos(hwnd, 0, 0, 0, width, height, SWP_NOZORDER);
GetClientRect(hwnd, &rc);
x = width + width - (rc.right - rc.left);
y = height + height - (rc.bottom - rc.top);
wx = (GetSystemMetrics(SM_CXSCREEN) - x) / 2;
wy = (GetSystemMetrics(SM_CYSCREEN) - y) / 2;
if(px == null || py == null) {
SetWindowPos(hwnd, 0, wx, wy, x, y, SWP_NOZORDER);
} else {
SetWindowPos(hwnd, 0, px, py, x, y, SWP_NOZORDER);
}
}
HBRUSH black_brush;
long __stdcall wndprocMain(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
void RegisterMainWindow() {
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = black_brush;
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = wndprocMain;
wc.lpszClassName = "bsnes";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
}
void CreateMainMenu(void) {
HMENU hsubmenu, hbranchmenu;
hmenuMain = CreateMenu();
hsubmenu = CreatePopupMenu();
AppendMenu(hsubmenu, MF_STRING, MENU_FILE_LOAD, "&Load ROM");
AppendMenu(hsubmenu, MF_STRING, MENU_FILE_RESET, "&Reset");
AppendMenu(hsubmenu, MF_SEPARATOR, 0, "");
AppendMenu(hsubmenu, MF_STRING, MENU_FILE_EXIT, "E&xit");
AppendMenu(hmenuMain, MF_STRING | MF_POPUP, (unsigned int)hsubmenu, "&File");
hsubmenu = CreatePopupMenu();
hbranchmenu = CreatePopupMenu();
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_VIDEOMODE_256x224w, "256x224 Windowed");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_VIDEOMODE_512x448w, "512x448 Windowed");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_VIDEOMODE_640x480f, "640x480 Fullscreen");
AppendMenu(hsubmenu, MF_STRING | MF_POPUP, (unsigned int)hbranchmenu, "&Video Mode");
hbranchmenu = CreatePopupMenu();
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_FRAMESKIP_OFF, "Off");
AppendMenu(hbranchmenu, MF_SEPARATOR, 0, "");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_FRAMESKIP_1, "1");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_FRAMESKIP_2, "2");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_FRAMESKIP_3, "3");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_FRAMESKIP_4, "4");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_FRAMESKIP_5, "5");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_FRAMESKIP_6, "6");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_FRAMESKIP_7, "7");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_FRAMESKIP_8, "8");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_FRAMESKIP_9, "9");
AppendMenu(hsubmenu, MF_STRING | MF_POPUP, (unsigned int)hbranchmenu, "&Frameskip");
AppendMenu(hsubmenu, MF_SEPARATOR, 0, "");
AppendMenu(hsubmenu, MF_STRING | (debug_get_state() == DEBUGMODE_WAIT)?MF_CHECKED:MF_UNCHECKED, MENU_SETTINGS_DEBUGGER, "&Debug Mode");
AppendMenu(hmenuMain, MF_STRING | MF_POPUP, (unsigned int)hsubmenu, "&Settings");
hsubmenu = CreatePopupMenu();
AppendMenu(hsubmenu, MF_STRING, MENU_HELP_ABOUT, "&About");
AppendMenu(hmenuMain, MF_STRING | MF_POPUP, (unsigned int)hsubmenu, "&Help");
CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_512x448w, MF_CHECKED);
CheckMenuItem(hmenuMain, MENU_SETTINGS_FRAMESKIP_OFF + render.frame_skip, MF_CHECKED);
}
void CreateMainWindow(void) {
hwndMain = CreateWindow("bsnes", BSNES_TITLE, WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
0, 0, 640, 480, 0, 0, GetModuleHandle(0), 0);
CreateMainMenu();
}
void SetMainWindowPos(bool update_style) {
if(render.fullscreen == true) {
if(update_style == true) {
SetWindowLong(hwndMain, GWL_STYLE, WS_POPUP);
SetWindowLong(hwndMain, GWL_EXSTYLE, WS_EX_TOPMOST);
SetWindowPos(hwndMain, HWND_TOPMOST, 0, 0, 640, 480, 0);
}
if(render.show_menu == true) {
ShowCursor(TRUE);
} else {
ShowCursor(FALSE);
}
} else {
if(update_style == true) {
SetWindowLong(hwndMain, GWL_STYLE, WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);
SetWindowLong(hwndMain, GWL_EXSTYLE, 0);
}
FixWindowSize(hwndMain, render.display_width, render.display_height);
}
}
void UpdateMainWindowStyle(bool update_style) {
if(render.fullscreen == false) {
ShowWindow(hwndMain, SW_HIDE);
}
if(render.show_menu == true) {
SetMenu(hwndMain, hmenuMain);
SetMainWindowPos(update_style);
} else {
SetMenu(hwndMain, 0);
SetMainWindowPos(update_style);
}
if(render.fullscreen == false) {
ShowWindow(hwndMain, SW_NORMAL);
}
}
HWND NewWindow(WNDPROC wndproc, char *classname, char *title, ulong color, ulong width, ulong height) {
WNDCLASS wc;
HWND hwnd;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (color == null)?(HBRUSH)(COLOR_WINDOW):black_brush;
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = wndproc;
wc.lpszClassName = classname;
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
hwnd = CreateWindow(classname, title, WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
0, 0, width, height, 0, 0, wc.hInstance, 0);
return hwnd;
}
#include "render.cpp"
bool GUIOpenFile(char *fn) {
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwndMain;
ofn.lpstrFilter = "SNES ROM Images (*.smc;*.swc;*.fig;*.ufo;*.gd3;*.078)\0*.smc;*.swc;*.fig;*.ufo;*.gd3;*.078\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = fn;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
ofn.lpstrDefExt = "smc";
if(GetOpenFileName(&ofn)) {
return true;
} else {
return false;
}
}
void EnableDebugger(byte first_time);
void DisableDebugger(void);
long __stdcall wndprocMain(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
char fn[MAX_PATH];
bool result;
switch(msg) {
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_PAINT:
DrawScene();
break;
case WM_KEYDOWN:
switch(wparam) {
case VK_ESCAPE:
if(render.show_menu == true) {
render.show_menu = false;
} else {
render.show_menu = true;
}
UpdateMainWindowStyle(false);
break;
}
break;
case WM_COMMAND:
switch(LOWORD(wparam)) {
case MENU_FILE_LOAD:
strcpy(fn, "");
result = GUIOpenFile(fn);
if(result == true) {
emu_state.rom_loaded = true;
strcpy(emu_state.rom_name, fn);
fn[strlen(fn) - 4] = 0;
strcat(fn, ".srm");
strcpy(emu_state.sram_name, fn);
gx816->PowerOn(0);
gx816->LoadROM();
ResetSNES();
if(debugger_enabled() == true) {
debug_set_state(DEBUGMODE_WAIT);
}
}
break;
case MENU_FILE_RESET:
ResetSNES();
break;
case MENU_FILE_EXIT:
PostQuitMessage(0);
break;
case MENU_SETTINGS_VIDEOMODE_256x224w:
video_setmode(false, 256, 224);
CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_256x224w, MF_CHECKED);
CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_512x448w, MF_UNCHECKED);
CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_640x480f, MF_UNCHECKED);
break;
case MENU_SETTINGS_VIDEOMODE_512x448w:
video_setmode(false, 512, 448);
CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_256x224w, MF_UNCHECKED);
CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_512x448w, MF_CHECKED);
CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_640x480f, MF_UNCHECKED);
break;
case MENU_SETTINGS_VIDEOMODE_640x480f:
video_setmode(true, 512, 448);
CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_256x224w, MF_UNCHECKED);
CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_512x448w, MF_UNCHECKED);
CheckMenuItem(hmenuMain, MENU_SETTINGS_VIDEOMODE_640x480f, MF_CHECKED);
break;
case MENU_SETTINGS_FRAMESKIP_OFF:
case MENU_SETTINGS_FRAMESKIP_1:
case MENU_SETTINGS_FRAMESKIP_2:
case MENU_SETTINGS_FRAMESKIP_3:
case MENU_SETTINGS_FRAMESKIP_4:
case MENU_SETTINGS_FRAMESKIP_5:
case MENU_SETTINGS_FRAMESKIP_6:
case MENU_SETTINGS_FRAMESKIP_7:
case MENU_SETTINGS_FRAMESKIP_8:
case MENU_SETTINGS_FRAMESKIP_9:
CheckMenuItem(hmenuMain, MENU_SETTINGS_FRAMESKIP_OFF + render.frame_skip, MF_UNCHECKED);
render.frame_skip = LOWORD(wparam) - MENU_SETTINGS_FRAMESKIP_OFF;
render.frame_count = 0;
CheckMenuItem(hmenuMain, MENU_SETTINGS_FRAMESKIP_OFF + render.frame_skip, MF_CHECKED);
break;
case MENU_SETTINGS_DEBUGGER:
if(debugger_enabled() == false) {
CheckMenuItem(hmenuMain, MENU_SETTINGS_DEBUGGER, MF_CHECKED);
EnableDebugger(0);
} else {
CheckMenuItem(hmenuMain, MENU_SETTINGS_DEBUGGER, MF_UNCHECKED);
DisableDebugger();
}
break;
case MENU_HELP_ABOUT:
MessageBox(hwndMain, "bsnes -- written by byuu", "About", MB_OK);
break;
}
break;
}
return DefWindowProc(hwnd, msg, wparam, lparam);
}
void CreateFonts(void) {
HDC hdc;
long height;
hdc = GetDC(0);
height = -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72);
ReleaseDC(0, hdc);
hFontFixed = CreateFont(height, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Courier New");
hdc = GetDC(0);
height = -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72);
ReleaseDC(0, hdc);
hFont = CreateFont(height, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Tahoma");
}
#include "gui_cpu.cpp"
#include "gui_mem.cpp"
#include "gui_bp.cpp"
#include "gui_bgtoggle.cpp"
void EnableDebugger(byte first_time) {
debug_set_state(DEBUGMODE_WAIT);
hwndDCPU = NewWindow(wndprocDCPU, "bsnes_cpu", "console", null, DCPU_WIDTH, DCPU_HEIGHT);
CreateDCPU();
FixWindowSize(hwndDCPU, DCPU_WIDTH, DCPU_HEIGHT, 0, 1024 - 410);
hwndDMEM = NewWindow(wndprocDMEM, "bsnes_mem", "memory editor", null, DMEM_WIDTH, DMEM_HEIGHT);
CreateDMEM();
FixWindowSize(hwndDMEM, DMEM_WIDTH, DMEM_HEIGHT, 386, 321);
hwndDBP = NewWindow(wndprocDBP, "bsnes_bp", "breakpoint editor", null, DBP_WIDTH, DBP_HEIGHT);
CreateDBP();
FixWindowSize(hwndDBP, DBP_WIDTH, DBP_HEIGHT, 0, 346);
hwndDBGToggle = NewWindow(wndprocDBGToggle, "bsnes_bgtoggle", "ppu bg toggle", null, 275, 90);
CreateDBGToggle();
FixWindowSize(hwndDBGToggle, 275, 90, 0, 231);
FixWindowSize(hwndMain, 256, 223, 871, 1024 - 410);
ShowWindow(hwndDCPU, SW_NORMAL);
ShowWindow(hwndDMEM, SW_NORMAL);
ShowWindow(hwndDBP, SW_NORMAL);
ShowWindow(hwndDBGToggle, SW_NORMAL);
ShowWindow(hwndMain, SW_NORMAL);
if(first_time == 0) {
debug_refresh_mem();
debug_refresh_bp();
debug_update_status();
dprintf("* Debugger Enabled");
UpdateDisplay();
}
}
void DisableDebugger(void) {
debug_set_state(DEBUGMODE_DISABLED);
DestroyWindow(hwndDCPU);
DestroyWindow(hwndDBP);
DestroyWindow(hwndDMEM);
DestroyWindow(hwndDBGToggle);
}
void __winmain(void) {
MSG msg;
CreateFonts();
black_brush = CreateSolidBrush(RGB(0, 0, 0));
RegisterMainWindow();
CreateMainWindow();
UpdateMainWindowStyle(false);
if(debug_get_state() == DEBUGMODE_WAIT) {
EnableDebugger(1);
}
video_setmode(render.fullscreen, render.display_width, render.display_height);
InitDisplay();
CreateColorTable();
InitSNES();
UpdateDisplay();
UpdateDisplay();
while(1) {
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
if(msg.message == WM_QUIT)break;
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
RunSNES();
}
}
}
+149
View File
@@ -0,0 +1,149 @@
#define DBGTOGGLE_BG1ENABLE 100
#define DBGTOGGLE_BG1ENABLE0 101
#define DBGTOGGLE_BG1ENABLE1 102
#define DBGTOGGLE_BG2ENABLE 103
#define DBGTOGGLE_BG2ENABLE0 104
#define DBGTOGGLE_BG2ENABLE1 105
#define DBGTOGGLE_BG3ENABLE 106
#define DBGTOGGLE_BG3ENABLE0 107
#define DBGTOGGLE_BG3ENABLE1 108
#define DBGTOGGLE_BG4ENABLE 109
#define DBGTOGGLE_BG4ENABLE0 110
#define DBGTOGGLE_BG4ENABLE1 111
#define DBGTOGGLE_OAMENABLE 112
#define DBGTOGGLE_OAMENABLE0 113
#define DBGTOGGLE_OAMENABLE1 114
#define DBGTOGGLE_OAMENABLE2 115
#define DBGTOGGLE_OAMENABLE3 116
#define BGTOGGLE_CLICK(src, val) \
case src: \
state = SendDlgItemMessage(hwndDBGToggle, src, BM_GETCHECK, 0, 0); \
if(state == 0) { \
val = true; \
SendDlgItemMessage(hwndDBGToggle, src, BM_SETCHECK, 1, 0); \
} else { \
val = false; \
SendDlgItemMessage(hwndDBGToggle, src, BM_SETCHECK, 0, 0); \
} \
break
HWND hwndDBGToggle;
long __stdcall wndprocDBGToggle(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
int state;
if(msg == WM_DESTROY || msg == WM_CLOSE)return 0;
if(msg == WM_COMMAND) {
if(HIWORD(wparam) == BN_CLICKED) {
switch(LOWORD(wparam)) {
BGTOGGLE_CLICK(DBGTOGGLE_BG1ENABLE, render.bg1_enabled[DEBUG_BGENABLED_ALL ]);
BGTOGGLE_CLICK(DBGTOGGLE_BG1ENABLE0, render.bg1_enabled[DEBUG_BGENABLED_PRI0]);
BGTOGGLE_CLICK(DBGTOGGLE_BG1ENABLE1, render.bg1_enabled[DEBUG_BGENABLED_PRI1]);
BGTOGGLE_CLICK(DBGTOGGLE_BG2ENABLE, render.bg2_enabled[DEBUG_BGENABLED_ALL ]);
BGTOGGLE_CLICK(DBGTOGGLE_BG2ENABLE0, render.bg2_enabled[DEBUG_BGENABLED_PRI0]);
BGTOGGLE_CLICK(DBGTOGGLE_BG2ENABLE1, render.bg2_enabled[DEBUG_BGENABLED_PRI1]);
BGTOGGLE_CLICK(DBGTOGGLE_BG3ENABLE, render.bg3_enabled[DEBUG_BGENABLED_ALL ]);
BGTOGGLE_CLICK(DBGTOGGLE_BG3ENABLE0, render.bg3_enabled[DEBUG_BGENABLED_PRI0]);
BGTOGGLE_CLICK(DBGTOGGLE_BG3ENABLE1, render.bg3_enabled[DEBUG_BGENABLED_PRI1]);
BGTOGGLE_CLICK(DBGTOGGLE_BG4ENABLE, render.bg4_enabled[DEBUG_BGENABLED_ALL ]);
BGTOGGLE_CLICK(DBGTOGGLE_BG4ENABLE0, render.bg4_enabled[DEBUG_BGENABLED_PRI0]);
BGTOGGLE_CLICK(DBGTOGGLE_BG4ENABLE1, render.bg4_enabled[DEBUG_BGENABLED_PRI1]);
BGTOGGLE_CLICK(DBGTOGGLE_OAMENABLE, render.oam_enabled[DEBUG_BGENABLED_ALL ]);
BGTOGGLE_CLICK(DBGTOGGLE_OAMENABLE0, render.oam_enabled[DEBUG_BGENABLED_PRI0]);
BGTOGGLE_CLICK(DBGTOGGLE_OAMENABLE1, render.oam_enabled[DEBUG_BGENABLED_PRI1]);
BGTOGGLE_CLICK(DBGTOGGLE_OAMENABLE2, render.oam_enabled[DEBUG_BGENABLED_PRI2]);
BGTOGGLE_CLICK(DBGTOGGLE_OAMENABLE3, render.oam_enabled[DEBUG_BGENABLED_PRI3]);
}
}
}
return DefWindowProc(hwnd, msg, wparam, lparam);
}
void CreateDBGToggle(void) {
int x, y, wl, wr, h;
x = 5;
y = 5;
wl = 90;
wr = 45;
h = 16;
CreateWindow("BUTTON", "Enable BG1", WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x, y, wl, h,
hwndDBGToggle, (HMENU)DBGTOGGLE_BG1ENABLE, GetModuleHandle(0), 0);
x += wl;
CreateWindow("BUTTON", "Pri 0", WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x, y, wr, h,
hwndDBGToggle, (HMENU)DBGTOGGLE_BG1ENABLE0, GetModuleHandle(0), 0);
x += wr;
CreateWindow("BUTTON", "Pri 1", WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x, y, wr, h,
hwndDBGToggle, (HMENU)DBGTOGGLE_BG1ENABLE1, GetModuleHandle(0), 0);
x = 5;
y += h;
CreateWindow("BUTTON", "Enable BG2", WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x, y, wl, h,
hwndDBGToggle, (HMENU)DBGTOGGLE_BG2ENABLE, GetModuleHandle(0), 0);
x += wl;
CreateWindow("BUTTON", "Pri 0", WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x, y, wr, h,
hwndDBGToggle, (HMENU)DBGTOGGLE_BG2ENABLE0, GetModuleHandle(0), 0);
x += wr;
CreateWindow("BUTTON", "Pri 1", WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x, y, wr, h,
hwndDBGToggle, (HMENU)DBGTOGGLE_BG2ENABLE1, GetModuleHandle(0), 0);
x = 5;
y += h;
CreateWindow("BUTTON", "Enable BG3", WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x, y, wl, h,
hwndDBGToggle, (HMENU)DBGTOGGLE_BG3ENABLE, GetModuleHandle(0), 0);
x += wl;
CreateWindow("BUTTON", "Pri 0", WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x, y, wr, h,
hwndDBGToggle, (HMENU)DBGTOGGLE_BG3ENABLE0, GetModuleHandle(0), 0);
x += wr;
CreateWindow("BUTTON", "Pri 1", WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x, y, wr, h,
hwndDBGToggle, (HMENU)DBGTOGGLE_BG3ENABLE1, GetModuleHandle(0), 0);
x = 5;
y += h;
CreateWindow("BUTTON", "Enable BG4", WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x, y, wl, h,
hwndDBGToggle, (HMENU)DBGTOGGLE_BG4ENABLE, GetModuleHandle(0), 0);
x += wl;
CreateWindow("BUTTON", "Pri 0", WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x, y, wr, h,
hwndDBGToggle, (HMENU)DBGTOGGLE_BG4ENABLE0, GetModuleHandle(0), 0);
x += wr;
CreateWindow("BUTTON", "Pri 1", WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x, y, wr, h,
hwndDBGToggle, (HMENU)DBGTOGGLE_BG4ENABLE1, GetModuleHandle(0), 0);
x = 5;
y += h;
CreateWindow("BUTTON", "Enable OAM", WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x, y, wl, h,
hwndDBGToggle, (HMENU)DBGTOGGLE_OAMENABLE, GetModuleHandle(0), 0);
x += wl;
CreateWindow("BUTTON", "Pri 0", WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x, y, wr, h,
hwndDBGToggle, (HMENU)DBGTOGGLE_OAMENABLE0, GetModuleHandle(0), 0);
x += wr;
CreateWindow("BUTTON", "Pri 1", WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x, y, wr, h,
hwndDBGToggle, (HMENU)DBGTOGGLE_OAMENABLE1, GetModuleHandle(0), 0);
x += wr;
CreateWindow("BUTTON", "Pri 2", WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x, y, wr, h,
hwndDBGToggle, (HMENU)DBGTOGGLE_OAMENABLE2, GetModuleHandle(0), 0);
x += wr;
CreateWindow("BUTTON", "Pri 3", WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x, y, wr, h,
hwndDBGToggle, (HMENU)DBGTOGGLE_OAMENABLE3, GetModuleHandle(0), 0);
SendDlgItemMessage(hwndDBGToggle, DBGTOGGLE_BG1ENABLE, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBGToggle, DBGTOGGLE_BG1ENABLE0, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBGToggle, DBGTOGGLE_BG1ENABLE1, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBGToggle, DBGTOGGLE_BG2ENABLE, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBGToggle, DBGTOGGLE_BG2ENABLE0, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBGToggle, DBGTOGGLE_BG2ENABLE1, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBGToggle, DBGTOGGLE_BG3ENABLE, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBGToggle, DBGTOGGLE_BG3ENABLE0, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBGToggle, DBGTOGGLE_BG3ENABLE1, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBGToggle, DBGTOGGLE_BG4ENABLE, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBGToggle, DBGTOGGLE_BG4ENABLE0, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBGToggle, DBGTOGGLE_BG4ENABLE1, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBGToggle, DBGTOGGLE_OAMENABLE, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBGToggle, DBGTOGGLE_OAMENABLE0, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBGToggle, DBGTOGGLE_OAMENABLE1, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBGToggle, DBGTOGGLE_OAMENABLE2, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBGToggle, DBGTOGGLE_OAMENABLE3, WM_SETFONT, (WPARAM)hFont, TRUE);
for(int i=DBGTOGGLE_BG1ENABLE;i<=DBGTOGGLE_OAMENABLE3;i++) {
SendDlgItemMessage(hwndDBGToggle, i, BM_SETCHECK, 1, 0);
}
}
+227
View File
@@ -0,0 +1,227 @@
#define DBP_WIDTH 380
#define DBP_HEIGHT 243
#define DBP_LIST 100
#define DBP_ADDBP 101
#define DBP_REMBP 102
#define DBP_CLRBP 103
#define DBP_STATIC1 104
#define DBP_BPNUM 105
#define DBP_BPOFFSET 106
#define DBP_BPR 107
#define DBP_BPW 108
#define DBP_BPX 109
#define DBP_BPV 110
#define DBP_BPVAL 111
#define DBP_STATIC2 112
#define DBP_SRCMEM 113
#define DBP_SRCVRAM 114
#define DBP_SRCCGRAM 115
#define DBP_SRCOAM 116
#define DBP_SRCSPCRAM 117
#define DBP_SRCMODE 118
HWND hwndDBP;
byte debug_bp_src;
void debug_refresh_bp(void) {
char str[128*16], t[128];
if(debugger_enabled() == false)return;
strcpy(str, "");
for(int i=0;i<16;i++) {
sprintf(t, "%0.2d: ", i);
strcat(str, t);
if(debugger.bp_list[i].flags == BP_OFF) {
strcat(str, "------ ---- -- ------ (Disabled)");
} else {
sprintf(t, "%0.6x %c%c%c%c ", debugger.bp_list[i].offset,
(debugger.bp_list[i].flags & BP_READ )?'R':'r',
(debugger.bp_list[i].flags & BP_WRITE)?'W':'w',
(debugger.bp_list[i].flags & BP_EXEC )?'X':'x',
(debugger.bp_list[i].flags & BP_VAL )?'V':'v');
strcat(str, t);
if(debugger.bp_list[i].flags & BP_VAL) {
sprintf(t, "%0.2x ", debugger.bp_list[i].value);
strcat(str, t);
} else strcat(str, "-- ");
switch(debugger.bp_list[i].source) {
case BPSRC_MEM: strcat(str, "DRAM ");break;
case BPSRC_VRAM: strcat(str, "VRAM ");break;
case BPSRC_CGRAM: strcat(str, "CGRAM ");break;
case BPSRC_OAM: strcat(str, "OAM ");break;
case BPSRC_SPCRAM:strcat(str, "SPCRAM ");break;
}
sprintf(t, "%10d", debugger.bp_list[i].hit_count);
strcat(str, t);
}
if(i != 15)strcat(str, "\r\n");
}
SetDlgItemText(hwndDBP, DBP_LIST, str);
}
long __stdcall wndprocDBP(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
char str[256];
ulong num, offset, val, flags;
int i, pos;
if(msg == WM_DESTROY || msg == WM_CLOSE)return 0; //don't allow debugger to be closed (yet)
if(msg == WM_COMMAND) {
switch(LOWORD(wparam)) {
case DBP_BPNUM:
if(HIWORD(wparam) == CBN_SELCHANGE) {
num = SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_GETCURSEL, 0, 0);
sprintf(str, "%0.6x", debugger.bp_list[num].offset);
SetDlgItemText(hwndDBP, DBP_BPOFFSET, str);
sprintf(str, "%0.2x", debugger.bp_list[num].value);
SetDlgItemText(hwndDBP, DBP_BPVAL, str);
switch(debugger.bp_list[num].source) {
case BPSRC_MEM: pos = 0; break;
case BPSRC_VRAM: pos = 1; break;
case BPSRC_CGRAM: pos = 2; break;
case BPSRC_OAM: pos = 3; break;
case BPSRC_SPCRAM: pos = 4; break;
}
SendDlgItemMessage(hwndDBP, DBP_SRCMODE, CB_SETCURSEL, (WPARAM)pos, 0);
SendDlgItemMessage(hwndDBP, DBP_BPR, BM_SETCHECK, (debugger.bp_list[num].flags & BP_READ )?1:0, 0);
SendDlgItemMessage(hwndDBP, DBP_BPW, BM_SETCHECK, (debugger.bp_list[num].flags & BP_WRITE)?1:0, 0);
SendDlgItemMessage(hwndDBP, DBP_BPX, BM_SETCHECK, (debugger.bp_list[num].flags & BP_EXEC )?1:0, 0);
SendDlgItemMessage(hwndDBP, DBP_BPV, BM_SETCHECK, (debugger.bp_list[num].flags & BP_VAL )?1:0, 0);
}
break;
case DBP_ADDBP:
num = SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_GETCURSEL, 0, 0);
GetDlgItemText(hwndDBP, DBP_BPOFFSET, str, 255);
offset = strhex(str) & 0xffffff;
GetDlgItemText(hwndDBP, DBP_BPVAL, str, 255);
val = strhex(str);
flags = 0;
if(SendDlgItemMessage(hwndDBP, DBP_BPR, BM_GETCHECK, 0, 0))flags |= BP_READ;
if(SendDlgItemMessage(hwndDBP, DBP_BPW, BM_GETCHECK, 0, 0))flags |= BP_WRITE;
if(SendDlgItemMessage(hwndDBP, DBP_BPX, BM_GETCHECK, 0, 0))flags |= BP_EXEC;
if(SendDlgItemMessage(hwndDBP, DBP_BPV, BM_GETCHECK, 0, 0))flags |= BP_VAL;
debugger.bp_list[num].offset = offset;
debugger.bp_list[num].flags = flags;
debugger.bp_list[num].source = debug_bp_src;
if(debugger.bp_list[num].flags & BP_VAL) {
debugger.bp_list[num].value = val;
} else {
debugger.bp_list[num].value = 0;
}
debugger.bp_list[num].hit_count = 0;
debugger.refresh_bp = true;
break;
case DBP_REMBP:
num = SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_GETCURSEL, 0, 0);
debugger.bp_list[num].offset = 0;
debugger.bp_list[num].flags = BP_OFF;
debugger.bp_list[num].source = BPSRC_MEM;
debugger.bp_list[num].value = 0;
debugger.bp_list[num].hit_count = 0;
debugger.refresh_bp = true;
break;
case DBP_CLRBP:
for(i=0;i<16;i++) {
debugger.bp_list[i].offset = 0;
debugger.bp_list[i].flags = BP_OFF;
debugger.bp_list[i].source = BPSRC_MEM;
debugger.bp_list[i].value = 0;
debugger.bp_list[i].hit_count = 0;
}
debugger.refresh_bp = true;
break;
case DBP_SRCMODE:
if(HIWORD(wparam) == CBN_SELCHANGE) {
pos = SendDlgItemMessage(hwndDBP, DBP_SRCMODE, CB_GETCURSEL, 0, 0);
if(pos == 0) {
debug_bp_src = BPSRC_MEM;
} else if(pos == 1) {
debug_bp_src = BPSRC_VRAM;
} else if(pos == 2) {
debug_bp_src = BPSRC_CGRAM;
} else if(pos == 3) {
debug_bp_src = BPSRC_OAM;
} else if(pos == 4) {
debug_bp_src = BPSRC_SPCRAM;
}
}
break;
}
}
return DefWindowProc(hwnd, msg, wparam, lparam);
}
void CreateDBP(void) {
CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_READONLY,
5, 5, 260, 233, hwndDBP, (HMENU)DBP_LIST, GetModuleHandle(0), 0);
CreateWindow("STATIC", "BP #: Offset:", WS_CHILD|WS_VISIBLE, 270, 5, 90, 15, hwndDBP, (HMENU)DBP_STATIC1, GetModuleHandle(0), 0);
CreateWindow("COMBOBOX", "",
WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST|CBS_HASSTRINGS,
270, 20, 45, 300, hwndDBP, (HMENU)DBP_BPNUM, GetModuleHandle(0), 0);
SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"00");
SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"01");
SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"02");
SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"03");
SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"04");
SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"05");
SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"06");
SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"07");
SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"08");
SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"09");
SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"10");
SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"11");
SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"12");
SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"13");
SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"14");
SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_ADDSTRING, 0, (LPARAM)"15");
SendDlgItemMessage(hwndDBP, DBP_BPNUM, CB_SETCURSEL, 0, 0);
CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "000000", WS_CHILD|WS_VISIBLE, 315, 20, 60, 23, hwndDBP, (HMENU)DBP_BPOFFSET, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "R", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 270, 44, 30, 18, hwndDBP, (HMENU)DBP_BPR, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "W", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 300, 44, 30, 18, hwndDBP, (HMENU)DBP_BPW, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "X", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 330, 44, 30, 18, hwndDBP, (HMENU)DBP_BPX, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "V", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 270, 65, 30, 18, hwndDBP, (HMENU)DBP_BPV, GetModuleHandle(0), 0);
CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "00", WS_CHILD|WS_VISIBLE, 300, 62, 30, 23, hwndDBP, (HMENU)DBP_BPVAL, GetModuleHandle(0), 0);
CreateWindow("STATIC", "Source:", WS_CHILD|WS_VISIBLE, 270, 85, 90, 15, hwndDBP, (HMENU)DBP_STATIC2, GetModuleHandle(0), 0);
CreateWindow("COMBOBOX", "",
WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST|CBS_HASSTRINGS,
270, 100, 105, 200, hwndDBP, (HMENU)DBP_SRCMODE, GetModuleHandle(0), 0);
SendDlgItemMessage(hwndDBP, DBP_SRCMODE, CB_ADDSTRING, 0, (LPARAM)"DRAM");
SendDlgItemMessage(hwndDBP, DBP_SRCMODE, CB_ADDSTRING, 0, (LPARAM)"VRAM");
SendDlgItemMessage(hwndDBP, DBP_SRCMODE, CB_ADDSTRING, 0, (LPARAM)"CGRAM");
SendDlgItemMessage(hwndDBP, DBP_SRCMODE, CB_ADDSTRING, 0, (LPARAM)"OAM");
SendDlgItemMessage(hwndDBP, DBP_SRCMODE, CB_ADDSTRING, 0, (LPARAM)"SPCRAM");
SendDlgItemMessage(hwndDBP, DBP_SRCMODE, CB_SETCURSEL, 0, 0);
CreateWindow("BUTTON", "Set BP", WS_CHILD|WS_VISIBLE, 270, 125, 105, 20, hwndDBP, (HMENU)DBP_ADDBP, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Clear BP", WS_CHILD|WS_VISIBLE, 270, 145, 105, 20, hwndDBP, (HMENU)DBP_REMBP, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Clear All BPs", WS_CHILD|WS_VISIBLE, 270, 165, 105, 20, hwndDBP, (HMENU)DBP_CLRBP, GetModuleHandle(0), 0);
SendDlgItemMessage(hwndDBP, DBP_LIST, WM_SETFONT, (WPARAM)hFontFixed, TRUE);
SendDlgItemMessage(hwndDBP, DBP_STATIC1, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBP, DBP_BPNUM, WM_SETFONT, (WPARAM)hFontFixed, TRUE);
SendDlgItemMessage(hwndDBP, DBP_BPOFFSET, WM_SETFONT, (WPARAM)hFontFixed, TRUE);
SendDlgItemMessage(hwndDBP, DBP_BPR, WM_SETFONT, (WPARAM)hFontFixed, TRUE);
SendDlgItemMessage(hwndDBP, DBP_BPW, WM_SETFONT, (WPARAM)hFontFixed, TRUE);
SendDlgItemMessage(hwndDBP, DBP_BPX, WM_SETFONT, (WPARAM)hFontFixed, TRUE);
SendDlgItemMessage(hwndDBP, DBP_BPV, WM_SETFONT, (WPARAM)hFontFixed, TRUE);
SendDlgItemMessage(hwndDBP, DBP_BPVAL, WM_SETFONT, (WPARAM)hFontFixed, TRUE);
SendDlgItemMessage(hwndDBP, DBP_SRCMODE, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBP, DBP_STATIC2, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBP, DBP_ADDBP, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBP, DBP_REMBP, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBP, DBP_CLRBP, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDBP, DBP_SRCMEM, BM_SETCHECK, 1, 0);
debug_bp_src = BPSRC_MEM;
}
+409
View File
@@ -0,0 +1,409 @@
#define DCPU_WIDTH 865
#define DCPU_HEIGHT 385
enum {
DCPU_DISAS = 100,
DCPU_CPUGROUP,
DCPU_CPUSTEP,
DCPU_CPUPROCEED,
DCPU_CPUSKIP,
DCPU_CPUTRACENUM,
DCPU_CPUTRACE,
DCPU_CPUDISABLE,
DCPU_APUGROUP,
DCPU_APUSTEP,
DCPU_APUPROCEED,
DCPU_APUSKIP,
DCPU_APUTRACENUM,
DCPU_APUTRACE,
DCPU_APUDISABLE,
DCPU_SYSGROUP,
DCPU_SYSRUN,
DCPU_SYSRUNTOFRAME,
DCPU_SYSRUNTOVBLANK,
DCPU_SYSRUNTONMI,
DCPU_SYSRUNTOIRQ,
DCPU_SYSRUNTOINT,
DCPU_CFGGROUP,
DCPU_CFGCPUOUT,
DCPU_CFGAPUOUT,
DCPU_CFGDBGOUT,
DCPU_CFGTRACE,
DCPU_CFGTRACEPRINT,
DCPU_CFGREGTYPE,
DCPU_CFGREGNUM,
DCPU_CFGREGVAL,
DCPU_CFGREGSET,
DCPU_CFGLOCK,
DCPU_CFGLOCKUP,
DCPU_CFGLOCKDOWN,
DCPU_CFGLOCKLEFT,
DCPU_CFGLOCKRIGHT,
DCPU_CFGLOCKA,
DCPU_CFGLOCKB,
DCPU_CFGLOCKX,
DCPU_CFGLOCKY,
DCPU_CFGLOCKL,
DCPU_CFGLOCKR,
DCPU_CFGLOCKSELECT,
DCPU_CFGLOCKSTART,
DCPU_STATUS
};
HWND hwndDCPU;
#define DEBUG_CONSOLE_LINES 250
char dcpu_disas_mem[DEBUG_CONSOLE_LINES][256];
void debug_update_console(void) {
int i;
char str[256 * DEBUG_CONSOLE_LINES];
if(debug_write_status() == DEBUGWRITE_NONE)return;
strcpy(str, "");
for(i=0;i<DEBUG_CONSOLE_LINES;i++) {
strcat(str, dcpu_disas_mem[i]);
if(i != DEBUG_CONSOLE_LINES-1)strcat(str, "\r\n");
}
SetDlgItemText(hwndDCPU, DCPU_DISAS, str);
SendDlgItemMessage(hwndDCPU, DCPU_DISAS, EM_SETSEL, 0, -1);
SendDlgItemMessage(hwndDCPU, DCPU_DISAS, EM_SCROLLCARET, 0, 0);
}
void debug_update_status(void) {
char str[4096];
if(!(debug_write_status() & DEBUGWRITE_CONSOLE))return;
sprintf(str,
"Scanline: %3d, HCycle Pos: %4d, HDot Pos: %3d, Master Cycle Pos: %10d\r\n"
"NMI: %s, VIRQ: %s, HIRQ: %s, VIRQ Pos: %3d, HIRQ Pos: %3d\r\n"
"CPU Status: { PC:%0.6x A:%0.4x X:%0.4x Y:%0.4x S:%0.4x D:%0.4x DB:%0.2x }\r\n"
"APU Status: { PC:%0.4x A:%0.2x X:%0.2x Y:%0.2x SP:%0.2x YA:%0.4x }",
snes_time->vscan_pos, snes_time->hcycle_pos, snes_time->hscan_pos, snes_time->master_cycles,
(gx816->nmi_enabled == true)?" Enabled":"Disabled",
(ppu.vcounter_enabled == true)?" Enabled":"Disabled",
(ppu.hcounter_enabled == true)?" Enabled":"Disabled",
ppu.virq_pos, ppu.hirq_pos,
gx816->regs.pc, gx816->regs.a.w, gx816->regs.x, gx816->regs.y,
gx816->regs.s, gx816->regs.d, gx816->regs.db,
spc700->regs.pc, spc700->regs.a, spc700->regs.x, spc700->regs.y,
spc700->regs.sp, (spc700->regs.y << 8) | spc700->regs.a);
SetDlgItemText(hwndDCPU, DCPU_STATUS, str);
}
void debug_write(ulong msg_type, char *s) {
int i;
if(debugger_enabled() == false)return;
switch(msg_type) {
case DEBUGMSG_INFO:
if(debugger.output_debug_info == false)return;
break;
case DEBUGMSG_CPU:
if(debugger.output_cpu_instrs == false)return;
break;
case DEBUGMSG_APU:
if(debugger.output_apu_instrs == false)return;
break;
}
if(debugger.trace_enabled == true) {
fprintf(debugger.trace_fp, "%s\r\n", s);
}
if(debug_write_status() & DEBUGWRITE_CONSOLE) {
for(i=0;i<DEBUG_CONSOLE_LINES-1;i++)strcpy(dcpu_disas_mem[i], dcpu_disas_mem[i+1]);
strcpy(dcpu_disas_mem[DEBUG_CONSOLE_LINES - 1], s);
debug_update_console();
}
}
void dprintf(char *s, ...) {
char str[4096];
va_list args;
int i;
if(debugger_enabled() == false)return;
va_start(args, s);
vsprintf(str, s, args);
va_end(args);
debug_write(DEBUGMSG_INFO, str);
}
void dprintf(ulong msg_type, char *s, ...) {
char str[4096];
va_list args;
int i;
if(debugger_enabled() == false)return;
va_start(args, s);
vsprintf(str, s, args);
va_end(args);
debug_write(msg_type, str);
}
void debug_set_state(byte state) {
debugger.mode = state;
if(hwndDCPU && state != DEBUGMODE_DISABLED) {
if(state == DEBUGMODE_WAIT) {
SetDlgItemText(hwndDCPU, DCPU_SYSRUN, "Run");
} else if(state == DEBUGMODE_RUN) {
SetDlgItemText(hwndDCPU, DCPU_SYSRUN, "Stop");
}
}
}
long __stdcall wndprocDCPU(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
FILE *fp;
int state;
if(msg == WM_DESTROY || msg == WM_CLOSE)return 0; //don't allow debugger to be closed (yet)
if(msg == WM_COMMAND) {
switch(LOWORD(wparam)) {
case DCPU_SYSRUN:
if(debug_get_state() == DEBUGMODE_WAIT) {
debug_set_state(DEBUGMODE_RUN);
} else if(debug_get_state() == DEBUGMODE_RUN) {
debug_set_state(DEBUGMODE_WAIT);
debug_update_console();
debug_update_status();
}
break;
case DCPU_CPUSTEP:
if(debug_get_state() == DEBUGMODE_WAIT) {
debug_set_state(DEBUGMODE_CPUSTEP);
}
debugger.cpu_op_executed = false;
break;
case DCPU_APUSTEP:
if(debug_get_state() == DEBUGMODE_WAIT) {
debug_set_state(DEBUGMODE_APUSTEP);
}
debugger.apu_op_executed = false;
break;
case DCPU_CFGCPUOUT:
state = SendDlgItemMessage(hwndDCPU, DCPU_CFGCPUOUT, BM_GETCHECK, 0, 0);
debugger.output_cpu_instrs = (state == 1)?true:false;
break;
case DCPU_CFGAPUOUT:
state = SendDlgItemMessage(hwndDCPU, DCPU_CFGAPUOUT, BM_GETCHECK, 0, 0);
debugger.output_apu_instrs = (state == 1)?true:false;
break;
case DCPU_CFGDBGOUT:
state = SendDlgItemMessage(hwndDCPU, DCPU_CFGDBGOUT, BM_GETCHECK, 0, 0);
debugger.output_debug_info = (state == 1)?true:false;
break;
case DCPU_CFGTRACE:
state = SendDlgItemMessage(hwndDCPU, DCPU_CFGTRACE, BM_GETCHECK, 0, 0);
if(state == 0) {
fclose(debugger.trace_fp);
debugger.trace_enabled = false;
} else {
debugger.trace_fp = fopen("trace.log", "wb");
debugger.trace_enabled = true;
}
break;
case DCPU_CFGTRACEPRINT:
state = SendDlgItemMessage(hwndDCPU, DCPU_CFGTRACEPRINT, BM_GETCHECK, 0, 0);
debugger.trace_output_enabled = (state == 1)?true:false;
break;
case DCPU_CFGLOCKUP:
state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKUP, BM_GETCHECK, 0, 0);
debugger.lock_up = (state == 1)?true:false;
debugger.lock_down = false;
SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKDOWN, BM_SETCHECK, 0, 0);
break;
case DCPU_CFGLOCKDOWN:
state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKDOWN, BM_GETCHECK, 0, 0);
debugger.lock_down = (state == 1)?true:false;
debugger.lock_up = false;
SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKUP, BM_SETCHECK, 0, 0);
break;
case DCPU_CFGLOCKLEFT:
state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKLEFT, BM_GETCHECK, 0, 0);
debugger.lock_left = (state == 1)?true:false;
debugger.lock_right = false;
SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKRIGHT, BM_SETCHECK, 0, 0);
break;
case DCPU_CFGLOCKRIGHT:
state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKRIGHT, BM_GETCHECK, 0, 0);
debugger.lock_right = (state == 1)?true:false;
debugger.lock_left = false;
SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKLEFT, BM_SETCHECK, 0, 0);
break;
case DCPU_CFGLOCKA:
state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKA, BM_GETCHECK, 0, 0);
debugger.lock_a = (state == 1)?true:false;
break;
case DCPU_CFGLOCKB:
state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKB, BM_GETCHECK, 0, 0);
debugger.lock_b = (state == 1)?true:false;
break;
case DCPU_CFGLOCKX:
state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKX, BM_GETCHECK, 0, 0);
debugger.lock_x = (state == 1)?true:false;
break;
case DCPU_CFGLOCKY:
state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKY, BM_GETCHECK, 0, 0);
debugger.lock_y = (state == 1)?true:false;
break;
case DCPU_CFGLOCKL:
state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKL, BM_GETCHECK, 0, 0);
debugger.lock_l = (state == 1)?true:false;
break;
case DCPU_CFGLOCKR:
state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKR, BM_GETCHECK, 0, 0);
debugger.lock_r = (state == 1)?true:false;
break;
case DCPU_CFGLOCKSELECT:
state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKSELECT, BM_GETCHECK, 0, 0);
debugger.lock_select = (state == 1)?true:false;
break;
case DCPU_CFGLOCKSTART:
state = SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKSTART, BM_GETCHECK, 0, 0);
debugger.lock_start = (state == 1)?true:false;
break;
}
}
return DefWindowProc(hwnd, msg, wparam, lparam);
}
void CreateDCPU(void) {
int i;
for(i=0;i<20;i++)strcpy(dcpu_disas_mem[i], "");
CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_READONLY, 5, 5, 600, 290,
hwndDCPU, (HMENU)DCPU_DISAS, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "cpu (wdc 65816)", WS_CHILD|WS_VISIBLE|BS_GROUPBOX, 610, 5, 250, 60, hwndDCPU, (HMENU)DCPU_CPUGROUP, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Step", WS_CHILD|WS_VISIBLE, 615, 20, 80, 20, hwndDCPU, (HMENU)DCPU_CPUSTEP, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Proceed", WS_CHILD|WS_VISIBLE|WS_DISABLED, 695, 20, 80, 20, hwndDCPU, (HMENU)DCPU_CPUPROCEED, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Skip", WS_CHILD|WS_VISIBLE|WS_DISABLED, 775, 20, 80, 20, hwndDCPU, (HMENU)DCPU_CPUSKIP, GetModuleHandle(0), 0);
CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "0",
WS_CHILD|WS_VISIBLE|ES_RIGHT|WS_DISABLED, 615, 40, 80, 20, hwndDCPU, (HMENU)DCPU_CPUTRACENUM, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Trace", WS_CHILD|WS_VISIBLE|WS_DISABLED, 695, 40, 80, 20, hwndDCPU, (HMENU)DCPU_CPUTRACE, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Disable", WS_CHILD|WS_VISIBLE|WS_DISABLED, 775, 40, 80, 20, hwndDCPU, (HMENU)DCPU_CPUDISABLE, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "apu (sony spc700)", WS_CHILD|WS_VISIBLE|BS_GROUPBOX, 610, 70, 250, 60, hwndDCPU, (HMENU)DCPU_APUGROUP, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Step", WS_CHILD|WS_VISIBLE, 615, 85, 80, 20, hwndDCPU, (HMENU)DCPU_APUSTEP, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Proceed", WS_CHILD|WS_VISIBLE|WS_DISABLED, 695, 85, 80, 20, hwndDCPU, (HMENU)DCPU_APUPROCEED, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Skip", WS_CHILD|WS_VISIBLE|WS_DISABLED, 775, 85, 80, 20, hwndDCPU, (HMENU)DCPU_APUSKIP, GetModuleHandle(0), 0);
CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "0",
WS_CHILD|WS_VISIBLE|ES_RIGHT|WS_DISABLED, 615, 105, 80, 20, hwndDCPU, (HMENU)DCPU_APUTRACENUM, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Trace", WS_CHILD|WS_VISIBLE|WS_DISABLED, 695, 105, 80, 20, hwndDCPU, (HMENU)DCPU_APUTRACE, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Disable", WS_CHILD|WS_VISIBLE|WS_DISABLED, 775, 105, 80, 20, hwndDCPU, (HMENU)DCPU_APUDISABLE, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "System", WS_CHILD|WS_VISIBLE|BS_GROUPBOX, 610, 135, 250, 60, hwndDCPU, (HMENU)DCPU_SYSGROUP, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Run", WS_CHILD|WS_VISIBLE, 615, 150, 80, 20, hwndDCPU, (HMENU)DCPU_SYSRUN, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "To Frame", WS_CHILD|WS_VISIBLE|WS_DISABLED, 695, 150, 80, 20, hwndDCPU, (HMENU)DCPU_SYSRUNTOFRAME, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "To VBlank", WS_CHILD|WS_VISIBLE|WS_DISABLED, 775, 150, 80, 20, hwndDCPU, (HMENU)DCPU_SYSRUNTOVBLANK, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "To NMI", WS_CHILD|WS_VISIBLE|WS_DISABLED, 615, 170, 80, 20, hwndDCPU, (HMENU)DCPU_SYSRUNTONMI, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "To IRQ", WS_CHILD|WS_VISIBLE|WS_DISABLED, 695, 170, 80, 20, hwndDCPU, (HMENU)DCPU_SYSRUNTOIRQ, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "To Interrupt", WS_CHILD|WS_VISIBLE|WS_DISABLED, 775, 170, 80, 20, hwndDCPU, (HMENU)DCPU_SYSRUNTOINT, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Settings", WS_CHILD|WS_VISIBLE|BS_GROUPBOX, 610, 200, 250, 180, hwndDCPU, (HMENU)DCPU_CFGGROUP, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Output CPU instructions to console", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
615, 215, 240, 15, hwndDCPU, (HMENU)DCPU_CFGCPUOUT, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Output APU instructions to console", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
615, 230, 240, 15, hwndDCPU, (HMENU)DCPU_CFGAPUOUT, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Output debug info to console", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
615, 245, 240, 15, hwndDCPU, (HMENU)DCPU_CFGDBGOUT, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Trace output to file (very slow)", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
615, 260, 240, 15, hwndDCPU, (HMENU)DCPU_CFGTRACE, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Print debug info while tracing (very slow)", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
615, 275, 240, 15, hwndDCPU, (HMENU)DCPU_CFGTRACEPRINT, GetModuleHandle(0), 0);
CreateWindow("COMBOBOX", "", WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST|CBS_HASSTRINGS|WS_DISABLED,
615, 290, 60, 200, hwndDCPU, (HMENU)DCPU_CFGREGTYPE, GetModuleHandle(0), 0);
CreateWindow("COMBOBOX", "", WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST|CBS_HASSTRINGS|WS_DISABLED,
675, 290, 60, 200, hwndDCPU, (HMENU)DCPU_CFGREGNUM, GetModuleHandle(0), 0);
CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "000000", WS_CHILD|WS_VISIBLE|ES_RIGHT|WS_DISABLED,
735, 290, 60, 20, hwndDCPU, (HMENU)DCPU_CFGREGVAL, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Set Reg", WS_CHILD|WS_VISIBLE|WS_DISABLED,
795, 290, 60, 20, hwndDCPU, (HMENU)DCPU_CFGREGSET, GetModuleHandle(0), 0);
CreateWindow("STATIC", "Lock Joypad Buttons Down:", WS_CHILD|WS_VISIBLE, 615, 315, 240, 15, hwndDCPU, (HMENU)DCPU_CFGLOCK, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Up", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
615, 330, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKUP, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Down", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
675, 330, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKDOWN, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Left", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
735, 330, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKLEFT, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Right", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
795, 330, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKRIGHT, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "A", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
615, 345, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKA, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "B", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
675, 345, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKB, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "X", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
735, 345, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKX, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Y", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
795, 345, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKY, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "L", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
615, 360, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKL, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "R", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
675, 360, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKR, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Select", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
735, 360, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKSELECT, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Start", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
795, 360, 60, 15, hwndDCPU, (HMENU)DCPU_CFGLOCKSTART, GetModuleHandle(0), 0);
CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_READONLY, 5, 300, 600, 80,
hwndDCPU, (HMENU)DCPU_STATUS, GetModuleHandle(0), 0);
SendDlgItemMessage(hwndDCPU, DCPU_DISAS, WM_SETFONT, (WPARAM)hFontFixed, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CPUGROUP, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CPUSTEP, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CPUPROCEED, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CPUSKIP, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CPUTRACENUM, WM_SETFONT, (WPARAM)hFontFixed, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CPUTRACE, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CPUDISABLE, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_APUGROUP, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_APUSTEP, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_APUPROCEED, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_APUSKIP, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_APUTRACENUM, WM_SETFONT, (WPARAM)hFontFixed, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_APUTRACE, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_APUDISABLE, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_SYSGROUP, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_SYSRUN, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_SYSRUNTOFRAME, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_SYSRUNTOVBLANK, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_SYSRUNTONMI, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_SYSRUNTOIRQ, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_SYSRUNTOINT, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGGROUP, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGCPUOUT, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGAPUOUT, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGDBGOUT, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGTRACE, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGTRACEPRINT, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGREGTYPE, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGREGNUM, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGREGVAL, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGREGSET, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCK, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKUP, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKDOWN, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKLEFT, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKRIGHT, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKA, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKB, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKX, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKY, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKL, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKR, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKSELECT, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGLOCKSTART, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_STATUS, WM_SETFONT, (WPARAM)hFontFixed, TRUE);
SendDlgItemMessage(hwndDCPU, DCPU_CFGCPUOUT, BM_SETCHECK, (WPARAM)(debugger.output_cpu_instrs == true)?1:0, 0);
SendDlgItemMessage(hwndDCPU, DCPU_CFGAPUOUT, BM_SETCHECK, (WPARAM)(debugger.output_apu_instrs == true)?1:0, 0);
SendDlgItemMessage(hwndDCPU, DCPU_CFGDBGOUT, BM_SETCHECK, (WPARAM)(debugger.output_debug_info == true)?1:0, 0);
SendDlgItemMessage(hwndDCPU, DCPU_CFGTRACE, BM_SETCHECK, (WPARAM)(debugger.trace_enabled == true)?1:0, 0);
SendDlgItemMessage(hwndDCPU, DCPU_CFGTRACEPRINT, BM_SETCHECK, (WPARAM)(debugger.trace_output_enabled == true)?1:0, 0);
}
+288
View File
@@ -0,0 +1,288 @@
#define DMEM_WIDTH 500
#define DMEM_HEIGHT 268
#define DMEM_VIEW 100
#define DMEM_EDITWRAM 101
#define DMEM_UP40 102
#define DMEM_DOWN40 103
#define DMEM_UP400 104
#define DMEM_DOWN400 105
#define DMEM_UP4000 106
#define DMEM_DOWN4000 107
#define DMEM_UP40000 108
#define DMEM_DOWN40000 109
#define DMEM_TOWRAM 110
#define DMEM_TOROM 111
#define DMEM_TOVRAM 112
#define DMEM_TOCGRAM 113
#define DMEM_TOSRAM 114
#define DMEM_TOSPCRAM 115
#define DMEM_TOOAM 116
#define DMEM_TOOFFSET 117
#define DMEM_EDITLOC 118
#define DMEM_EDITVAL 119
#define DMEM_STATIC1 120
#define DMEM_STATIC2 121
#define DMEM_VIEWMODE 122
#define DMEM_GOTOADDR 123
#define DMEM_GOTO 124
#define DMEMMODE_WRAM 0
#define DMEMMODE_VRAM 1
#define DMEMMODE_CGRAM 2
#define DMEMMODE_OAM 3
#define DMEMMODE_SPCRAM 4
ulong dmem_mode = DMEMMODE_WRAM;
HWND hwndDMEM;
void debug_refresh_mem(void) {
char str[64*16], t[16];
ulong ptr;
int x, y;
if(debugger_enabled() == false)return;
ptr = debugger.mem_ptr;
strcpy(str, "");
if(dmem_mode == DMEMMODE_WRAM) {
ptr &= 0xffffff;
for(y=0;y<16;y++) {
sprintf(t, "%0.6x: ", ptr);
strcat(str, t);
for(x=0;x<16;x++) {
sprintf(t, "%0.2x", gx816->mem_read(MEMMODE_LONG, MEMSIZE_BYTE, ptr++, MEMACCESS_DEBUGGER));
ptr &= 0xffffff;
strcat(str, t);
if(x != 15)strcat(str, " ");
}
if(y != 15)strcat(str, "\r\n");
}
} else if(dmem_mode == DMEMMODE_VRAM) {
ptr &= 0xffff;
for(y=0;y<16;y++) {
sprintf(t, "--%0.4x: ", ptr);
strcat(str, t);
for(x=0;x<16;x++) {
sprintf(t, "%0.2x", ppu.vram[ptr++]);
ptr &= 0xffff;
strcat(str, t);
if(x != 15)strcat(str, " ");
}
if(y != 15)strcat(str, "\r\n");
}
} else if(dmem_mode == DMEMMODE_CGRAM) {
ptr &= 0x01ff;
for(y=0;y<16;y++) {
sprintf(t, "---%0.3x: ", ptr);
strcat(str, t);
for(x=0;x<16;x++) {
sprintf(t, "%0.2x", ppu.cgram[ptr++]);
ptr &= 0x01ff;
strcat(str, t);
if(x != 15)strcat(str, " ");
}
if(y != 15)strcat(str, "\r\n");
}
} else if(dmem_mode == DMEMMODE_OAM) {
ptr &= 0x03ff;
for(y=0;y<16;y++) {
sprintf(t, "---%0.3x: ", ptr);
strcat(str, t);
for(x=0;x<16;x++) {
sprintf(t, "%0.2x", oam_read(ptr++));
ptr &= 0x03ff;
strcat(str, t);
if(x != 15)strcat(str, " ");
}
if(y != 15)strcat(str, "\r\n");
}
} else if(dmem_mode == DMEMMODE_SPCRAM) {
ptr &= 0xffff;
for(y=0;y<16;y++) {
sprintf(t, "--%0.4x: ", ptr);
strcat(str, t);
for(x=0;x<16;x++) {
sprintf(t, "%0.2x", spc700->ram[ptr++]);
ptr &= 0xffff;
strcat(str, t);
if(x != 15)strcat(str, " ");
}
if(y != 15)strcat(str, "\r\n");
}
}
SetDlgItemText(hwndDMEM, DMEM_VIEW, str);
}
void __mask_mem_ptr(void) {
if(dmem_mode == DMEMMODE_WRAM )debugger.mem_ptr &= 0xffffff;
if(dmem_mode == DMEMMODE_VRAM )debugger.mem_ptr &= 0x00ffff;
if(dmem_mode == DMEMMODE_CGRAM )debugger.mem_ptr &= 0x0001ff;
if(dmem_mode == DMEMMODE_OAM )debugger.mem_ptr &= 0x0003ff;
if(dmem_mode == DMEMMODE_SPCRAM)debugger.mem_ptr &= 0x00ffff;
}
long __stdcall wndprocDMEM(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
char str[256];
ulong pos, val;
if(msg == WM_DESTROY || msg == WM_CLOSE) {
return 0; //don't allow debugger to be closed (yet)
}
if(emu_state.rom_loaded == false) {
return DefWindowProc(hwnd, msg, wparam, lparam);
}
if(msg == WM_COMMAND) {
switch(LOWORD(wparam)) {
case DMEM_EDITWRAM:
GetDlgItemText(hwndDMEM, DMEM_EDITLOC, str, 255);
pos = strhex(str);
GetDlgItemText(hwndDMEM, DMEM_EDITVAL, str, 255);
val = strhex(str);
if(dmem_mode == DMEMMODE_WRAM) {
gx816->mem_write(MEMMODE_LONG, MEMSIZE_BYTE, pos & 0xffffff, val, MEMACCESS_DEBUGGER);
} else if(dmem_mode == DMEMMODE_VRAM) {
ppu.vram[pos & 0xffff] = val;
} else if(dmem_mode == DMEMMODE_CGRAM) {
ppu.cgram[pos & 0x01ff] = val;
} else if(dmem_mode == DMEMMODE_OAM) {
oam_write(pos, val);
} else if(dmem_mode == DMEMMODE_SPCRAM) {
spc700->ram[pos & 0xffff] = val;
}
debug_refresh_mem();
break;
case DMEM_UP40:
debugger.mem_ptr -= 0x40;
debug_refresh_mem();
__mask_mem_ptr();
break;
case DMEM_DOWN40:
debugger.mem_ptr += 0x40;
debug_refresh_mem();
__mask_mem_ptr();
break;
case DMEM_UP400:
debugger.mem_ptr -= 0x400;
debug_refresh_mem();
__mask_mem_ptr();
break;
case DMEM_DOWN400:
debugger.mem_ptr += 0x400;
debug_refresh_mem();
__mask_mem_ptr();
break;
case DMEM_UP4000:
debugger.mem_ptr -= 0x4000;
debug_refresh_mem();
__mask_mem_ptr();
break;
case DMEM_DOWN4000:
debugger.mem_ptr += 0x4000;
debug_refresh_mem();
__mask_mem_ptr();
break;
case DMEM_UP40000:
debugger.mem_ptr -= 0x40000;
debug_refresh_mem();
__mask_mem_ptr();
break;
case DMEM_DOWN40000:
debugger.mem_ptr += 0x40000;
debug_refresh_mem();
__mask_mem_ptr();
break;
case DMEM_VIEWMODE:
if(HIWORD(wparam) == CBN_SELCHANGE) {
pos = SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_GETCURSEL, 0, 0);
if(pos == 0) {
dmem_mode = DMEMMODE_WRAM;
debugger.mem_ptr = 0x7e0000;
} else if(pos == 1) {
dmem_mode = DMEMMODE_WRAM;
if (gx816->map == MEMMAP_LOROM)debugger.mem_ptr = 0x008000;
else if(gx816->map == MEMMAP_HIROM)debugger.mem_ptr = 0xc00000;
} else if(pos == 2) {
dmem_mode = DMEMMODE_WRAM;
if (gx816->map == MEMMAP_LOROM)debugger.mem_ptr = 0x306000;
else if(gx816->map == MEMMAP_HIROM)debugger.mem_ptr = 0x700000;
} else if(pos == 3) {
dmem_mode = DMEMMODE_VRAM;
debugger.mem_ptr = 0x0000;
} else if(pos == 4) {
dmem_mode = DMEMMODE_CGRAM;
debugger.mem_ptr = 0x0000;
} else if(pos == 5) {
dmem_mode = DMEMMODE_OAM;
debugger.mem_ptr = 0x0000;
} else if(pos == 6) {
dmem_mode = DMEMMODE_SPCRAM;
debugger.mem_ptr = 0x0000;
}
debug_refresh_mem();
}
break;
case DMEM_GOTO:
GetDlgItemText(hwndDMEM, DMEM_GOTOADDR, str, 255);
debugger.mem_ptr = strhex(str);
__mask_mem_ptr();
debug_refresh_mem();
break;
}
}
return DefWindowProc(hwnd, msg, wparam, lparam);
}
void CreateDMEM(void) {
CreateWindow("COMBOBOX", "",
WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST|CBS_HASSTRINGS,
5, 5, 200, 200, hwndDMEM, (HMENU)DMEM_VIEWMODE, GetModuleHandle(0), 0);
CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "000000", WS_CHILD|WS_VISIBLE, 210, 5, 60, 21, hwndDMEM, (HMENU)DMEM_GOTOADDR, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Goto", WS_CHILD|WS_VISIBLE, 270, 5, 50, 20, hwndDMEM, (HMENU)DMEM_GOTO, GetModuleHandle(0), 0);
CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_READONLY,
5, 30, 395, 233, hwndDMEM, (HMENU)DMEM_VIEW, GetModuleHandle(0), 0);
CreateWindow("STATIC", "Offset: Val:", WS_CHILD|WS_VISIBLE, 405, 15, 100, 15, hwndDMEM, (HMENU)DMEM_STATIC1, GetModuleHandle(0), 0);
CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "000000", WS_CHILD|WS_VISIBLE, 405, 30, 60, 23, hwndDMEM, (HMENU)DMEM_EDITLOC, GetModuleHandle(0), 0);
CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "00", WS_CHILD|WS_VISIBLE, 465, 30, 30, 23, hwndDMEM, (HMENU)DMEM_EDITVAL, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "Edit Memory", WS_CHILD|WS_VISIBLE, 405, 55, 90, 20, hwndDMEM, (HMENU)DMEM_EDITWRAM, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "-40", WS_CHILD|WS_VISIBLE, 405, 80, 45, 20, hwndDMEM, (HMENU)DMEM_UP40, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "+40", WS_CHILD|WS_VISIBLE, 450, 80, 45, 20, hwndDMEM, (HMENU)DMEM_DOWN40, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "-400", WS_CHILD|WS_VISIBLE, 405, 100, 45, 20, hwndDMEM, (HMENU)DMEM_UP400, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "+400", WS_CHILD|WS_VISIBLE, 450, 100, 45, 20, hwndDMEM, (HMENU)DMEM_DOWN400, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "-4000", WS_CHILD|WS_VISIBLE, 405, 120, 45, 20, hwndDMEM, (HMENU)DMEM_UP4000, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "+4000", WS_CHILD|WS_VISIBLE, 450, 120, 45, 20, hwndDMEM, (HMENU)DMEM_DOWN4000, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "-40000", WS_CHILD|WS_VISIBLE, 405, 140, 45, 20, hwndDMEM, (HMENU)DMEM_UP40000, GetModuleHandle(0), 0);
CreateWindow("BUTTON", "+40000", WS_CHILD|WS_VISIBLE, 450, 140, 45, 20, hwndDMEM, (HMENU)DMEM_DOWN40000, GetModuleHandle(0), 0);
SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_ADDSTRING, 0, (LPARAM)"DRAM [7e0000-7fffff]");
SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_ADDSTRING, 0, (LPARAM)"ROM [008000/c00000]");
SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_ADDSTRING, 0, (LPARAM)"SRAM [306000/700000]");
SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_ADDSTRING, 0, (LPARAM)"VRAM [0000-ffff]");
SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_ADDSTRING, 0, (LPARAM)"CGRAM [0000-01ff]");
SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_ADDSTRING, 0, (LPARAM)"OAM [0000-03ff]");
SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_ADDSTRING, 0, (LPARAM)"SPCRAM [0000-ffff]");
SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, CB_SETCURSEL, 0, 0);
SendDlgItemMessage(hwndDMEM, DMEM_GOTOADDR, WM_SETFONT, (WPARAM)hFontFixed, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_VIEW, WM_SETFONT, (WPARAM)hFontFixed, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_EDITLOC, WM_SETFONT, (WPARAM)hFontFixed, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_EDITVAL, WM_SETFONT, (WPARAM)hFontFixed, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_GOTO, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_STATIC1, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_EDITWRAM, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_UP40, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_DOWN40, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_UP400, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_DOWN400, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_UP4000, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_DOWN4000, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_UP40000, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_DOWN40000, WM_SETFONT, (WPARAM)hFont, TRUE);
SendDlgItemMessage(hwndDMEM, DMEM_VIEWMODE, WM_SETFONT, (WPARAM)hFontFixed, TRUE);
}
+213
View File
@@ -0,0 +1,213 @@
#include <ddraw.h>
LPDIRECTDRAW lpdd = 0;
LPDIRECTDRAWSURFACE lpdds = 0, lpddsb = 0;
LPDIRECTDRAWCLIPPER lpddc = 0;
DDSURFACEDESC ddsd;
DDSCAPS ddscaps;
void DestroyDDraw(void) {
if(lpddc) {
lpddc->Release();
lpddc = 0;
}
if(lpddsb) {
lpddsb->Release();
lpddsb = 0;
}
if(lpdds) {
lpdds->Release();
lpdds = 0;
}
if(lpdd) {
lpdd->Release();
lpdd = 0;
}
}
void CreateDDraw_Win(void) {
DestroyDDraw();
DirectDrawCreate(0, &lpdd, 0);
lpdd->SetCooperativeLevel(hwndMain, DDSCL_NORMAL);
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
lpdd->CreateSurface(&ddsd, &lpdds, 0);
lpdd->CreateClipper(0, &lpddc, 0);
lpddc->SetHWnd(0, hwndMain);
lpdds->SetClipper(lpddc);
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
ddsd.dwWidth = 512;
ddsd.dwHeight = 478;
lpdd->CreateSurface(&ddsd, &lpddsb, 0);
}
void CreateDDraw_Full(void) {
DestroyDDraw();
DirectDrawCreate(0, &lpdd, 0);
lpdd->SetCooperativeLevel(hwndMain, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
lpdd->SetDisplayMode(640, 480, 16);
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
lpdd->CreateSurface(&ddsd, &lpdds, 0);
lpdd->CreateClipper(0, &lpddc, 0);
lpddc->SetHWnd(0, hwndMain);
lpdds->SetClipper(lpddc);
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
ddsd.dwWidth = 512;
ddsd.dwHeight = 478;
lpdd->CreateSurface(&ddsd, &lpddsb, 0);
}
void InitDisplay(void) {
CreateDDraw_Win();
}
//size is doubled (mirrored) to prevent having to mask the top unused bit of snes color data
ulong render_color_lookup[65536];
void InitColorTable16(void) {
int i, r, g, b;
for(i=0;i<65536;i++) {
r = (i ) & 31;
g = (i >> 5) & 31;
b = (i >> 10) & 31;
render_color_lookup[i] = (r << 11) | (g << 6) | (b);
}
}
void InitColorTable24(void) {
int i, r, g, b;
for(i=0;i<65536;i++) {
r = (i ) & 31;
g = (i >> 5) & 31;
b = (i >> 10) & 31;
render_color_lookup[i] = (r << 19) | (g << 11) | (b << 3);
}
}
vfunc RenderScene;
#include "render_modes.cpp"
//sets up color table and sets render proc
void CreateColorTable(void) {
lpdds->GetSurfaceDesc(&ddsd);
switch(ddsd.ddpfPixelFormat.dwRGBBitCount) {
case 16:
InitColorTable16();
RenderScene = RenderScene16;
break;
case 32:
InitColorTable24();
RenderScene = RenderScene32;
break;
default:
alert("Error: Bit depth [%d] unsupported (supported depths: 16, 32)", ddsd.ddpfPixelFormat.dwRGBBitCount);
exit(0);
break;
}
}
void DrawScene(void) {
RECT rsrc, rdest;
POINT p;
HRESULT hr;
p.x = p.y = 0;
if(render.fullscreen == true) {
SetRect(&rdest, 0, 0, 512, 448);
OffsetRect(&rdest, (640 - 512) / 2, (480 - 448) / 2);
} else {
ClientToScreen(hwndMain, &p);
GetClientRect(hwndMain, &rdest);
OffsetRect(&rdest, p.x, p.y);
}
if(ppu.overscan == false) {
SetRect(&rsrc, 0, 2, 512, 448);
} else {
SetRect(&rsrc, 0, 2 + 15, 512, 448 + 15);
}
hr = lpdds->Blt(&rdest, lpddsb, &rsrc, DDBLT_WAIT, 0);
if(hr == DDERR_SURFACELOST) {
lpdds->Restore();
lpddsb->Restore();
}
}
void UpdateDisplay(void) {
RenderScene();
DrawScene();
}
void video_setmode(bool fullscreen, word width, word height) {
bool prev_mode = render.fullscreen;
if(debug_get_state() != DEBUGMODE_DISABLED)return;
render.fullscreen = fullscreen;
render.display_width = width;
render.display_height = height;
//remove top scanline that is not rendered
if (height == 224)height = 223;
else if(height == 239)height = 238;
else if(height == 448)height = 446;
else if(height == 478)height = 476;
FixWindowSize(hwndMain, width, height);
ShowWindow(hwndMain, SW_NORMAL);
if(prev_mode != fullscreen) {
if(fullscreen == true) {
render.show_menu = false;
UpdateMainWindowStyle(true);
CreateDDraw_Full();
ShowWindow(hwndMain, SW_NORMAL);
} else {
render.show_menu = true;
UpdateMainWindowStyle(true);
CreateDDraw_Win();
FixWindowSize(hwndMain, width, height);
ShowWindow(hwndMain, SW_NORMAL);
}
CreateColorTable();
}
}
void video_setsnesmode(void) {
if(ppu.bg_mode == 5 || ppu.bg_mode == 6) {
render.snes_width = 512;
} else {
render.snes_width = 256;
}
if(ppu.interlace == false) {
if(ppu.overscan == false) {
render.snes_height = 224;
} else {
render.snes_height = 239;
}
} else {
if(ppu.overscan == false) {
render.snes_height = 448;
} else {
render.snes_height = 478;
}
}
}
+84
View File
@@ -0,0 +1,84 @@
void RenderScene16(void) {
HRESULT hr;
hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0);
if(hr != DD_OK)return;
__asm {
mov edi,ddsd.lpSurface
mov edx,ddsd.lPitch
add edi,edx
add edi,edx
sub edx,1024
mov esi,ppu.screen
add esi,2048
mov ebx,478-2
xor eax,eax
loop_y:
mov ecx,512
loop_x:
lodsw
mov eax,dword ptr[render_color_lookup+eax*4]
stosw
dec ecx
jnz loop_x
add edi,edx
dec ebx
jnz loop_y
}
/*
word *screen, *src;
word pitch;
int x, y;
pitch = ddsd.lPitch >> 1;
for(y=2;y<478;y++) {
screen = (word*)ddsd.lpSurface + (pitch * y);
src = (word*)ppu.screen + y * 512;
for(x=0;x<512;x++) {
*screen++ = render_color_lookup[*src++];
}
}
*/
lpddsb->Unlock(0);
}
void RenderScene32(void) {
HRESULT hr;
hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0);
if(hr != DD_OK)return;
__asm {
mov edi,ddsd.lpSurface
mov edx,ddsd.lPitch
add edi,edx
add edi,edx
sub edx,2048
mov esi,ppu.screen
add esi,2048
mov ebx,478-2
loop_y:
mov ecx,512
loop_x:
lodsw
and eax,0xffff
mov eax,dword ptr[render_color_lookup+eax*4]
stosd
dec ecx
jnz loop_x
add edi,edx
dec ebx
jnz loop_y
}
/*
ulong *screen;
word *src;
word pitch;
int x, y;
pitch = ddsd.lPitch >> 2;
for(y=2;y<478;y++) {
screen = (ulong*)ddsd.lpSurface + (pitch * y);
src = (word*)ppu.screen + y * 512;
for(x=0;x<512;x++) {
*screen++ = render_color_lookup[*src++];
}
}
*/
lpddsb->Unlock(0);
}
-59
View File
@@ -1,59 +0,0 @@
name := genius
build := stable
flags += -I..
nall.path := ../nall
include $(nall.path)/GNUmakefile
hiro.path := ../hiro
hiro.resource := data/$(name).rc
include $(hiro.path)/GNUmakefile
objects := obj/genius.o
obj/genius.o: genius.cpp
all: $(hiro.objects) $(objects)
$(info Linking out/$(name) ...)
+@$(compiler) -o out/$(name) $(hiro.objects) $(objects) $(hiro.options) $(options)
ifeq ($(platform),macos)
rm -rf out/$(name).app
mkdir -p out/$(name).app/Contents/MacOS/
mkdir -p out/$(name).app/Contents/Resources/
mv out/$(name) out/$(name).app/Contents/MacOS/$(name)
cp data/$(name).plist out/$(name).app/Contents/Info.plist
sips -s format icns data/$(name).png --out out/$(name).app/Contents/Resources/$(name).icns
endif
verbose: hiro.verbose nall.verbose all;
clean:
ifeq ($(platform),macos)
rm -rf out/$(name).app
endif
$(call delete,obj/*)
$(call delete,out/*)
install: all
ifeq ($(platform),macos)
cp -R out/$(name).app /Applications/$(name).app
else ifneq ($(filter $(platform),linux bsd),)
mkdir -p $(prefix)/bin/
mkdir -p $(prefix)/share/applications/
mkdir -p $(prefix)/share/icons/
mkdir -p $(prefix)/share/$(name)/
cp out/$(name) $(prefix)/bin/$(name)
cp data/$(name).desktop $(prefix)/share/applications/$(name).desktop
cp data/$(name).png $(prefix)/share/icons/$(name).png
endif
uninstall:
ifeq ($(platform),macos)
rm -rf /Applications/$(name).app
else ifneq ($(filter $(platform),linux bsd),)
rm -f $(prefix)/bin/$(name)
rm -f $(prefix)/share/applications/$(name).desktop
rm -f $(prefix)/share/icons/$(name).png
endif
-include obj/*.d
-15
View File
@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="genius" version="1.0.0.0" processorArchitecture="*"/>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
</dependentAssembly>
</dependency>
<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<asmv3:windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
-8
View File
@@ -1,8 +0,0 @@
[Desktop Entry]
Name=genius
Comment=Emulator
Exec=genius
Icon=genius
Terminal=false
Type=Application
Categories=Game;Emulator;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

-18
View File
@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>org.byuu.genius</string>
<key>CFBundleDisplayName</key>
<string>genius</string>
<key>CFBundleExecutable</key>
<string>genius</string>
<key>CFBundleIconFile</key>
<string>genius.icns</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>NSSupportsAutomaticGraphicsSwitching</key>
<true/>
</dict>
</plist>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

-2
View File
@@ -1,2 +0,0 @@
1 24 "genius.Manifest"
2 ICON DISCARDABLE "genius.ico"
-80
View File
@@ -1,80 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="256mm"
height="256mm"
viewBox="0 0 256 256"
version="1.1"
id="svg8"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="icarus.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.5"
inkscape:cx="62.34093"
inkscape:cy="560"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1028"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-41)">
<circle
id="path10"
cx="128.0"
cy="169.0"
r="120.0"
style="stroke-width:0.25;fill:#b8b8ff;fill-opacity:1" />
<g
aria-label="氷"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:260.07336426px;line-height:1.25;font-family:KaiTi;-inkscape-font-specification:KaiTi;letter-spacing:0px;word-spacing:0px;fill:#4050e0;fill-opacity:1;stroke:#4050e0;stroke-width:6;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="text818">
<path
style="fill:#4050e0;fill-opacity:1;stroke:#4050e0;stroke-width:6;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 130.80961,146.24049 q 5.07956,5.07956 14.22276,15.23868 14.22277,-13.20685 25.39779,-27.42962 12.19094,-15.23867 11.17503,-24.38187 0,-10.15912 10.15912,-4.06365 10.15911,6.09547 14.22276,12.19094 4.06364,5.07956 -2.03182,7.11138 -6.09547,1.01591 -22.35006,14.22276 -15.23867,12.19094 -32.50917,26.4137 13.20685,11.17503 23.36597,20.31823 11.17502,9.14321 24.38187,18.28641 14.22277,8.1273 27.42962,14.22276 14.22276,5.07956 21.33414,7.11139 7.11138,2.03182 -3.04773,5.07955 -9.14321,2.03183 -23.36597,3.04774 -14.22276,0 -21.33414,-2.03182 -6.09547,-3.04774 -11.17503,-8.1273 -4.06365,-5.07956 -24.38188,-27.42961 -19.30232,-23.36597 -31.49326,-39.62055 1.01591,41.65237 2.03182,64.00243 2.03183,22.35005 0,34.54099 -2.03182,12.19094 -8.12729,19.30232 -5.07956,7.11138 -8.12729,4.06365 -2.03182,-2.03183 -7.11138,-11.17503 -5.07956,-8.12729 -16.254587,-15.23867 -11.175027,-8.1273 1.015912,-5.07956 12.190935,2.03182 16.254585,2.03182 4.06365,-1.01591 6.09547,-7.11138 2.03182,-7.11138 2.03182,-46.73193 0,-40.63646 -1.01591,-77.20928 -1.01591,-37.58873 -6.09547,-45.716022 -5.07956,-9.143205 4.06365,-7.111382 10.15911,1.015912 16.25458,5.079558 7.11138,3.047735 4.06365,9.143205 -3.04774,5.079557 -4.06365,15.238673 -1.01591,10.159118 -1.01591,51.811488 z"
id="path822" />
<path
style="fill:#4050e0;fill-opacity:1;stroke:#4050e0;stroke-width:6;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 88.141325,149.28823 q 5.079558,1.01591 14.222765,7.11138 9.1432,6.09547 4.06364,10.15911 -5.07955,4.06365 -12.190935,18.28641 -6.09547,14.22276 -14.222763,25.39779 -8.127292,10.15912 -19.30232,19.30232 -11.175027,8.12729 -21.334143,12.19094 -9.143204,3.04774 -16.254585,5.07956 -6.095469,1.01591 5.079558,-6.09547 11.175027,-7.11138 21.334143,-17.2705 11.175027,-10.15911 18.286408,-21.33414 8.127293,-12.19094 11.175028,-20.31823 3.047735,-9.14321 3.047735,-14.22276 1.015911,-5.07956 -3.047735,-5.07956 -4.063646,0 -15.238674,4.06364 -10.159116,4.06365 -15.238674,6.09547 -4.063646,2.03183 -13.20685,-3.04773 -8.127293,-6.09547 2.031823,-6.09547 11.175027,-1.01591 24.381878,-5.07956 14.222762,-5.07956 17.270497,-7.11138 4.063646,-3.04773 9.143204,-2.03182 z"
id="path820" />
<path
style="fill:#4050e0;fill-opacity:1;stroke:#4050e0;stroke-width:6;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 63.759447,101.54038 q 9.143204,1.01591 18.286409,5.07956 9.143204,4.06365 11.175027,11.17503 2.031823,7.11138 -1.015912,11.17503 -3.047734,4.06364 -15.238673,-4.06365 -11.175028,-9.1432 -16.254586,-16.25459 -5.079557,-8.12729 3.047735,-7.11138 z"
id="path815" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.9 KiB

-628
View File
@@ -1,628 +0,0 @@
#include <nall/nall.hpp>
using namespace nall;
#include <hiro/hiro.hpp>
using namespace hiro;
#include "genius.hpp"
namespace Instances {
Instance<ListWindow> listWindow;
Instance<GameWindow> gameWindow;
Instance<MemoryWindow> memoryWindow;
Instance<OscillatorWindow> oscillatorWindow;
}
ListWindow& listWindow = Instances::listWindow();
GameWindow& gameWindow = Instances::gameWindow();
MemoryWindow& memoryWindow = Instances::memoryWindow();
OscillatorWindow& oscillatorWindow = Instances::oscillatorWindow();
//
ListWindow::ListWindow() {
fileMenu.setText("File");
newAction.setText("New").onActivate([&] { newDatabase(); });
openAction.setText("Open ...").onActivate([&] {
if(auto location = BrowserDialog().setAlignment(*this).setFilters({"*.bml"}).openFile()) {
loadDatabase(location);
}
});
saveAction.setText("Save").onActivate([&] {
if(!location) return saveAsAction.doActivate();
saveDatabase(location);
});
saveAsAction.setText("Save As ...").onActivate([&] {
if(auto location = BrowserDialog().setAlignment(*this).setFilters({"*.bml"}).saveFile()) {
saveDatabase(location);
}
});
quitAction.setText("Quit").onActivate([&] { quit(); });
helpMenu.setText("Help");
aboutAction.setText("About ...").onActivate([&] {
AboutDialog()
.setName("genius")
.setVersion("1")
.setCopyright("byuu")
.setLicense("GPLv3")
.setWebsite("https://byuu.org")
.setAlignment(*this)
.show();
});
layout.setPadding(5);
gameList.setHeadered();
gameList.onActivate([&](auto cell) { modifyButton.doActivate(); });
gameList.onChange([&] { updateWindow(); });
appendButton.setText("Append").onActivate([&] {
setEnabled(false);
gameWindow.show();
});
modifyButton.setText("Modify").onActivate([&] {
if(auto item = gameList.selected()) {
setEnabled(false);
gameWindow.show(games[item.offset()]);
}
});
removeButton.setText("Remove").onActivate([&] { removeGame(); });
onClose([&] { quit(); });
setSize({820, 600});
reloadList();
updateWindow();
setAlignment(Alignment::Center);
}
auto ListWindow::quit() -> void {
if(!modified || MessageDialog().setAlignment(*this).setText({
"Are you sure you want to quit without saving your changes?"
}).question() == "Yes") {
Application::quit();
}
}
auto ListWindow::reloadList() -> void {
gameList.reset();
gameList.append(TableViewColumn().setText("Name").setExpandable());
gameList.append(TableViewColumn().setText("Region"));
gameList.append(TableViewColumn().setText("Revision"));
gameList.append(TableViewColumn().setText("Board"));
for(auto& game : games) {
TableViewItem item{&gameList};
item.append(TableViewCell().setText(game.name));
item.append(TableViewCell().setText(game.region));
item.append(TableViewCell().setText(game.revision));
item.append(TableViewCell().setText(game.board));
}
Application::processEvents();
gameList.resizeColumns();
}
auto ListWindow::updateWindow() -> void {
modifyButton.setEnabled((bool)gameList.selected());
removeButton.setEnabled((bool)gameList.selected());
string name = Location::base(location);
if(!name) name = "(Untitled)";
setTitle({modified ? "*" : "", name, " [", games.size(), "] - genius"});
}
auto ListWindow::newDatabase() -> void {
games.reset();
modified = false;
location = "";
reloadList();
updateWindow();
}
auto ListWindow::loadDatabase(string location) -> void {
auto document = BML::unserialize(string::read(location));
games.reset();
for(auto node : document.find("game")) {
Game game;
game.sha256 = node["sha256"].text();
game.label = node["label"].text();
game.name = node["name"].text();
game.region = node["region"].text();
game.revision = node["revision"].text();
game.board = node["board"].text();
for(auto object : node["board"]) {
Component component;
if(object.name() == "memory") {
component.type = Component::Type::Memory;
component.memory.type = object["type"].text();
component.memory.size = object["size"].text();
component.memory.content = object["content"].text();
component.memory.manufacturer = object["manufacturer"].text();
component.memory.architecture = object["architecture"].text();
component.memory.identifier = object["identifier"].text();
component.memory.Volatile = (bool)object["volatile"];
}
if(object.name() == "oscillator") {
component.type = Component::Type::Oscillator;
component.oscillator.frequency = object["frequency"].text();
}
game.components.append(component);
}
game.note = node["note"].text();
games.append(game);
}
modified = false;
this->location = location;
reloadList();
updateWindow();
}
auto ListWindow::saveDatabase(string location) -> void {
auto fp = file::open(location, file::mode::write);
if(!fp) return MessageDialog().setAlignment(*this).setText({
"Error: failed to write file.\n\n",
"Name: ", location
}).error(), void();
auto copy = games;
copy.sort([](auto x, auto y) {
return string::icompare(
{x.name, "\n", x.region, "\n", x.revision},
{y.name, "\n", y.region, "\n", y.revision}
) < 0;
});
fp.print("database\n");
fp.print(" revision: ", chrono::local::date(), "\n\n");
for(auto& game : copy) {
fp.print("game\n");
fp.print(" sha256: ", game.sha256, "\n");
if(game.label)
fp.print(" label: ", game.label, "\n");
fp.print(" name: ", game.name, "\n");
fp.print(" region: ", game.region, "\n");
fp.print(" revision: ", game.revision, "\n");
if(game.board)
fp.print(" board: ", game.board, "\n");
else if(game.components)
fp.print(" board\n");
for(auto& component : game.components) {
if(component.type == Component::Type::Memory) {
fp.print(" memory\n");
fp.print(" type: ", component.memory.type, "\n");
fp.print(" size: ", component.memory.size, "\n");
fp.print(" content: ", component.memory.content, "\n");
if(component.memory.manufacturer)
fp.print(" manufacturer: ", component.memory.manufacturer, "\n");
if(component.memory.architecture)
fp.print(" architecture: ", component.memory.architecture, "\n");
if(component.memory.identifier)
fp.print(" identifier: ", component.memory.identifier, "\n");
if(component.memory.Volatile)
fp.print(" volatile\n");
}
if(component.type == Component::Type::Oscillator) {
fp.print(" oscillator\n");
fp.print(" frequency: ", component.oscillator.frequency, "\n");
}
}
if(game.note)
fp.print(" note: ", game.note, "\n");
fp.print("\n");
}
modified = false;
this->location = location;
updateWindow();
}
auto ListWindow::appendGame(Game game) -> void {
modified = true;
auto offset = games.size();
games.append(game);
reloadList();
gameList.item(offset).setSelected().setFocused();
updateWindow();
}
auto ListWindow::modifyGame(Game game) -> void {
if(auto item = gameList.selected()) {
modified = true;
auto offset = item.offset();
games[offset] = game;
reloadList();
gameList.item(offset).setSelected().setFocused();
updateWindow();
}
}
auto ListWindow::removeGame() -> void {
if(auto item = gameList.selected()) {
if(MessageDialog().setAlignment(*this).setText({
"Are you sure you want to permanently remove this game?\n\n",
"Name: ", item.cell(0).text()
}).question() == "Yes") {
modified = true;
games.remove(item.offset());
reloadList();
updateWindow();
}
}
}
//
GameWindow::GameWindow() {
layout.setPadding(5);
hashLabel.setText("SHA256:").setAlignment(1.0);
hashEdit.setFont(Font().setFamily(Font::Mono)).onChange([&] { modified = true, updateWindow(); });
regionLabel.setText("Region:").setAlignment(1.0);
regionEdit.setFont(Font().setFamily(Font::Mono)).onChange([&] { modified = true, updateWindow(); });
revisionLabel.setText("Revision:");
revisionEdit.setFont(Font().setFamily(Font::Mono)).onChange([&] { modified = true, updateWindow(); });
boardLabel.setText("Board:");
boardEdit.setFont(Font().setFamily(Font::Mono)).onChange([&] { modified = true, updateWindow(); });
nameLabel.setText("Name:").setAlignment(1.0);
nameEdit.onChange([&] { modified = true, updateWindow(); });
labelLabel.setText("Label:").setAlignment(1.0);
labelEdit.onChange([&] { modified = true, updateWindow(); });
noteLabel.setText("Note:").setAlignment(1.0);
noteEdit.onChange([&] { modified = true, updateWindow(); });
componentLabel.setText("Tree:").setAlignment({1.0, 0.0});
componentTree.onActivate([&] { modifyComponentButton.doActivate(); });
componentTree.onChange([&] { updateWindow(); });
appendMemoryButton.setText("Memory").onActivate([&] {
setEnabled(false);
memoryWindow.show();
});
appendOscillatorButton.setText("Oscillator").onActivate([&] {
setEnabled(false);
oscillatorWindow.show();
});
modifyComponentButton.setText("Modify").onActivate([&] {
if(auto item = componentTree.selected()) {
setEnabled(false);
auto path = item.path().split("/");
auto offset = path(0).natural();
Component component = game.components[offset];
if(component.type == Component::Type::Memory) {
memoryWindow.show(component.memory);
}
if(component.type == Component::Type::Oscillator) {
oscillatorWindow.show(component.oscillator);
}
}
});
removeComponentButton.setText("Remove").onActivate([&] { removeComponent(); });
acceptButton.setText("Accept").onActivate([&] { accept(); });
cancelButton.setText("Cancel").onActivate([&] { cancel(); });
onClose([&] { cancel(); });
setSize({640, 480});
setDismissable();
}
auto GameWindow::show(Game game) -> void {
this->game = game;
modified = false;
create = !game.sha256;
hashEdit.setText(game.sha256);
regionEdit.setText(game.region);
revisionEdit.setText(game.revision);
boardEdit.setText(game.board);
nameEdit.setText(game.name);
labelEdit.setText(game.label);
noteEdit.setText(game.note);
acceptButton.setText(create ? "Create" : "Apply");
reloadList();
updateWindow();
setAlignment(*listWindow);
setVisible();
if(create) {
hashEdit.setFocused();
} else {
cancelButton.setFocused();
}
}
auto GameWindow::accept() -> void {
game.sha256 = hashEdit.text().strip();
game.region = regionEdit.text().strip();
game.revision = revisionEdit.text().strip();
game.board = boardEdit.text().strip();
game.name = nameEdit.text().strip();
game.label = labelEdit.text().strip();
game.note = noteEdit.text().strip();
if(create) {
listWindow.appendGame(game);
} else {
listWindow.modifyGame(game);
}
memoryWindow.setVisible(false);
setVisible(false);
listWindow.setEnabled();
listWindow.setFocused();
}
auto GameWindow::cancel() -> void {
if(!modified || MessageDialog().setAlignment(*this).setText({
"Are you sure you want to discard your changes to this game?"
}).question() == "Yes") {
memoryWindow->setVisible(false);
setVisible(false);
listWindow->setEnabled();
listWindow->setFocused();
}
}
auto GameWindow::reloadList() -> void {
componentTree.reset();
uint counter = 1;
for(auto& component : game.components) {
TreeViewItem item;
string index = {"[", counter++, "] "};
if(component.type == Component::Type::Memory) {
item.setText({index, "Memory"});
item.append(TreeViewItem().setText({"Type: ", component.memory.type}));
item.append(TreeViewItem().setText({"Size: ", component.memory.size}));
item.append(TreeViewItem().setText({"Content: ", component.memory.content}));
if(component.memory.manufacturer)
item.append(TreeViewItem().setText({"Manufacturer: ", component.memory.manufacturer}));
if(component.memory.architecture)
item.append(TreeViewItem().setText({"Architecture: ", component.memory.architecture}));
if(component.memory.identifier)
item.append(TreeViewItem().setText({"Identifier: ", component.memory.identifier}));
if(component.memory.Volatile)
item.append(TreeViewItem().setText({"Volatile"}));
}
if(component.type == Component::Type::Oscillator) {
item.setText({index, "Oscillator"});
item.append(TreeViewItem().setText({"Frequency: ", component.oscillator.frequency}));
}
componentTree.append(item);
}
Application::processEvents();
for(auto& item : componentTree.items()) item.setExpanded();
}
auto GameWindow::updateWindow() -> void {
bool valid = true;
bool hashValid = hashEdit.text().strip().size() == 64;
hashEdit.setEditable(!hashValid).setBackgroundColor(
!create || hashValid ? Color{192, 255, 192}
: (valid = false, Color{255, 224, 224}));
regionEdit.setBackgroundColor(regionEdit.text().strip() ? Color{} : (valid = false, Color{255, 224, 224}));
revisionEdit.setBackgroundColor(revisionEdit.text().strip() ? Color{} : (valid = false, Color{255, 224, 224}));
boardEdit.setBackgroundColor(boardEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
nameEdit.setBackgroundColor(nameEdit.text().strip() ? Color{} : (valid = false, Color{255, 224, 224}));
labelEdit.setBackgroundColor(labelEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
noteEdit.setBackgroundColor(noteEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
modifyComponentButton.setEnabled((bool)componentTree.selected());
removeComponentButton.setEnabled((bool)componentTree.selected());
acceptButton.setEnabled(valid);
setTitle({modified ? "*" : "", create ? "Add New Game" : "Modify Game Details"});
if(create && hashValid && hashEdit.focused()) regionEdit.setFocused();
}
auto GameWindow::appendComponent(Component component) -> void {
modified = true;
auto offset = game.components.size();
game.components.append(component);
reloadList();
componentTree.item(offset).setSelected().setFocused();
updateWindow();
}
auto GameWindow::modifyComponent(Component component) -> void {
if(auto item = componentTree.selected()) {
modified = true;
auto path = item.path().split("/");
auto offset = path(0).natural();
game.components[offset] = component;
reloadList();
componentTree.item(offset).setSelected().setFocused();
updateWindow();
}
}
auto GameWindow::removeComponent() -> void {
if(auto item = componentTree.selected()) {
if(MessageDialog().setAlignment(*this).setText({
"Are you sure you want to permanently remove this component?"
}).question() == "Yes") {
modified = true;
auto path = item.path().split("/");
auto offset = path(0).natural();
game.components.remove(offset);
reloadList();
updateWindow();
}
}
}
//
MemoryWindow::MemoryWindow() {
layout.setPadding(5);
typeLabel.setText("Type:").setAlignment(1.0);
typeEdit.append(ComboEditItem().setText("ROM"));
typeEdit.append(ComboEditItem().setText("EEPROM"));
typeEdit.append(ComboEditItem().setText("Flash"));
typeEdit.append(ComboEditItem().setText("RAM"));
typeEdit.append(ComboEditItem().setText("RTC"));
typeEdit.onChange([&] { modified = true, updateWindow(); });
sizeLabel.setText("Size:").setAlignment(1.0);
sizeEdit.onChange([&] { modified = true, updateWindow(); });
contentLabel.setText("Content:").setAlignment(1.0);
contentEdit.append(ComboEditItem().setText("Program"));
contentEdit.append(ComboEditItem().setText("Data"));
contentEdit.append(ComboEditItem().setText("Character"));
contentEdit.append(ComboEditItem().setText("Save"));
contentEdit.append(ComboEditItem().setText("Time"));
contentEdit.onChange([&] { modified = true, updateWindow(); });
manufacturerLabel.setText("Manufacturer:").setAlignment(1.0);
manufacturerEdit.onChange([&] { modified = true, updateWindow(); });
architectureLabel.setText("Architecture:").setAlignment(1.0);
architectureEdit.onChange([&] { modified = true, updateWindow(); });
identifierLabel.setText("Identifier:").setAlignment(1.0);
identifierEdit.onChange([&] { modified = true, updateWindow(); });
volatileOption.setText("Volatile").onToggle([&] { modified = true, updateWindow(); });
acceptButton.setText("Accept").onActivate([&] { accept(); });
cancelButton.setText("Cancel").onActivate([&] { cancel(); });
onClose([&] { cancel(); });
setSize({320, layout.minimumSize().height()});
setDismissable();
}
auto MemoryWindow::show(Memory memory) -> void {
this->memory = memory;
modified = false;
create = !memory.type;
typeEdit.setText(memory.type);
sizeEdit.setText(memory.size);
contentEdit.setText(memory.content);
manufacturerEdit.setText(memory.manufacturer);
architectureEdit.setText(memory.architecture);
identifierEdit.setText(memory.identifier);
volatileOption.setChecked(memory.Volatile);
updateWindow();
setAlignment(*gameWindow);
setVisible();
typeEdit.setFocused();
}
auto MemoryWindow::accept() -> void {
memory.type = typeEdit.text().strip();
memory.size = sizeEdit.text().strip();
memory.content = contentEdit.text().strip();
memory.manufacturer = manufacturerEdit.text().strip();
memory.architecture = architectureEdit.text().strip();
memory.identifier = identifierEdit.text().strip();
memory.Volatile = volatileOption.checked() && (memory.type == "RAM" || memory.type == "RTC");
Component component{Component::Type::Memory};
component.memory = memory;
if(create) {
gameWindow.appendComponent(component);
} else {
gameWindow.modifyComponent(component);
}
setVisible(false);
gameWindow.setEnabled();
gameWindow.setFocused();
}
auto MemoryWindow::cancel() -> void {
if(!modified || MessageDialog().setAlignment(*this).setText({
"Are you sure you want to discard your changes to this memory?"
}).question() == "Yes") {
setVisible(false);
gameWindow.setEnabled();
gameWindow.setFocused();
}
}
auto MemoryWindow::updateWindow() -> void {
bool valid = true;
typeEdit.setBackgroundColor(typeEdit.text().strip() ? Color{} : (valid = false, Color{255, 224, 224}));
sizeEdit.setBackgroundColor(sizeEdit.text().strip() ? Color{} : (valid = false, Color{255, 224, 224}));
contentEdit.setBackgroundColor(contentEdit.text().strip() ? Color{} : (valid = false, Color{255, 224, 224}));
manufacturerEdit.setBackgroundColor(manufacturerEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
architectureEdit.setBackgroundColor(architectureEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
identifierEdit.setBackgroundColor(identifierEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
volatileOption.setEnabled(typeEdit.text().strip() == "RAM" || typeEdit.text().strip() == "RTC");
acceptButton.setEnabled(valid);
setTitle({modified ? "*" : "", create ? "Add New Memory" : "Modify Memory Details"});
}
//
OscillatorWindow::OscillatorWindow() {
layout.setPadding(5);
frequencyLabel.setText("Frequency:").setAlignment(1.0);
frequencyEdit.onChange([&] { modified = true, updateWindow(); });
acceptButton.setText("Accept").onActivate([&] { accept(); });
cancelButton.setText("Cancel").onActivate([&] { cancel(); });
onClose([&] { cancel(); });
setSize({320, layout.minimumSize().height()});
setDismissable();
}
auto OscillatorWindow::show(Oscillator oscillator) -> void {
this->oscillator = oscillator;
modified = false;
create = !oscillator.frequency;
frequencyEdit.setText(oscillator.frequency);
updateWindow();
setAlignment(*gameWindow);
setVisible();
frequencyEdit.setFocused();
}
auto OscillatorWindow::accept() -> void {
oscillator.frequency = frequencyEdit.text().strip();
Component component{Component::Type::Oscillator};
component.oscillator = oscillator;
if(create) {
gameWindow.appendComponent(component);
} else {
gameWindow.modifyComponent(component);
}
setVisible(false);
gameWindow->setEnabled();
gameWindow->setFocused();
}
auto OscillatorWindow::cancel() -> void {
if(!modified || MessageDialog().setAlignment(*this).setText({
"Are you sure you want to discard your changes to this property?"
}).question() == "Yes") {
setVisible(false);
gameWindow->setEnabled();
gameWindow->setFocused();
}
}
auto OscillatorWindow::updateWindow() -> void {
bool valid = true;
frequencyEdit.setBackgroundColor(frequencyEdit.text().strip() ? Color{} : (valid = false, Color{255, 224, 224}));
acceptButton.setEnabled(valid);
setTitle({modified ? "*" : "", create ? "Add New Property" : "Modify Property Details"});
}
//
#include <nall/main.hpp>
auto nall::main(Arguments) -> void {
Application::setName("genius");
Instances::listWindow.construct();
Instances::gameWindow.construct();
Instances::memoryWindow.construct();
Instances::oscillatorWindow.construct();
listWindow.setVisible();
Application::run();
}
-178
View File
@@ -1,178 +0,0 @@
struct Memory {
string type;
string size;
string content;
string manufacturer;
string architecture;
string identifier;
boolean Volatile;
};
struct Oscillator {
string frequency;
};
//variant meta-class
struct Component {
enum class Type : uint {
Memory,
Oscillator,
} type;
Memory memory;
Oscillator oscillator;
};
struct Game {
string sha256;
string region;
string revision;
string board;
string name;
string label;
string note;
vector<Component> components;
};
struct ListWindow : Window {
ListWindow();
auto quit() -> void;
auto reloadList() -> void;
auto updateWindow() -> void;
auto newDatabase() -> void;
auto loadDatabase(string) -> void;
auto saveDatabase(string) -> void;
auto appendGame(Game) -> void;
auto modifyGame(Game) -> void;
auto removeGame() -> void;
private:
bool modified = false;
vector<Game> games;
string location;
MenuBar menuBar{this};
Menu fileMenu{&menuBar};
MenuItem newAction{&fileMenu};
MenuItem openAction{&fileMenu};
MenuItem saveAction{&fileMenu};
MenuItem saveAsAction{&fileMenu};
MenuSeparator quitSeparator{&fileMenu};
MenuItem quitAction{&fileMenu};
Menu helpMenu{&menuBar};
MenuItem aboutAction{&helpMenu};
HorizontalLayout layout{this};
TableView gameList{&layout, Size{~0, ~0}};
VerticalLayout controlLayout{&layout, Size{80, ~0}};
Button appendButton{&controlLayout, Size{~0, 0}};
Button modifyButton{&controlLayout, Size{~0, 0}};
Button removeButton{&controlLayout, Size{~0, 0}};
};
struct GameWindow : Window {
GameWindow();
auto show(Game = {}) -> void;
auto accept() -> void;
auto cancel() -> void;
auto reloadList() -> void;
auto updateWindow() -> void;
auto appendComponent(Component) -> void;
auto modifyComponent(Component) -> void;
auto removeComponent() -> void;
private:
bool modified = false;
bool create = true;
Game game;
VerticalLayout layout{this};
HorizontalLayout hashLayout{&layout, Size{~0, 0}};
Label hashLabel{&hashLayout, Size{50, 0}};
LineEdit hashEdit{&hashLayout, Size{~0, 0}};
HorizontalLayout infoLayout{&layout, Size{~0, 0}};
Label regionLabel{&infoLayout, Size{50, 0}};
LineEdit regionEdit{&infoLayout, Size{~0, 0}};
Label revisionLabel{&infoLayout, Size{0, 0}};
LineEdit revisionEdit{&infoLayout, Size{~0, 0}};
Label boardLabel{&infoLayout, Size{0, 0}};
LineEdit boardEdit{&infoLayout, Size{~0, 0}, 0};
HorizontalLayout nameLayout{&layout, Size{~0, 0}};
Label nameLabel{&nameLayout, Size{50, 0}};
LineEdit nameEdit{&nameLayout, Size{~0, 0}};
HorizontalLayout labelLayout{&layout, Size{~0, 0}};
Label labelLabel{&labelLayout, Size{50, 0}};
LineEdit labelEdit{&labelLayout, Size{~0, 0}};
HorizontalLayout noteLayout{&layout, Size{~0, 0}};
Label noteLabel{&noteLayout, Size{50, 0}};
LineEdit noteEdit{&noteLayout, Size{~0, 0}};
HorizontalLayout lowerLayout{&layout, Size{~0, ~0}};
Label componentLabel{&lowerLayout, Size{50, ~0}};
TreeView componentTree{&lowerLayout, Size{~0, ~0}};
VerticalLayout controlLayout{&lowerLayout, Size{0, ~0}};
Button appendMemoryButton{&controlLayout, Size{80, 0}};
Button appendOscillatorButton{&controlLayout, Size{80, 0}};
Button modifyComponentButton{&controlLayout, Size{80, 0}};
Button removeComponentButton{&controlLayout, Size{80, 0}};
Widget controlSpacer{&controlLayout, Size{0, ~0}};
Button acceptButton{&controlLayout, Size{80, 0}};
Button cancelButton{&controlLayout, Size{80, 0}};
};
struct MemoryWindow : Window {
MemoryWindow();
auto show(Memory = {}) -> void;
auto accept() -> void;
auto cancel() -> void;
auto updateWindow() -> void;
private:
bool modified = false;
bool create = true;
Memory memory;
VerticalLayout layout{this};
HorizontalLayout infoLayout{&layout, Size{~0, 0}};
Label typeLabel{&infoLayout, Size{80, 0}};
ComboEdit typeEdit{&infoLayout, Size{~0, 0}};
Label sizeLabel{&infoLayout, Size{0, 0}};
LineEdit sizeEdit{&infoLayout, Size{~0, 0}};
HorizontalLayout contentLayout{&layout, Size{~0, 0}};
Label contentLabel{&contentLayout, Size{80, 0}};
ComboEdit contentEdit{&contentLayout, Size{~0, 0}};
HorizontalLayout manufacturerLayout{&layout, Size{~0, 0}};
Label manufacturerLabel{&manufacturerLayout, Size{80, 0}};
LineEdit manufacturerEdit{&manufacturerLayout, Size{~0, 0}};
HorizontalLayout architectureLayout{&layout, Size{~0, 0}};
Label architectureLabel{&architectureLayout, Size{80, 0}};
LineEdit architectureEdit{&architectureLayout, Size{~0, 0}};
HorizontalLayout identifierLayout{&layout, Size{~0, 0}};
Label identifierLabel{&identifierLayout, Size{80, 0}};
LineEdit identifierEdit{&identifierLayout, Size{~0, 0}};
HorizontalLayout controlLayout{&layout, Size{~0, 0}};
Widget controlSpacer{&controlLayout, Size{~0, 0}};
CheckLabel volatileOption{&controlLayout, Size{0, 0}};
Button acceptButton{&controlLayout, Size{80, 0}};
Button cancelButton{&controlLayout, Size{80, 0}};
};
struct OscillatorWindow : Window {
OscillatorWindow();
auto show(Oscillator = {}) -> void;
auto accept() -> void;
auto cancel() -> void;
auto updateWindow() -> void;
private:
bool modified = false;
bool create = true;
Oscillator oscillator;
VerticalLayout layout{this};
HorizontalLayout frequencyLayout{&layout, Size{~0, 0}};
Label frequencyLabel{&frequencyLayout, Size{60, 0}};
LineEdit frequencyEdit{&frequencyLayout, Size{~0, 0}};
HorizontalLayout controlLayout{&layout, Size{~0, 0}};
Widget controlSpacer{&controlLayout, Size{~0, 0}};
Button acceptButton{&controlLayout, Size{80, 0}};
Button cancelButton{&controlLayout, Size{80, 0}};
};
Loaded 100 of 2267 files, more files were not shown because too many files have changed in this diff. Show more