Compare commits

...
11 Commits
Author SHA1 Message Date
byuu 35fd80bde7 Update to bsnes v018 release.
I began working on bsnes on October 14th, 2004. I am releasing bsnes v0.018 today to celebrate bsnes' two year anniversary. Please note that this release incurs a ~15% speed reduction since v0.017, due to IRQ and S-SMP timing improvements.
Changelog:
    - Fixed many critical errors in IRQ timing, should be *very* close to real hardware now
    - Corrected major CPU timing bug involving CPU I/O condition 4
    - Corrected bug with generic HiROM / LoROM memory maps
    - Corrected bug involving HDMA indirect channel termination [anomie]
    - OAM address reset now occurs when screen display is enabled, per recent research
    - Readded full DMA, HDMA and HDMA init bus sync timing
    - Added preliminary emulation of S-SMP $00f0 TEST register (6 of 8 bits are supported)
    - Readded emulation of known timing differences between CPU revisions 1 and 2
    - Config file can now control scanline-based PPU render position. This will only be needed until a proper dot-based PPU renderer is added
    - Removed core debugging hooks so that debugging console can remain in public releases, it now functions as a tracer and memory editor
    - Config file paths once again work correctly even if missing trailing backslash
    - Video configuration simplified, sorry in advance to those who enjoyed the profile mode used before
    - Added new configuration screen to control some emulation settings
    - Replaced bsnes program icon with a much nicer one [FitzRoy]
    - Optimized memory speed detection algorithm
    - Preliminary UPS soft-patching support (do not use this yet!)
    - Decreased memory usage and optimized generic libraries used by bsnes (/src/lib)
    - Now caching OAM by one line, somewhat similar to a real SNES. Fixes Winter Gold, but causes line rendering error in Mega lo Mania
    - Lots more, as usual
The following games have been fixed since v0.017 by the above bugfixes:
    - Battle Blaze (J, U)
    - Circuit USA (J)
    - F1 Grand Prix (J)
    - Funaki Masakatsu no Hybrid Wrestler - Tougi Denshou (J)
    - Jumbo Ozaki no Hole in One (J)
    - Mahjongg Taikai II (J)
    - RPG Tsukuru - Super Dante (J)
    - Robocop Versus The Terminator (U, E)
    - Sink or Swim (U, E)
    - Street Racer (J)
    - Touge Densetsu Saisoku Battle (J)
    - Winter Olympics (U, E)
2006-10-14 05:34:24 +00:00
byuu ccf1c00b58 Update to bsnes v017r16? release.
Ok, reverted the SPCRAM initialization pattern, which
should fix Kamen Rider SD.
 Verified DMA timing steps, I had them right. Still need to verify
HDMA/HDMA init, but they're almost definitely the same anyway.
 Also, I noticed the spc700.txt doc by anomie on romhacking.net was
more recent than mine, and had info on $00f0 - TEST o_O
 So, went ahead and added emulation for 5 out of 8 of these bits.
Notably, the CPU speed control bits and the RAM write enable bit. The
other three aren't well understood enough to add support for them just
yet.
 Now, the CPU speed control in the S-SMP means the SMP core is taking
a significant speed hit to support this register. ~5% total speed hit,
though I can probably get that number down a little with some more
optimizations. I know the register is never used by any games, but you
know how I am. I added support for it anyway.
 Note that the WIP doesn't like my inlining combination and is taking
a much more significant speed hit with global optimizations turned on,
so the WIP is ~13% slower than the last one.







> On a side note, kernel streaming method works with event
> notification per audio packet you feed into it, and that
> notification receives full precision time slices even without
> setting the timer resolution manually. At least, when I was using
> kernel streaming in my NES emulator, it didn't need vsync to output
> almost a smooth 60fps, while WaveOut mode outputs in bursts and
> requires vsync to smooth out the frames.




 If you wouldn't mind turning that into a compatible derived Audio
class, I'd love to add this as an option into bsnes :)
 It'll be drop-in and compile, so you don't have to worry about me not
adding the code this time. No problem if you don't have the time /
desire / patience to do this.
 Although, I wouldn't want to do this if it requires 3rd-party
libraries / loading a special .sys driver into the kernel space /
Windows DDK to compile / something else crazy like that.

[No archive available]
2006-10-04 06:27:00 +00:00
byuu f4520d41ec Update to bsnes v017r06? release.
New WIP should fix: RPG Tsukuru, Circuit USA, Jumbo Ozaki no Hole in
One (not a permanent fix, I'm not entirely happy with the HDMA timing,
but at least the name entry screen works again for now), and Taz-
Mania.

 The two games you said started flickering since v0.017.07 might be
fixed now, but I'm not worried about these horizontal-line issues
regardless of when they started occurring at the moment. The other
ones you said would be fixed by setting HCLOCK=256 should be fixed as
well, as this is the new default value.

 Super Mario Kart's line doesn't appear to flicker now, but I think
it's because I'm technically running the emulation a little too fast
again, due to the Ozaki fix. Another game you shouldn't expect to stay
fixed, and again another game I'm not worried about remaining fixed.

 Koushien 2 and Mahjongg Taikai 2 are very likely still broken.
Uniracers definitely is. These appear to be the only three serious
known bugs remaining.

[No archive available]
2006-09-20 04:06:00 +00:00
byuu e308cf4275 Update to bsnes v017 release.
- This version adds major accuracy improvements, countless bugfixes and DSP-1 support. At the time of this release, the only remaining known bug in bsnes is with Uniracers 2-player mode, with well over 300+ games tested.
Changelog:
    - DSP-1 support added [Andreas Naive, byuu]
    - Added cooperative multithreading library, written by myself
    - Rewritten CPU core, now bus accurate
    - Rewritten APU core, now bus accurate
    - Added cartridge database
    - Added several PCB mappers, thanks to research from Overload
    - Added several games to database, fixing several mapping-related bugs
    - Improved mirroring [Nach, grinvader, byuu]
    - vscroll bug in hires, interlaced mode fixed. Fixes RPM racing
    - RTO X=256 bug corrected. Fixes Super Conflict title screen [anomie]
    - Fixed bug in NTSC filter with hires games
    - Updated snes_ntsc to version 2.0.1 [blargg]
    - Fixed bugs in HiROM / LoROM memory mapping. Fixes countless games
    - Fixed major bugs in HDMA routine. Fixes ToP, Mortal Kombat and Genjuu Ryodan
    - Added out-of-order execution to CPU, APU synchronization for major speedup with no accuracy loss
    - IRQs are now delayed after H/DMA transfers. Fixes Wild Guns
    - HDMA transfers now kill active DMA channels that are on the same channel. Fixes Bugs Bunny and World Class Rugby. Special thanks to zones for researching this
    - CPU emulation mode accuracy was improved
    - Cleaned up port-specific code to ease porting
    - Created unified Makefile, used by all ports [Nach]
    - Created GTK+ port of bsnes (although input is currently broken)
    - WRAM is now initialized to 0x55, SRAM to 0xff. Fixes Power Drive, Death Brade and RPM Racing
    - Fixed extreme NMI / IRQ edge case. Fixes Chou Aniki
    - Adjusted PAL execution speed. Fixes Earthworm Jim 2 (E) sound effects
    - Fixed auto joypad polling bug. Fixes La Wares
    - Fixed H/DMA bug that was preventing saves from working in Secret of Evermore
    - bsnes low loads d3dx9_*.dll dynamically at runtime, it is no longer required
    - Added support for 239-line PAL mode rendering
    - As usual, there have been much more changes I've forgotten about since the last release
    - Two C4 bugs fixed. Mega Man X2 / X3 have no remaining known bugs [anomie, byuu]
2006-08-27 03:01:06 +00:00
byuu 192e53bb87 Update to bsnes v016r52 release.
bsnes now builds with no warnings on Linux:
               http://byuu.cinnamonpirate.com/images/desktop082106.png
               However, input is not working unless you build the non-
GTK+ port (see below for more info).

 I'm planning on releasing next weekend. This will likely be the last
public WIP, unless something major is found before the weekend:
               byuu.cinnamonpirate.com/files/bsnes_v016_wip52.zip <-
copy/paste link







> If you can actually get it going fast in an all-in-one window like
> that it'd be cool. I normally just punt and have the GUI separate
> from the emulator output (GTK or Qt for the UI, SDL for the output)
> but it'd be nice for my NEStopia port if I could make it "one piece"
> like the Win32 original




 I can. Please take a look at my above sourcecode, and check your
private messages for another note. Specifically, src/ui/video/sdl.cpp
and src/ui/gtk/gtk_mainwindow.cpp. I am able to merge the SDL output
into the GTK+ window by setting the environment variable
"SDL_WINDOWID=%ld", GDK_WINDOW_XWINDOW(mydrawingbox->window).
 One important thing to note is that you must not initialize SDL video
until the render window has been realized. Simply showing the window
is not enough. You need to also clear all pending events in GTK+ after
showing the window before calling SDL video init, or it will die.
               You can do that with this code:






    gtk_widget_show(mainwindow);
                       while(gtk_events_pending() == true) {
                       gtk_main_iteration_do(false);
                       }




 However, one problem I am having is that by calling
gtk_main_iteration_do(), it steals all SDL input, and I'm not able to
poll any keypresses. This happens whether I embed the SDL video output
into the GTK+ window or not. The only way to get SDL input is to
ignore all GTK+ events, effectively freezing the window completely.

               I don't suppose you'd mind sharing how you got SDL
input working with GTK+ with me?
2006-08-21 00:43:46 +00:00
byuu 0ed9edfcdb Update to bsnes v016r46 release.
wip46 up. Adds all kinds of things, please test.

 First, no more d3dx9_27.dll requirement to run the application, but
screenshots still work if you have any d3dx9_nn.dll files.
 I specifically want to know if any of the other versions (24, 30,
etc) cause the emulator to crash when use. I'm pretty sure the
function is backwards-compatible, but we should probably make sure
before I make the next release and start getting bugreports about
screenshots crashing the program.
             Note: there is no error message for failed screen
captures, I'll add that in eventually.

 Next, the video options finally enable/disable controls depending on
certain settings. Should make using the video options a little easier.

 Next, to enable SDL audio on Windows and remove the win32 port's
wMain.hwnd reference, I now pass GetDesktopWindow() to DirectSound's
SetCooperativeLevel function, since no sound comes out if you pass a
null handle. This is because I don't know how to get the window handle
from SDL, and I prefer to keep port-specific code out of there if
possible.
             Note: SDL is not a windows port, but it builds on
windows, and thus needs DirectSound to output audio on windows.
 I'm hoping this doesn't cause audio problems for anyone else, but
honestly I have no idea what DSound uses the window handle with
DSSCL_PRIORITY for anyway.

 The $2100 luminance stuff was improved by adding rounding support to
the double-to-int casts, so fades should appear a little smoother now
in games.

 Possibly fixed a bug where RTO wasn't being calculated when
brightness=0 and the screen is enabled. Didn't see any improvements in
the three known bugged games.

[No archive available]
2006-08-11 06:59:00 +00:00
byuu 764fe1974a Update to bsnes v016r44 release.
[No changelog available]
2006-08-08 02:02:38 +00:00
byuu a55d640459 Update to bsnes v016r42 release.
Ok, one semi-large change if anyone wants to test.

             byuu.cinnamonpirate.com/files/bsnes_v016_wip42.zip

 This is built for maximum speed. No debugger, PGO enabled, favor
speed, no c++ EH (so no ZIP/JMA), and a new addition: links against
msvcrt instead of libcmt.

 By using msvcrt and some evil linker hacks I was finally able to
build the SDL port again on Windows. So now I just need to focus on
cleaning that up so the next release will build on Linux out of the
box. Anyway, I tried it on the non-SDL port for the hell of it, and
noticed not only a 20% drop in EXE size, but a ~10-11% speedup as
well. Only problem is it requires msvcr80.dll, and I have no idea how
common that file is. So, that's what this wip is for. Does this
version work for you, and if it does, does it run faster? A direct FPS
comparison between v0.016 and v0.016.42 would be helpful if you're not
sure.
2006-08-04 01:27:04 +00:00
byuu 6010bffe5d Update to bsnes v016r38 release.
Ok, this WIP rewrites the input code and modifies the PAL clock speed.
Fairly major changes. Ideally, this will wipe out four bugs without
causing any new ones since wip37.

             Bug fixes :
             Earthworm Jim 2 (E) - adjusted PAL CPU clock speed.
Please test for *new* sound problems in PAL games
             La Wares (J) + Galivan 2 (J) - no longer return 0 when
auto joypad is off for polling $4218-$421f
             Super Conflict (J) - added anomie's new OAM RTO findings
to fix title screen

 The input code was almost completely rewritten to simulate real
hardware more. As such, it's very possible there are new input bugs.

             Ok, so then
byuu.cinnamonpirate.com/files/bsnes_v016_wip38.zip
 Please only download if you intend to test games and report feedback.
This version is slower than normal, lacks ZIP+JMA loading, and has the
debugger enabled (that is only useful to me, it lacks a functional
user interface) which slows down emulation even more. eg you're better
off with v0.016 official if you just want to run games.
             As always, please don't post this link anywhere else, or
I will be forced to remove the file to conserve bandwidth.

 If anyone posts bugs that hasn't tested against wip37, can I please
have someone with wip37 verify/deny the bug presence in wip37 as well
as in 016 official? wip37 isn't on my website because I don't have a
lot of web space to spare.

             Thank you to everyone in advance for helping.
2006-07-27 23:56:42 +00:00
byuu e492268025 Update to bsnes v016r27a release.
Ok, I tried converting the switch/case table to a jump table for both
CPU+APU cores. Results? EXE is 70kb larger, compile time is 5-10%
slower, and speed is identical. Needless to say I reverted that change
back. I then tried narrowing down the cause of the PGO error. Found
out it was Dai Kaijuu Monogatari. If I don't run that, I can build
with PGO. Unfortunately, this is the ROM I use to stress optimize
color add/sub. So as a result, this game will run a little slowly now
(sort of like how Chrono Trigger's OPT title screen effects were
before). But, better one game than all, right?

             byuu.org/files/bsnes_v016_wip27a.zip

 Once again, please do not submit news about this to an emulation
site. The file will be removed if I notice anyone mentioning it
anywhere.

             That will be 20-25% faster than wip27, but otherwise
everything is identical.

 DSP1: there's either a bug in op02, op06, or in the getSr/getDr/setDr
functions. We have so far been unable to spot the error and correct
it. Help is always welcome, as always. Please consider DSP-1 support
as not being there at all. I doubt any games will work right with it
right now :(

             This is how interlace works :
             I call each frame a "field", meaning even or odd fields
on your television / monitor.
             When interlace is off, I draw to the even fields every
time, so you don't notice anything.
 However, when interlace is on, I alternate between which one I draw
to each field. So depending on your frameskip, this can cause serious
problems for interlace mode. I also only physically draw to "half" the
resolution each field, much like a real TV would. This makes 512x448
mode just as fast as 512x224 mode.
 I can't think of an easy way to cheat the system with frameskipping.
Luckily, very very few games use interlace at all. Most use hires
512x224 and that's it.
2006-07-09 05:32:10 +00:00
byuu a36c26c997 Update to bsnes v016r27 release.
Here's a WIP to try out, it's 20-40% slower than it
should be, due to PGO crashing the compiler*.

               Please copy and paste link, and _do not_ post this on
emulation news sites or I will remove the file.

               byuu.org/files/bsnes_v016_wip27.zip

 Even though it's slower, could I get some people to try running
through a bunch of games and look for new bugs? Given I rewrote the
entire CPU+APU, it's possible some new bugs crept in.

               * No release this weekend. Please be sure to thank
Microsoft personally for the delay.







    rc /r /fobsnes.res bsnes.rc
                       cl /Febsnes.exe /nologo /O2 /GL /EHsc main.obj
    libco.obj libstring.obj
                       libconfig.obj libbpf.obj reader.obj cart.obj
    cheat.obj memory.obj bmemory.obj
                       cpu.obj scpu.obj bcpu.obj apu.obj sapu.obj
    bapu.obj bdsp.obj ppu.obj bppu.ob
                       j snes.obj srtc.obj sdd1.obj c4.obj dsp1.obj
    dsp2.obj obc1.obj adler32.obj co
                       mpress.obj crc32.obj deflate.obj gzio.obj
    inffast.obj inflate.obj inftrees.obj
                       ioapi.obj trees.obj unzip.obj zip.obj zutil.obj
    jma.obj jcrc32.obj lzmadec.obj
                       7zlzma.obj iiostrm.obj inbyte.obj lzma.obj
    winout.obj bsnes.res kernel32.lib use
                       r32.lib gdi32.lib comdlg32.lib comctl32.lib
    d3d9.lib d3dx9.lib ddraw.lib dsound
                       .lib dinput8.lib dxguid.lib /link
    /PGD:bsnes.pgd /LTCG:PGOPTIMIZE
                       Merging bsnes!1.pgc
                       Generating code
                       \bsnes\src\apu\sapu\core\core.cpp(16) : fatal
    error C1001: An internal er
                       ror has occurred in the compiler.
                       (compiler file
    'f:\rtm\vctools\compiler\utc\src\P2\main.c[0x10CB9ABB:0x00000025]
                       ', line 182)
                       To work around this problem, try simplifying or
    changing the program near the l
                       ocations listed above.
                       Please choose the Technical Support command on
    the Visual C++
                       Help menu, or open the Technical Support help
    file for more information

                       LINK : fatal error LNK1000: Internal error
    during IMAGE::BuildImage




               What is on sapu\core\core.cpp(16) that's too complex
for Visual c++ to handle?







    status.in_opcode = false;




               Please, if anyone can simplify that for me, let me
know.

 Seriously, though, if anyone can take a look at the source and fix
this compiler error I'd really appreciate it, and I'll get a release
out this weekend. I'm using Visual C++ 2005 Professional. Otherwise
I'll have to set it aside because I don't have time.

[No archive available]
2006-07-09 01:38:00 +00:00
354 changed files with 22889 additions and 12113 deletions

No files matched your search

-26
View File
@@ -1,26 +0,0 @@
bsnes License:
--------------
You are free to redistribute this software, and its source code; provided
there is no charge for the software, nor any charge for the medium used to
distribute the software. You are also free to use and modify the source code
as you desire for personal use only. No publically-released derivative works
of this source code are permitted without my permission, though I will likely
grant you permission if you ask me. You must also abide by the terms of any
additional source code licenses contained within this program.
Simple DirectMedia Layer License:
---------------------------------
The Simple DirectMedia Layer (SDL for short) is a cross-platform library
designed to make it easy to write multi-media software, such as games and
emulators.
The Simple DirectMedia Layer library source code is available from:
http://www.libsdl.org/
This library is distributed under the terms of the GNU LGPL:
http://www.gnu.org/copyleft/lesser.html
Licensing Exemptions:
---------------------
Richard Bannister has asked for and received my permission to distribute
a binary-only port of bsnes on the Mac OS X platform.
-33
View File
@@ -1,33 +0,0 @@
#include "apuregs.h"
class APU {
public:
APURegs regs;
static const uint8 iplrom[64];
enum {
FLAG_N = 0x80, FLAG_V = 0x40,
FLAG_P = 0x20, FLAG_B = 0x10,
FLAG_H = 0x08, FLAG_I = 0x04,
FLAG_Z = 0x02, FLAG_C = 0x01
};
virtual uint8 spcram_read (uint16 addr) = 0;
virtual void spcram_write(uint16 addr, uint8 value) = 0;
//$f4-$f7
virtual uint8 port_read (uint8 port) = 0;
virtual void port_write(uint8 port, uint8 value) = 0;
virtual uint8 *get_spcram_handle() = 0;
virtual void run() = 0;
virtual uint32 cycles_executed() = 0;
virtual void power() = 0;
virtual void reset() = 0;
//debugging functions
virtual bool in_opcode();
void disassemble_opcode(char *output);
inline uint16 __relb(int8 offset, int op_len);
APU() {}
virtual ~APU() {}
};
-49
View File
@@ -1,49 +0,0 @@
class APURegFlags {
private:
template <uint8 B> class bit {
public:
uint8 _b;
inline operator bool() { return (_b & B); }
inline bool operator = (bool i) { (i) ? _b |= B : _b &= ~B; return (_b & B); }
inline bool operator & (bool i) { if(i)_b &= ~B; return (_b & B); }
inline bool operator &= (bool i) { if(i)_b &= ~B; return (_b & B); }
inline bool operator | (bool i) { if(i)_b |= B; return (_b & B); }
inline bool operator |= (bool i) { if(i)_b |= B; return (_b & B); }
inline bool operator ^ (bool i) { if(i)_b ^= B; return (_b & B); }
inline bool operator ^= (bool i) { if(i)_b ^= B; return (_b & B); }
};
public:
union {
uint8 _b;
bit<0x80> n;
bit<0x40> v;
bit<0x20> p;
bit<0x10> b;
bit<0x08> h;
bit<0x04> i;
bit<0x02> z;
bit<0x01> c;
};
APURegFlags() { _b = 0; }
inline operator uint8() { return _b; }
inline unsigned operator = (uint8 i) { _b = i; return _b; }
inline unsigned operator &= (uint8 i) { _b &= i; return _b; }
inline unsigned operator |= (uint8 i) { _b |= i; return _b; }
inline unsigned operator ^= (uint8 i) { _b ^= i; return _b; }
};
class APURegs {
public:
uint16 pc;
union {
uint16 ya;
#ifdef ARCH_LSB
struct { uint8 a, y; };
#else
struct { uint8 y, a; };
#endif
};
uint8 x, sp;
APURegFlags p;
};
-3
View File
@@ -1,3 +0,0 @@
cl /O2 /wd4996 bapugen.cpp
@pause
@del *.obj
-8
View File
@@ -1,8 +0,0 @@
@del *.exe
@del op.h
@del optable.cpp
@del op_mov.cpp
@del op_pc.cpp
@del op_read.cpp
@del op_rmw.cpp
@del op_misc.cpp
-256
View File
@@ -1,256 +0,0 @@
optbl[0x7d] = &bAPU::op_mov_a_x;
optbl[0xdd] = &bAPU::op_mov_a_y;
optbl[0x5d] = &bAPU::op_mov_x_a;
optbl[0xfd] = &bAPU::op_mov_y_a;
optbl[0x9d] = &bAPU::op_mov_x_sp;
optbl[0xbd] = &bAPU::op_mov_sp_x;
optbl[0xe8] = &bAPU::op_mov_a_const;
optbl[0xcd] = &bAPU::op_mov_x_const;
optbl[0x8d] = &bAPU::op_mov_y_const;
optbl[0xe6] = &bAPU::op_mov_a_ix;
optbl[0xbf] = &bAPU::op_mov_a_ixinc;
optbl[0xe4] = &bAPU::op_mov_a_dp;
optbl[0xf8] = &bAPU::op_mov_x_dp;
optbl[0xeb] = &bAPU::op_mov_y_dp;
optbl[0xf4] = &bAPU::op_mov_a_dpx;
optbl[0xf9] = &bAPU::op_mov_x_dpy;
optbl[0xfb] = &bAPU::op_mov_y_dpx;
optbl[0xe5] = &bAPU::op_mov_a_addr;
optbl[0xe9] = &bAPU::op_mov_x_addr;
optbl[0xec] = &bAPU::op_mov_y_addr;
optbl[0xf5] = &bAPU::op_mov_a_addrx;
optbl[0xf6] = &bAPU::op_mov_a_addry;
optbl[0xe7] = &bAPU::op_mov_a_idpx;
optbl[0xf7] = &bAPU::op_mov_a_idpy;
optbl[0xfa] = &bAPU::op_mov_dp_dp;
optbl[0x8f] = &bAPU::op_mov_dp_const;
optbl[0xc6] = &bAPU::op_mov_ix_a;
optbl[0xaf] = &bAPU::op_mov_ixinc_a;
optbl[0xc4] = &bAPU::op_mov_dp_a;
optbl[0xd8] = &bAPU::op_mov_dp_x;
optbl[0xcb] = &bAPU::op_mov_dp_y;
optbl[0xd4] = &bAPU::op_mov_dpx_a;
optbl[0xd9] = &bAPU::op_mov_dpy_x;
optbl[0xdb] = &bAPU::op_mov_dpx_y;
optbl[0xc5] = &bAPU::op_mov_addr_a;
optbl[0xc9] = &bAPU::op_mov_addr_x;
optbl[0xcc] = &bAPU::op_mov_addr_y;
optbl[0xd5] = &bAPU::op_mov_addrx_a;
optbl[0xd6] = &bAPU::op_mov_addry_a;
optbl[0xc7] = &bAPU::op_mov_idpx_a;
optbl[0xd7] = &bAPU::op_mov_idpy_a;
optbl[0xba] = &bAPU::op_movw_ya_dp;
optbl[0xda] = &bAPU::op_movw_dp_ya;
optbl[0xaa] = &bAPU::op_mov1_c_bit;
optbl[0xca] = &bAPU::op_mov1_bit_c;
optbl[0x2f] = &bAPU::op_bra;
optbl[0xf0] = &bAPU::op_beq;
optbl[0xd0] = &bAPU::op_bne;
optbl[0xb0] = &bAPU::op_bcs;
optbl[0x90] = &bAPU::op_bcc;
optbl[0x70] = &bAPU::op_bvs;
optbl[0x50] = &bAPU::op_bvc;
optbl[0x30] = &bAPU::op_bmi;
optbl[0x10] = &bAPU::op_bpl;
optbl[0x03] = &bAPU::op_bbs0;
optbl[0x13] = &bAPU::op_bbc0;
optbl[0x23] = &bAPU::op_bbs1;
optbl[0x33] = &bAPU::op_bbc1;
optbl[0x43] = &bAPU::op_bbs2;
optbl[0x53] = &bAPU::op_bbc2;
optbl[0x63] = &bAPU::op_bbs3;
optbl[0x73] = &bAPU::op_bbc3;
optbl[0x83] = &bAPU::op_bbs4;
optbl[0x93] = &bAPU::op_bbc4;
optbl[0xa3] = &bAPU::op_bbs5;
optbl[0xb3] = &bAPU::op_bbc5;
optbl[0xc3] = &bAPU::op_bbs6;
optbl[0xd3] = &bAPU::op_bbc6;
optbl[0xe3] = &bAPU::op_bbs7;
optbl[0xf3] = &bAPU::op_bbc7;
optbl[0x2e] = &bAPU::op_cbne_dp;
optbl[0xde] = &bAPU::op_cbne_dpx;
optbl[0x6e] = &bAPU::op_dbnz_dp;
optbl[0xfe] = &bAPU::op_dbnz_y;
optbl[0x5f] = &bAPU::op_jmp_addr;
optbl[0x1f] = &bAPU::op_jmp_iaddrx;
optbl[0x3f] = &bAPU::op_call;
optbl[0x4f] = &bAPU::op_pcall;
optbl[0x01] = &bAPU::op_tcall_0;
optbl[0x11] = &bAPU::op_tcall_1;
optbl[0x21] = &bAPU::op_tcall_2;
optbl[0x31] = &bAPU::op_tcall_3;
optbl[0x41] = &bAPU::op_tcall_4;
optbl[0x51] = &bAPU::op_tcall_5;
optbl[0x61] = &bAPU::op_tcall_6;
optbl[0x71] = &bAPU::op_tcall_7;
optbl[0x81] = &bAPU::op_tcall_8;
optbl[0x91] = &bAPU::op_tcall_9;
optbl[0xa1] = &bAPU::op_tcall_10;
optbl[0xb1] = &bAPU::op_tcall_11;
optbl[0xc1] = &bAPU::op_tcall_12;
optbl[0xd1] = &bAPU::op_tcall_13;
optbl[0xe1] = &bAPU::op_tcall_14;
optbl[0xf1] = &bAPU::op_tcall_15;
optbl[0x0f] = &bAPU::op_brk;
optbl[0x6f] = &bAPU::op_ret;
optbl[0x7f] = &bAPU::op_reti;
optbl[0x88] = &bAPU::op_adc_a_const;
optbl[0x28] = &bAPU::op_and_a_const;
optbl[0x68] = &bAPU::op_cmp_a_const;
optbl[0xc8] = &bAPU::op_cmp_x_const;
optbl[0xad] = &bAPU::op_cmp_y_const;
optbl[0x48] = &bAPU::op_eor_a_const;
optbl[0x08] = &bAPU::op_or_a_const;
optbl[0xa8] = &bAPU::op_sbc_a_const;
optbl[0x86] = &bAPU::op_adc_a_ix;
optbl[0x26] = &bAPU::op_and_a_ix;
optbl[0x66] = &bAPU::op_cmp_a_ix;
optbl[0x46] = &bAPU::op_eor_a_ix;
optbl[0x06] = &bAPU::op_or_a_ix;
optbl[0xa6] = &bAPU::op_sbc_a_ix;
optbl[0x84] = &bAPU::op_adc_a_dp;
optbl[0x24] = &bAPU::op_and_a_dp;
optbl[0x64] = &bAPU::op_cmp_a_dp;
optbl[0x3e] = &bAPU::op_cmp_x_dp;
optbl[0x7e] = &bAPU::op_cmp_y_dp;
optbl[0x44] = &bAPU::op_eor_a_dp;
optbl[0x04] = &bAPU::op_or_a_dp;
optbl[0xa4] = &bAPU::op_sbc_a_dp;
optbl[0x94] = &bAPU::op_adc_a_dpx;
optbl[0x34] = &bAPU::op_and_a_dpx;
optbl[0x74] = &bAPU::op_cmp_a_dpx;
optbl[0x54] = &bAPU::op_eor_a_dpx;
optbl[0x14] = &bAPU::op_or_a_dpx;
optbl[0xb4] = &bAPU::op_sbc_a_dpx;
optbl[0x85] = &bAPU::op_adc_a_addr;
optbl[0x25] = &bAPU::op_and_a_addr;
optbl[0x65] = &bAPU::op_cmp_a_addr;
optbl[0x1e] = &bAPU::op_cmp_x_addr;
optbl[0x5e] = &bAPU::op_cmp_y_addr;
optbl[0x45] = &bAPU::op_eor_a_addr;
optbl[0x05] = &bAPU::op_or_a_addr;
optbl[0xa5] = &bAPU::op_sbc_a_addr;
optbl[0x95] = &bAPU::op_adc_a_addrx;
optbl[0x96] = &bAPU::op_adc_a_addry;
optbl[0x35] = &bAPU::op_and_a_addrx;
optbl[0x36] = &bAPU::op_and_a_addry;
optbl[0x75] = &bAPU::op_cmp_a_addrx;
optbl[0x76] = &bAPU::op_cmp_a_addry;
optbl[0x55] = &bAPU::op_eor_a_addrx;
optbl[0x56] = &bAPU::op_eor_a_addry;
optbl[0x15] = &bAPU::op_or_a_addrx;
optbl[0x16] = &bAPU::op_or_a_addry;
optbl[0xb5] = &bAPU::op_sbc_a_addrx;
optbl[0xb6] = &bAPU::op_sbc_a_addry;
optbl[0x87] = &bAPU::op_adc_a_idpx;
optbl[0x27] = &bAPU::op_and_a_idpx;
optbl[0x67] = &bAPU::op_cmp_a_idpx;
optbl[0x47] = &bAPU::op_eor_a_idpx;
optbl[0x07] = &bAPU::op_or_a_idpx;
optbl[0xa7] = &bAPU::op_sbc_a_idpx;
optbl[0x97] = &bAPU::op_adc_a_idpy;
optbl[0x37] = &bAPU::op_and_a_idpy;
optbl[0x77] = &bAPU::op_cmp_a_idpy;
optbl[0x57] = &bAPU::op_eor_a_idpy;
optbl[0x17] = &bAPU::op_or_a_idpy;
optbl[0xb7] = &bAPU::op_sbc_a_idpy;
optbl[0x99] = &bAPU::op_adc_ix_iy;
optbl[0x39] = &bAPU::op_and_ix_iy;
optbl[0x79] = &bAPU::op_cmp_ix_iy;
optbl[0x59] = &bAPU::op_eor_ix_iy;
optbl[0x19] = &bAPU::op_or_ix_iy;
optbl[0xb9] = &bAPU::op_sbc_ix_iy;
optbl[0x89] = &bAPU::op_adc_dp_dp;
optbl[0x29] = &bAPU::op_and_dp_dp;
optbl[0x69] = &bAPU::op_cmp_dp_dp;
optbl[0x49] = &bAPU::op_eor_dp_dp;
optbl[0x09] = &bAPU::op_or_dp_dp;
optbl[0xa9] = &bAPU::op_sbc_dp_dp;
optbl[0x98] = &bAPU::op_adc_dp_const;
optbl[0x38] = &bAPU::op_and_dp_const;
optbl[0x78] = &bAPU::op_cmp_dp_const;
optbl[0x58] = &bAPU::op_eor_dp_const;
optbl[0x18] = &bAPU::op_or_dp_const;
optbl[0xb8] = &bAPU::op_sbc_dp_const;
optbl[0x7a] = &bAPU::op_addw_ya_dp;
optbl[0x5a] = &bAPU::op_cmpw_ya_dp;
optbl[0x9a] = &bAPU::op_subw_ya_dp;
optbl[0x4a] = &bAPU::op_and1_bit;
optbl[0x6a] = &bAPU::op_and1_notbit;
optbl[0x8a] = &bAPU::op_eor1_bit;
optbl[0xea] = &bAPU::op_not1_bit;
optbl[0x0a] = &bAPU::op_or1_bit;
optbl[0x2a] = &bAPU::op_or1_notbit;
optbl[0xbc] = &bAPU::op_inc_a;
optbl[0x3d] = &bAPU::op_inc_x;
optbl[0xfc] = &bAPU::op_inc_y;
optbl[0x9c] = &bAPU::op_dec_a;
optbl[0x1d] = &bAPU::op_dec_x;
optbl[0xdc] = &bAPU::op_dec_y;
optbl[0x1c] = &bAPU::op_asl_a;
optbl[0x5c] = &bAPU::op_lsr_a;
optbl[0x3c] = &bAPU::op_rol_a;
optbl[0x7c] = &bAPU::op_ror_a;
optbl[0xab] = &bAPU::op_inc_dp;
optbl[0x8b] = &bAPU::op_dec_dp;
optbl[0x0b] = &bAPU::op_asl_dp;
optbl[0x4b] = &bAPU::op_lsr_dp;
optbl[0x2b] = &bAPU::op_rol_dp;
optbl[0x6b] = &bAPU::op_ror_dp;
optbl[0xbb] = &bAPU::op_inc_dpx;
optbl[0x9b] = &bAPU::op_dec_dpx;
optbl[0x1b] = &bAPU::op_asl_dpx;
optbl[0x5b] = &bAPU::op_lsr_dpx;
optbl[0x3b] = &bAPU::op_rol_dpx;
optbl[0x7b] = &bAPU::op_ror_dpx;
optbl[0xac] = &bAPU::op_inc_addr;
optbl[0x8c] = &bAPU::op_dec_addr;
optbl[0x0c] = &bAPU::op_asl_addr;
optbl[0x4c] = &bAPU::op_lsr_addr;
optbl[0x2c] = &bAPU::op_rol_addr;
optbl[0x6c] = &bAPU::op_ror_addr;
optbl[0x3a] = &bAPU::op_incw_dp;
optbl[0x1a] = &bAPU::op_decw_dp;
optbl[0x00] = &bAPU::op_nop;
optbl[0xef] = &bAPU::op_sleep;
optbl[0xff] = &bAPU::op_stop;
optbl[0x9f] = &bAPU::op_xcn;
optbl[0xdf] = &bAPU::op_daa;
optbl[0xbe] = &bAPU::op_das;
optbl[0x60] = &bAPU::op_clrc;
optbl[0x20] = &bAPU::op_clrp;
optbl[0x80] = &bAPU::op_setc;
optbl[0x40] = &bAPU::op_setp;
optbl[0xe0] = &bAPU::op_clrv;
optbl[0xed] = &bAPU::op_notc;
optbl[0xa0] = &bAPU::op_ei;
optbl[0xc0] = &bAPU::op_di;
optbl[0x02] = &bAPU::op_set0_dp;
optbl[0x12] = &bAPU::op_clr0_dp;
optbl[0x22] = &bAPU::op_set1_dp;
optbl[0x32] = &bAPU::op_clr1_dp;
optbl[0x42] = &bAPU::op_set2_dp;
optbl[0x52] = &bAPU::op_clr2_dp;
optbl[0x62] = &bAPU::op_set3_dp;
optbl[0x72] = &bAPU::op_clr3_dp;
optbl[0x82] = &bAPU::op_set4_dp;
optbl[0x92] = &bAPU::op_clr4_dp;
optbl[0xa2] = &bAPU::op_set5_dp;
optbl[0xb2] = &bAPU::op_clr5_dp;
optbl[0xc2] = &bAPU::op_set6_dp;
optbl[0xd2] = &bAPU::op_clr6_dp;
optbl[0xe2] = &bAPU::op_set7_dp;
optbl[0xf2] = &bAPU::op_clr7_dp;
optbl[0x0e] = &bAPU::op_tset_addr_a;
optbl[0x4e] = &bAPU::op_tclr_addr_a;
optbl[0x2d] = &bAPU::op_push_a;
optbl[0x4d] = &bAPU::op_push_x;
optbl[0x6d] = &bAPU::op_push_y;
optbl[0x0d] = &bAPU::op_push_p;
optbl[0xae] = &bAPU::op_pop_a;
optbl[0xce] = &bAPU::op_pop_x;
optbl[0xee] = &bAPU::op_pop_y;
optbl[0x8e] = &bAPU::op_pop_p;
optbl[0xcf] = &bAPU::op_mul_ya;
optbl[0x9e] = &bAPU::op_div_ya_x;
-306
View File
@@ -1,306 +0,0 @@
//virtual function, see src/cpu/dcpu.cpp
//for explanation of this function
bool APU::in_opcode() { return false; }
uint16 APU::__relb(int8 offset, int op_len) {
uint16 pc = regs.pc + op_len;
return pc + offset;
}
void APU::disassemble_opcode(char *output) {
char *s, t[512];
uint8 op, op0, op1;
uint16 opw, opdp0, opdp1;
s = output;
if(in_opcode() == true) {
strcpy(s, "..???? <APU within opcode>");
return;
}
sprintf(s, "..%0.4x ", regs.pc);
op = spcram_read(regs.pc);
op0 = spcram_read(regs.pc + 1);
op1 = spcram_read(regs.pc + 2);
opw = (op0) | (op1 << 8);
opdp0 = ((regs.p.p)?0x100:0x000) + op0;
opdp1 = ((regs.p.p)?0x100:0x000) + op1;
strcpy(t, " ");
switch(op) {
case 0x00:sprintf(t, "nop"); break;
case 0x01:sprintf(t, "tcall 0"); break;
case 0x02:sprintf(t, "set0 $%0.3x", opdp0); break;
case 0x03:sprintf(t, "bbs0 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x04:sprintf(t, "or a,$%0.3x", opdp0); break;
case 0x05:sprintf(t, "or a,$%0.4x", opw); break;
case 0x06:sprintf(t, "or a,(x)"); break;
case 0x07:sprintf(t, "or a,($%0.3x+x)", opdp0); break;
case 0x08:sprintf(t, "or a,#$%0.2x", op0); break;
case 0x09:sprintf(t, "or $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x0a:sprintf(t, "or1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x0b:sprintf(t, "asl $%0.3x", opdp0); break;
case 0x0c:sprintf(t, "asl $%0.4x", opw); break;
case 0x0d:sprintf(t, "push p"); break;
case 0x0e:sprintf(t, "tset $%0.4x,a", opw); break;
case 0x0f:sprintf(t, "brk"); break;
case 0x10:sprintf(t, "bpl $%0.4x", __relb(op0, 2)); break;
case 0x11:sprintf(t, "tcall 1"); break;
case 0x12:sprintf(t, "clr0 $%0.3x", opdp0); break;
case 0x13:sprintf(t, "bbc0 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x14:sprintf(t, "or a,$%0.3x+x", opdp0); break;
case 0x15:sprintf(t, "or a,$%0.4x+x", opw); break;
case 0x16:sprintf(t, "or a,$%0.4x+y", opw); break;
case 0x17:sprintf(t, "or a,($%0.3x)+y", opdp0); break;
case 0x18:sprintf(t, "or $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x19:sprintf(t, "or (x),(y)"); break;
case 0x1a:sprintf(t, "decw $%0.3x", opdp0); break;
case 0x1b:sprintf(t, "asl $%0.3x+x", opdp0); break;
case 0x1c:sprintf(t, "asl a"); break;
case 0x1d:sprintf(t, "dec x"); break;
case 0x1e:sprintf(t, "cmp x,$%0.4x", opw); break;
case 0x1f:sprintf(t, "jmp ($%0.4x+x)", opw); break;
case 0x20:sprintf(t, "clrp"); break;
case 0x21:sprintf(t, "tcall 2"); break;
case 0x22:sprintf(t, "set1 $%0.3x", opdp0); break;
case 0x23:sprintf(t, "bbs1 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x24:sprintf(t, "and a,$%0.3x", opdp0); break;
case 0x25:sprintf(t, "and a,$%0.4x", opw); break;
case 0x26:sprintf(t, "and a,(x)"); break;
case 0x27:sprintf(t, "and a,($%0.3x+x)", opdp0); break;
case 0x28:sprintf(t, "and a,#$%0.2x", op0); break;
case 0x29:sprintf(t, "and $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x2a:sprintf(t, "or1 c,!$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x2b:sprintf(t, "rol $%0.3x", opdp0); break;
case 0x2c:sprintf(t, "rol $%0.4x", opw); break;
case 0x2d:sprintf(t, "push a"); break;
case 0x2e:sprintf(t, "cbne $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x2f:sprintf(t, "bra $%0.4x", __relb(op0, 2)); break;
case 0x30:sprintf(t, "bmi $%0.4x", __relb(op0, 2)); break;
case 0x31:sprintf(t, "tcall 3"); break;
case 0x32:sprintf(t, "clr1 $%0.3x", opdp0); break;
case 0x33:sprintf(t, "bbc1 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x34:sprintf(t, "and a,$%0.3x+x", opdp0); break;
case 0x35:sprintf(t, "and a,$%0.4x+x", opw); break;
case 0x36:sprintf(t, "and a,$%0.4x+y", opw); break;
case 0x37:sprintf(t, "and a,($%0.3x)+y", opdp0); break;
case 0x38:sprintf(t, "and $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x39:sprintf(t, "and (x),(y)"); break;
case 0x3a:sprintf(t, "incw $%0.3x", opdp0); break;
case 0x3b:sprintf(t, "rol $%0.3x+x", opdp0); break;
case 0x3c:sprintf(t, "rol a"); break;
case 0x3d:sprintf(t, "inc x"); break;
case 0x3e:sprintf(t, "cmp x,$%0.3x", opdp0); break;
case 0x3f:sprintf(t, "call $%0.4x", opw); break;
case 0x40:sprintf(t, "setp"); break;
case 0x41:sprintf(t, "tcall 4"); break;
case 0x42:sprintf(t, "set2 $%0.3x", opdp0); break;
case 0x43:sprintf(t, "bbs2 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x44:sprintf(t, "eor a,$%0.3x", opdp0); break;
case 0x45:sprintf(t, "eor a,$%0.4x", opw); break;
case 0x46:sprintf(t, "eor a,(x)"); break;
case 0x47:sprintf(t, "eor a,($%0.3x+x)", opdp0); break;
case 0x48:sprintf(t, "eor a,#$%0.2x", op0); break;
case 0x49:sprintf(t, "eor $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x4a:sprintf(t, "and1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x4b:sprintf(t, "lsr $%0.3x", opdp0); break;
case 0x4c:sprintf(t, "lsr $%0.4x", opw); break;
case 0x4d:sprintf(t, "push x"); break;
case 0x4e:sprintf(t, "tclr $%0.4x,a", opw); break;
case 0x4f:sprintf(t, "pcall $ff%0.2x", op0); break;
case 0x50:sprintf(t, "bvc $%0.4x", __relb(op0, 2)); break;
case 0x51:sprintf(t, "tcall 5"); break;
case 0x52:sprintf(t, "clr2 $%0.3x", opdp0); break;
case 0x53:sprintf(t, "bbc2 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x54:sprintf(t, "eor a,$%0.3x+x", opdp0); break;
case 0x55:sprintf(t, "eor a,$%0.4x+x", opw); break;
case 0x56:sprintf(t, "eor a,$%0.4x+y", opw); break;
case 0x57:sprintf(t, "eor a,($%0.3x)+y", opdp0); break;
case 0x58:sprintf(t, "eor $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x59:sprintf(t, "eor (x),(y)"); break;
case 0x5a:sprintf(t, "cmpw ya,$%0.3x", opdp0); break;
case 0x5b:sprintf(t, "lsr $%0.3x+x", opdp0); break;
case 0x5c:sprintf(t, "lsr a"); break;
case 0x5d:sprintf(t, "mov x,a"); break;
case 0x5e:sprintf(t, "cmp y,$%0.4x", opw); break;
case 0x5f:sprintf(t, "jmp $%0.4x", opw); break;
case 0x60:sprintf(t, "clrc"); break;
case 0x61:sprintf(t, "tcall 6"); break;
case 0x62:sprintf(t, "set3 $%0.3x", opdp0); break;
case 0x63:sprintf(t, "bbs3 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x64:sprintf(t, "cmp a,$%0.3x", opdp0); break;
case 0x65:sprintf(t, "cmp a,$%0.4x", opw); break;
case 0x66:sprintf(t, "cmp a,(x)"); break;
case 0x67:sprintf(t, "cmp a,($%0.3x+x)", opdp0); break;
case 0x68:sprintf(t, "cmp a,#$%0.2x", op0); break;
case 0x69:sprintf(t, "cmp $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x6a:sprintf(t, "and1 c,!$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x6b:sprintf(t, "ror $%0.3x", opdp0); break;
case 0x6c:sprintf(t, "ror $%0.4x", opw); break;
case 0x6d:sprintf(t, "push y"); break;
case 0x6e:sprintf(t, "dbnz $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x6f:sprintf(t, "ret"); break;
case 0x70:sprintf(t, "bvs $%0.4x", __relb(op0, 2)); break;
case 0x71:sprintf(t, "tcall 7"); break;
case 0x72:sprintf(t, "clr3 $%0.3x", opdp0); break;
case 0x73:sprintf(t, "bbc3 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x74:sprintf(t, "cmp a,$%0.3x+x", opdp0); break;
case 0x75:sprintf(t, "cmp a,$%0.4x+x", opw); break;
case 0x76:sprintf(t, "cmp a,$%0.4x+y", opw); break;
case 0x77:sprintf(t, "cmp a,($%0.3x)+y", opdp0); break;
case 0x78:sprintf(t, "cmp $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x79:sprintf(t, "cmp (x),(y)"); break;
case 0x7a:sprintf(t, "addw ya,$%0.3x", opdp0); break;
case 0x7b:sprintf(t, "ror $%0.3x+x", opdp0); break;
case 0x7c:sprintf(t, "ror a"); break;
case 0x7d:sprintf(t, "mov a,x"); break;
case 0x7e:sprintf(t, "cmp y,$%0.3x", opdp0); break;
case 0x7f:sprintf(t, "reti"); break;
case 0x80:sprintf(t, "setc"); break;
case 0x81:sprintf(t, "tcall 8"); break;
case 0x82:sprintf(t, "set4 $%0.3x", opdp0); break;
case 0x83:sprintf(t, "bbs4 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x84:sprintf(t, "adc a,$%0.3x", opdp0); break;
case 0x85:sprintf(t, "adc a,$%0.4x", opw); break;
case 0x86:sprintf(t, "adc a,(x)"); break;
case 0x87:sprintf(t, "adc a,($%0.3x+x)", opdp0); break;
case 0x88:sprintf(t, "adc a,#$%0.2x", op0); break;
case 0x89:sprintf(t, "adc $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x8a:sprintf(t, "eor1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x8b:sprintf(t, "dec $%0.3x", opdp0); break;
case 0x8c:sprintf(t, "dec $%0.4x", opw); break;
case 0x8d:sprintf(t, "mov y,#$%0.2x", op0); break;
case 0x8e:sprintf(t, "pop p"); break;
case 0x8f:sprintf(t, "mov $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x90:sprintf(t, "bcc $%0.4x", __relb(op0, 2)); break;
case 0x91:sprintf(t, "tcall 9"); break;
case 0x92:sprintf(t, "clr4 $%0.3x", opdp0); break;
case 0x93:sprintf(t, "bbc4 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x94:sprintf(t, "adc a,$%0.3x+x", opdp0); break;
case 0x95:sprintf(t, "adc a,$%0.4x+x", opw); break;
case 0x96:sprintf(t, "adc a,$%0.4x+y", opw); break;
case 0x97:sprintf(t, "adc a,($%0.3x)+y", opdp0); break;
case 0x98:sprintf(t, "adc $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x99:sprintf(t, "adc (x),(y)"); break;
case 0x9a:sprintf(t, "subw ya,$%0.3x", opdp0); break;
case 0x9b:sprintf(t, "dec $%0.3x+x", opdp0); break;
case 0x9c:sprintf(t, "dec a"); break;
case 0x9d:sprintf(t, "mov x,sp"); break;
case 0x9e:sprintf(t, "div ya,x"); break;
case 0x9f:sprintf(t, "xcn a"); break;
case 0xa0:sprintf(t, "ei"); break;
case 0xa1:sprintf(t, "tcall 10"); break;
case 0xa2:sprintf(t, "set5 $%0.3x", opdp0); break;
case 0xa3:sprintf(t, "bbs5 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xa4:sprintf(t, "sbc a,$%0.3x", opdp0); break;
case 0xa5:sprintf(t, "sbc a,$%0.4x", opw); break;
case 0xa6:sprintf(t, "sbc a,(x)"); break;
case 0xa7:sprintf(t, "sbc a,($%0.3x+x)", opdp0); break;
case 0xa8:sprintf(t, "sbc a,#$%0.2x", op0); break;
case 0xa9:sprintf(t, "sbc $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0xaa:sprintf(t, "mov1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0xab:sprintf(t, "inc $%0.3x", opdp0); break;
case 0xac:sprintf(t, "inc $%0.4x", opw); break;
case 0xad:sprintf(t, "cmp y,#$%0.2x", op0); break;
case 0xae:sprintf(t, "pop a"); break;
case 0xaf:sprintf(t, "mov (x)+,a"); break;
case 0xb0:sprintf(t, "bcs $%0.4x", __relb(op0, 2)); break;
case 0xb1:sprintf(t, "tcall 11"); break;
case 0xb2:sprintf(t, "clr5 $%0.3x", opdp0); break;
case 0xb3:sprintf(t, "bbc5 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xb4:sprintf(t, "sbc a,$%0.3x+x", opdp0); break;
case 0xb5:sprintf(t, "sbc a,$%0.4x+x", opw); break;
case 0xb6:sprintf(t, "sbc a,$%0.4x+y", opw); break;
case 0xb7:sprintf(t, "sbc a,($%0.3x)+y", opdp0); break;
case 0xb8:sprintf(t, "sbc $%0.3x,#$%0.2x", opdp1, op0); break;
case 0xb9:sprintf(t, "sbc (x),(y)"); break;
case 0xba:sprintf(t, "movw ya,$%0.3x", opdp0); break;
case 0xbb:sprintf(t, "inc $%0.3x+x", opdp0); break;
case 0xbc:sprintf(t, "inc a"); break;
case 0xbd:sprintf(t, "mov sp,x"); break;
case 0xbe:sprintf(t, "das a"); break;
case 0xbf:sprintf(t, "mov a,(x)+"); break;
case 0xc0:sprintf(t, "di"); break;
case 0xc1:sprintf(t, "tcall 12"); break;
case 0xc2:sprintf(t, "set6 $%0.3x", opdp0); break;
case 0xc3:sprintf(t, "bbs6 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xc4:sprintf(t, "mov $%0.3x,a", opdp0); break;
case 0xc5:sprintf(t, "mov $%0.4x,a", opw); break;
case 0xc6:sprintf(t, "mov (x),a"); break;
case 0xc7:sprintf(t, "mov ($%0.3x+x),a", opdp0); break;
case 0xc8:sprintf(t, "cmp x,#$%0.2x", op0); break;
case 0xc9:sprintf(t, "mov $%0.4x,x", opw); break;
case 0xca:sprintf(t, "mov1 $%0.4x:%d,c", opw & 0x1fff, opw >> 13); break;
case 0xcb:sprintf(t, "mov $%0.3x,y", opdp0); break;
case 0xcc:sprintf(t, "mov $%0.4x,y", opw); break;
case 0xcd:sprintf(t, "mov x,#$%0.2x", op0); break;
case 0xce:sprintf(t, "pop x"); break;
case 0xcf:sprintf(t, "mul ya"); break;
case 0xd0:sprintf(t, "bne $%0.4x", __relb(op0, 2)); break;
case 0xd1:sprintf(t, "tcall 13"); break;
case 0xd2:sprintf(t, "clr6 $%0.3x", opdp0); break;
case 0xd3:sprintf(t, "bbc6 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xd4:sprintf(t, "mov $%0.3x+x,a", opdp0); break;
case 0xd5:sprintf(t, "mov $%0.4x+x,a", opw); break;
case 0xd6:sprintf(t, "mov $%0.4x+y,a", opw); break;
case 0xd7:sprintf(t, "mov ($%0.3x)+y,a", opdp0); break;
case 0xd8:sprintf(t, "mov $%0.3x,x", opdp0); break;
case 0xd9:sprintf(t, "mov $%0.3x+y,x", opdp0); break;
case 0xda:sprintf(t, "movw $%0.3x,ya", opdp0); break;
case 0xdb:sprintf(t, "mov $%0.3x+x,y", opdp0); break;
case 0xdc:sprintf(t, "dec y"); break;
case 0xdd:sprintf(t, "mov a,y"); break;
case 0xde:sprintf(t, "cbne $%0.3x+x,$%0.4x", opdp0, __relb(op1, 3));break;
case 0xdf:sprintf(t, "daa a"); break;
case 0xe0:sprintf(t, "clrv"); break;
case 0xe1:sprintf(t, "tcall 14"); break;
case 0xe2:sprintf(t, "set7 $%0.3x", opdp0); break;
case 0xe3:sprintf(t, "bbs7 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xe4:sprintf(t, "mov a,$%0.3x", opdp0); break;
case 0xe5:sprintf(t, "mov a,$%0.4x", opw); break;
case 0xe6:sprintf(t, "mov a,(x)"); break;
case 0xe7:sprintf(t, "mov a,($%0.3x+x)", opdp0); break;
case 0xe8:sprintf(t, "mov a,#$%0.2x", op0); break;
case 0xe9:sprintf(t, "mov x,$%0.4x", opw); break;
case 0xea:sprintf(t, "not1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0xeb:sprintf(t, "mov y,$%0.3x", opdp0); break;
case 0xec:sprintf(t, "mov y,$%0.4x", opw); break;
case 0xed:sprintf(t, "notc"); break;
case 0xee:sprintf(t, "pop y"); break;
case 0xef:sprintf(t, "sleep"); break;
case 0xf0:sprintf(t, "beq $%0.4x", __relb(op0, 2)); break;
case 0xf1:sprintf(t, "tcall 15"); break;
case 0xf2:sprintf(t, "clr7 $%0.3x", opdp0); break;
case 0xf3:sprintf(t, "bbc7 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xf4:sprintf(t, "mov a,$%0.3x+x", opdp0); break;
case 0xf5:sprintf(t, "mov a,$%0.4x+x", opw); break;
case 0xf6:sprintf(t, "mov a,$%0.4x+y", opw); break;
case 0xf7:sprintf(t, "mov a,($%0.3x)+y", opdp0); break;
case 0xf8:sprintf(t, "mov x,$%0.3x", opdp0); break;
case 0xf9:sprintf(t, "mov x,$%0.3x+y", opdp0); break;
case 0xfa:sprintf(t, "mov $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0xfb:sprintf(t, "mov y,$%0.3x+x", opdp0); break;
case 0xfc:sprintf(t, "inc y"); break;
case 0xfd:sprintf(t, "mov y,a"); break;
case 0xfe:sprintf(t, "dbnz y,$%0.4x", __relb(op0, 2)); break;
case 0xff:sprintf(t, "stop"); break;
}
t[strlen(t)] = ' ';
strcat(s, t);
sprintf(t, "A:%0.2x X:%0.2x Y:%0.2x SP:01%0.2x YA:%0.4x ",
regs.a, regs.x, regs.y, regs.sp, regs.ya);
strcat(s, t);
sprintf(t, "%c%c%c%c%c%c%c%c",
(regs.p.n)?'N':'n',
(regs.p.v)?'V':'v',
(regs.p.p)?'P':'p',
(regs.p.b)?'B':'b',
(regs.p.h)?'H':'h',
(regs.p.i)?'I':'i',
(regs.p.z)?'Z':'z',
(regs.p.c)?'C':'c');
strcat(s, t);
}
+36 -30
View File
@@ -1,53 +1,46 @@
#define BSNES_VERSION "0.016"
#define BSNES_TITLE "bsnes v" BSNES_VERSION
#define BSNES_VERSION "0.018"
#define BSNES_TITLE "bsnes v" BSNES_VERSION
#define MEMCORE bMemBus
#define CPUCORE bCPU
#define APUCORE bAPU
#define CPUCORE sCPU
#define SMPCORE sSMP
#define DSPCORE bDSP
#define PPUCORE bPPU
//#define FAVOR_ACCURACY
#define FAVOR_SPEED
//game genie + pro action replay code support (~1-3% speed hit)
#define CHEAT_SYSTEM
//enable GZ, ZIP format support
//#define GZIP_SUPPORT
#define GZIP_SUPPORT
//enable JMA support
//#define JMA_SUPPORT
//debugging extensions (~10% speed hit)
#define DEBUGGER
#define JMA_SUPPORT
//snes core polymorphism
//(allow mem/cpu/apu/ppu overriding, ~10% speed hit)
//(allow runtime cpu/smp/dsp/ppu/bus selection, ~10% speed hit)
//#define POLYMORPHISM
//this should be declared in the port-specific makefiles
//#define ARCH_LSB
//#define ARCH_MSB
#ifndef ARCH_LSB
#ifndef ARCH_MSB
#define ARCH_LSB
#endif
#endif
#if defined(_WIN32)
#define _WIN32_
#undef _UNIX_
#elif defined(__GNUC__)
#define _UNIX_
#undef _WIN32_
#if defined(PROCESSOR_X86)
#define ARCH_LSB
#elif defined(PROCESSOR_X86_64)
#define ARCH_LSB
#elif defined(PROCESSOR_G5)
#define ARCH_MSB
#else
#error "unknown architecture"
#error "unsupported processor"
#endif
#include "lib/libbase.h"
#include "lib/libco_x86.h"
#include "lib/libarray.h"
#include "lib/libvector.h"
#include "lib/libfile.h"
#include "lib/libups.h"
#include "lib/libstring.h"
#include "lib/libconfig.h"
#include "lib/libbpf.h"
inline uint16 read16(uint8 *addr, uint pos) {
#ifdef ARCH_LSB
@@ -58,8 +51,21 @@ inline uint16 read16(uint8 *addr, uint pos) {
}
//platform-specific global functions
void alert(char *s, ...);
void dprintf(char *s, ...);
void alert(char *, ...);
void dprintf(char *, ...);
void dprintf(uint, char *, ...);
namespace source {
enum {
none = 0,
debug,
cpu,
ppu,
smp,
dsp,
bus,
};
};
//various class interfaces
#include "interface.h"
+196 -147
View File
@@ -1,62 +1,114 @@
#include "../base.h"
#include "database.cpp"
Cartridge cartridge;
void Cartridge::read_dbi() {
info.srtc = false;
info.sdd1 = false;
info.c4 = false;
info.dsp1 = false;
info.dsp2 = false;
info.obc1 = false;
info.dsp1_mapper = 0;
info.header_index = 0x7fc0;
info.mapper = PCB;
strcpy(info.name, dbi.name);
strcpy(info.pcb, dbi.pcb);
info.region = NTSC;
info.cart_mmio = false;
info.rom_size = dbi.rom;
info.ram_size = dbi.ram;
}
void Cartridge::read_header() {
cart.srtc = false;
cart.sdd1 = false;
cart.c4 = false;
cart.dsp2 = false;
cart.obc1 = false;
info.srtc = false;
info.sdd1 = false;
info.c4 = false;
info.dsp1 = false;
info.dsp2 = false;
info.obc1 = false;
if(cart.header_index == 0x7fc0 && cart.rom_size >= 0x401000) {
cart.mapper = EXLOROM;
} else if(cart.header_index == 0x7fc0 && rom[cart.header_index + MAPPER] == 0x32) {
cart.mapper = EXLOROM;
} else if(cart.header_index == 0x7fc0) {
cart.mapper = LOROM;
} else if(cart.header_index == 0xffc0) {
cart.mapper = HIROM;
} else { //cart.header_index == 0x40ffc0
cart.mapper = EXHIROM;
info.dsp1_mapper = 0;
if(info.header_index == 0x7fc0 && info.rom_size >= 0x401000) {
info.mapper = EXLOROM;
strcpy(info.pcb, "UNL-EXLOROM");
} else if(info.header_index == 0x7fc0 && rom[info.header_index + MAPPER] == 0x32) {
info.mapper = EXLOROM;
strcpy(info.pcb, "UNL-EXLOROM");
} else if(info.header_index == 0x7fc0) {
info.mapper = LOROM;
strcpy(info.pcb, "UNL-LOROM");
} else if(info.header_index == 0xffc0) {
info.mapper = HIROM;
strcpy(info.pcb, "UNL-HIROM");
} else { //info.header_index == 0x40ffc0
info.mapper = EXHIROM;
strcpy(info.pcb, "UNL-EXHIROM");
}
uint8 mapper = rom[cart.header_index + MAPPER];
uint8 rom_type = rom[cart.header_index + ROM_TYPE];
uint8 mapper = rom[info.header_index + MAPPER];
uint8 rom_type = rom[info.header_index + ROM_TYPE];
if(mapper == 0x35 && rom_type == 0x55) {
cart.srtc = true;
info.srtc = true;
}
if(mapper == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
cart.sdd1 = true;
info.sdd1 = true;
}
if(mapper == 0x20 && rom_type == 0xf3) {
cart.c4 = true;
info.c4 = true;
}
if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) {
info.dsp1 = true;
}
if(mapper == 0x30 && rom_type == 0x05) {
info.dsp1 = true;
}
if(mapper == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) {
info.dsp1 = true;
}
if(info.dsp1 == true) {
if((mapper & 0x2f) == 0x20 && info.rom_size <= 0x100000) {
info.dsp1_mapper = DSP1_LOROM_1MB;
} else if((mapper & 0x2f) == 0x20) {
info.dsp1_mapper = DSP1_LOROM_2MB;
} else if((mapper & 0x2f) == 0x21) {
info.dsp1_mapper = DSP1_HIROM;
}
}
if(mapper == 0x20 && rom_type == 0x05) {
cart.dsp2 = true;
info.dsp2 = true;
}
if(mapper == 0x30 && rom_type == 0x25) {
cart.obc1 = true;
info.obc1 = true;
}
cart.cart_mmio = cart.c4 | cart.dsp2 | cart.obc1;
info.cart_mmio = info.c4 | info.dsp1 | info.dsp2 | info.obc1;
if(rom[cart.header_index + SRAM_SIZE] & 7) {
cart.sram_size = 1024 << (rom[cart.header_index + SRAM_SIZE] & 7);
if(rom[info.header_index + SRAM_SIZE] & 7) {
info.ram_size = 1024 << (rom[info.header_index + SRAM_SIZE] & 7);
} else {
cart.sram_size = 0;
info.ram_size = 0;
}
cart.region = ((rom[cart.header_index + REGION] & 0x7f) < 2) ? NTSC : PAL;
memcpy(&cart.name, &rom[cart.header_index + CART_NAME], 21);
cart.name[21] = 0;
memcpy(&info.name, &rom[info.header_index + CART_NAME], 21);
info.name[21] = 0;
for(int i = 0; i < 22; i++) {
if(cart.name[i] & 0x80) {
cart.name[i] = '?';
if(info.name[i] & 0x80) {
info.name[i] = '?';
}
}
}
@@ -66,9 +118,9 @@ int32 score_lo = 0,
score_hi = 0,
score_ex = 0;
if(rom_size < 0x010000) {
//cart too small to be anything else
cart.header_index = 0x007fc0;
if(info.rom_size < 0x010000) {
//cart too small to be anything but lorom
info.header_index = 0x007fc0;
return;
}
@@ -90,6 +142,9 @@ int32 score_lo = 0,
if(rom[0x7fc0 + LICENSE] < 3)score_lo++;
if(rom[0xffc0 + LICENSE] < 3)score_hi++;
if(rom[0x7fc0 + RESH] & 0x80)score_lo += 2;
if(rom[0xffc0 + RESH] & 0x80)score_hi += 2;
uint16 cksum, icksum;
cksum = rom[0x7fc0 + CKSUM] | (rom[0x7fc0 + CKSUM + 1] << 8);
icksum = rom[0x7fc0 + ICKSUM] | (rom[0x7fc0 + ICKSUM + 1] << 8);
@@ -103,7 +158,7 @@ uint16 cksum, icksum;
score_hi += 8;
}
if(rom_size < 0x401000) {
if(info.rom_size < 0x401000) {
score_ex = 0;
} else {
if(rom[0x7fc0 + MAPPER] == 0x32)score_lo++;
@@ -111,100 +166,84 @@ uint16 cksum, icksum;
}
if(score_lo >= score_hi && score_lo >= score_ex) {
cart.header_index = 0x007fc0;
info.header_index = 0x007fc0;
} else if(score_hi >= score_ex) {
cart.header_index = 0x00ffc0;
info.header_index = 0x00ffc0;
} else {
cart.header_index = 0x40ffc0;
info.header_index = 0x40ffc0;
}
}
void Cartridge::load_sram() {
if(cart.sram_size == 0) {
if(info.ram_size == 0) {
sram = 0;
return;
}
FileReader ff(sram_fn);
if(!ff.ready()) {
sram = (uint8*)malloc(cart.sram_size);
memset(sram, 0, cart.sram_size);
sram = (uint8*)malloc(info.ram_size);
memset(sram, 0xff, info.ram_size);
return;
}
sram = ff.read(cart.sram_size);
sram = ff.read(info.ram_size);
}
void Cartridge::save_sram() {
if(cart.sram_size == 0)return;
if(info.ram_size == 0)return;
FileWriter ff(sram_fn);
if(!ff.ready())return;
ff.write(sram, cart.sram_size);
ff.write(sram, info.ram_size);
}
void Cartridge::load_rom(Reader *rf) {
base_rom = rf->read();
rom_size = rf->size();
void Cartridge::load_rom(Reader &rf) {
uint size = rf.size();
bool header = ((size & 0x7fff) == 512);
info.rom_size = size - (header ? 512 : 0);
if(info.rom_size & 0x7fff) {
info.rom_size += 0x8000 - (info.rom_size & 0x7fff);
}
if((rom_size & 0x7fff) == 0x0200) {
rom = base_rom + 512;
rom_size -= 512;
uint8 *base_rom = rf.read(info.rom_size + (header ? 512 : 0));
if(header) {
memcpy(rom_header, base_rom, 512);
} else {
rom = base_rom;
memset(rom_header, 0x00, 512);
}
cart.rom_size = rom_size;
rom = (uint8*)malloc(info.rom_size);
memcpy(rom, base_rom + (header ? 512 : 0), info.rom_size);
SafeFree(base_rom);
cart.crc32 = 0xffffffff;
for(int32 i = 0; i < cart.rom_size; i++) {
cart.crc32 = crc32_adjust(cart.crc32, rom[i]);
info.crc32 = 0xffffffff;
for(int32 i = 0; i < info.rom_size; i++) {
info.crc32 = crc32_adjust(info.crc32, rom[i]);
}
cart.crc32 = ~cart.crc32;
info.crc32 = ~info.crc32;
}
void Cartridge::patch_rom(Reader *rf) {
uint8 *patch_data = rf->read();
uint32 patch_size = rf->size();
BPF bpf;
if(patch_size < 34)return;
void Cartridge::patch_rom(Reader &rf) {
UPS<ramfile, ramfile, ramfile> ups;
uint patchsize = rf.size();
uint8 *patchdata = rf.read();
uint32 target;
target = patch_data[BPF::INDEX_FORMAT + 0] << 0;
target |= patch_data[BPF::INDEX_FORMAT + 1] << 8;
target |= patch_data[BPF::INDEX_FORMAT + 2] << 16;
target |= patch_data[BPF::INDEX_FORMAT + 3] << 24;
if(target != BPF::FORMAT_SNES) {
alert("Warning: BPF patch file is not in SNES format!\n\n"
"The patch will still be applied, but it will not be "
"possible to determine whether the patch was created "
"against an image with a header or without a header.\n\n"
"bsnes is now forced to assume the patch was created "
"against a headerless source image. If this is not the "
"case, then patching will fail!\n\n"
"If you are the author of this patch, please recreate "
"the patch in SNES format.\n\n"
"If you are not the patch author, please contact the "
"author and ask them to create an SNES format BPF patch.");
}
fopen(ups.original, 0, file::mode_writeread);
fopen(ups.modified, 0, file::mode_writeread);
fopen(ups.patch.fp, 0, file::mode_writeread);
if(bpf.apply_patch(patch_size, patch_data, rom_size, rom) == true) {
SafeFree(base_rom);
uint8 *temp = bpf.get_output_handle(rom_size);
base_rom = (uint8*)malloc(rom_size);
memcpy(base_rom, temp, rom_size);
rom = base_rom;
cart.rom_size = rom_size;
} else {
alert("Failed to apply patch.\n\nThis could be because the patch itself "
"does not match its internal checksum, because the ROM loaded does not "
"match the patch information for either the original or modified file, "
"or because the patched file does not match the checksum of either the "
"original or modified file that is stored inside the patch.\n\n"
"The original ROM image will be used instead.");
fwrite(ups.original, rom, info.rom_size);
fwrite(ups.patch.fp, patchdata, patchsize);
if(ups.apply() == true) {
info.crc32 = ups.modified_crc32;
info.rom_size = ups.modified_filesize;
rom = (uint8*)realloc(rom, info.rom_size);
fseek(ups.modified, 0, file::seek_start);
fread(ups.modified, rom, info.rom_size);
}
SafeFree(patch_data);
}
bool Cartridge::load(const char *fn) {
@@ -216,15 +255,16 @@ bool Cartridge::load(const char *fn) {
strcpy(rom_fn, fn);
switch(Reader::detect(rom_fn)) {
case Reader::RF_NORMAL: {
FileReader ff(rom_fn);
if(!ff.ready()) {
alert("Error loading image file (%s)!", rom_fn);
return false;
}
load_rom(static_cast<Reader*>(&ff));
break;
}
load_rom(ff);
} break;
#ifdef GZIP_SUPPORT
case Reader::RF_GZ: {
GZReader gf(rom_fn);
@@ -232,27 +272,27 @@ bool Cartridge::load(const char *fn) {
alert("Error loading image file (%s)!", rom_fn);
return false;
}
load_rom(static_cast<Reader*>(&gf));
break;
}
load_rom(gf);
} break;
case Reader::RF_ZIP: {
ZipReader zf(rom_fn);
load_rom(static_cast<Reader*>(&zf));
break;
}
load_rom(zf);
} break;
#endif
#ifdef JMA_SUPPORT
case Reader::RF_JMA: {
try {
JMAReader jf(rom_fn);
load_rom(static_cast<Reader*>(&jf));
load_rom(jf);
} catch(JMA::jma_errors jma_error) {
alert("Error loading image file (%s)!", rom_fn);
return false;
}
break;
}
} break;
#endif
}
//remove ROM extension
@@ -264,39 +304,24 @@ bool Cartridge::load(const char *fn) {
}
}
//check for bpf patch
#ifdef GZIP_SUPPORT
strcpy(patch_fn, sram_fn);
strcat(patch_fn, ".bpz");
if(fexists(patch_fn)) {
ZipReader zf(patch_fn);
patch_rom(static_cast<Reader*>(&zf));
} else {
#endif
strcpy(patch_fn, sram_fn);
strcat(patch_fn, ".bpf");
if(fexists(patch_fn)) {
FileReader ff(patch_fn);
patch_rom(static_cast<Reader*>(&ff));
}
#ifdef GZIP_SUPPORT
}
#endif
//add SRAM extension
strcat(sram_fn, ".");
strcat(sram_fn, config::fs.save_ext.sget());
//override default path (current directory)?
if(strmatch(config::fs.save_path.sget(), "") == false) {
//remove path if fs.sram_path was specified
string new_fn, parts;
stringarray save_path;
strcpy(save_path, config::fs.save_path.sget());
replace(save_path, "\\", "/");
if(strlen(save_path) && !strend(save_path, "/")) { strcat(save_path, "/"); }
if(strlen(save_path) != 0) {
//override default path (current directory)
stringarray new_fn, parts;
strcpy(new_fn, sram_fn);
replace(new_fn, "\\", "/");
split(parts, "/", new_fn);
//add new SRAM path
strcpy(new_fn, config::fs.save_path.sget());
strcpy(new_fn, save_path);
//append fs.base_path if fs.sram_path is not fully-qualified path
if(strbegin(new_fn, "./") == true) {
@@ -316,15 +341,44 @@ bool Cartridge::load(const char *fn) {
strrtrim(cheat_fn, config::fs.save_ext.sget());
strrtrim(cheat_fn, ".");
strcat(cheat_fn, ".cht");
if(fexists(cheat_fn) == true) {
FileReader ff(cheat_fn);
cheat.load(static_cast<Reader*>(&ff));
cheat.load(ff);
}
//load patch file if it exists
strcpy(patch_fn, sram_fn);
strrtrim(patch_fn, config::fs.save_ext.sget());
strrtrim(patch_fn, ".");
strcat(patch_fn, ".ups");
if(fexists(patch_fn) == true) {
FileReader ff(patch_fn);
patch_rom(ff);
}
#ifdef GZIP_SUPPORT
else {
strrtrim(patch_fn, ".ups");
strcat(patch_fn, ".upz");
if(fexists(patch_fn) == true) {
ZipReader zf(patch_fn);
patch_rom(zf);
}
}
#endif
if(read_database() == true) {
read_dbi();
} else {
find_header();
read_header();
}
find_header();
read_header();
load_sram();
cart_loaded = true;
r_mem->load_cart();
return true;
}
@@ -334,18 +388,13 @@ bool Cartridge::unload() {
r_mem->unload_cart();
if(base_rom) {
SafeFree(base_rom);
}
if(sram) {
save_sram();
SafeFree(sram);
}
if(sram) { save_sram(); }
SafeFree(rom);
SafeFree(sram);
if(cheat.count() > 0 || fexists(cheat_fn)) {
FileWriter ff(cheat_fn);
cheat.save(static_cast<Writer*>(&ff));
cheat.save(ff);
cheat.clear();
}
@@ -354,12 +403,12 @@ bool Cartridge::unload() {
}
Cartridge::Cartridge() {
load_database();
cart_loaded = false;
base_rom = 0;
rom = 0;
sram = 0;
rom_size = 0;
rom = 0;
sram = 0;
}
Cartridge::~Cartridge() {
+40 -12
View File
@@ -1,10 +1,24 @@
class Cartridge {
public:
/*****
* cart database
*****/
#include "db/db.h"
db_item dbi;
uint8 *database;
uint database_size;
uint database_blocksize;
void load_database();
bool read_database();
//
bool cart_loaded;
char rom_fn[4096], sram_fn[4096], cheat_fn[4096], patch_fn[4096];
uint8 *base_rom, *rom, *sram;
uint32 rom_size;
uint8 rom_header[512], *rom, *sram;
enum {
//header fields
@@ -18,28 +32,35 @@ enum {
VERSION = 0x1b,
ICKSUM = 0x1c,
CKSUM = 0x1e,
RESL = 0x3c,
RESH = 0x3d,
//regions
NTSC = 0,
PAL = 1,
//memory mappers
PCB = 0x00,
LOROM = 0x20,
HIROM = 0x21,
EXLOROM = 0x22,
EXHIROM = 0x25,
//special chip memory mappers
DSP1_LOROM_1MB = 1,
DSP1_LOROM_2MB = 2,
DSP1_HIROM = 3,
};
struct {
uint32 crc32;
uint32 header_index;
char name[128];
char pcb[32];
char name[32];
uint32 rom_size;
uint32 sram_size;
bool region;
uint32 mapper;
uint region;
uint mapper;
uint rom_size;
uint ram_size;
//set to true for games that need cart MMIO mapping (c4, dsp-n, ...),
//for games that map outside the standard MMIO range of $2000-$5fff
@@ -47,14 +68,21 @@ struct {
bool srtc;
bool sdd1;
bool c4;
bool dsp1;
bool dsp2;
bool obc1;
} cart;
void load_rom(Reader *rf);
void patch_rom(Reader *rf);
uint dsp1_mapper;
//HiROM / LoROM specific code
uint header_index;
} info;
void load_rom(Reader &rf);
void patch_rom(Reader &rf);
void load_sram();
void save_sram();
void read_dbi();
void find_header();
void read_header();
bool loaded() { return cart_loaded; }
+37
View File
@@ -0,0 +1,37 @@
void Cartridge::load_database() {
database = 0;
database_size = 0;
FILE *fp;
fp = fopen("cart.db", "rb");
if(!fp)return;
uint size = fsize(fp);
if(size < 8) {
fclose(fp);
return;
}
database = (uint8*)malloc(size);
fread(database, 1, size, fp);
fclose(fp);
database_blocksize = (database[6] << 0) | (database[7] << 8);
database_size = (size - 8) / database_blocksize;
}
bool Cartridge::read_database() {
uint i, crc32;
for(i = 0; i < database_size; i++) {
uint8 *p = database + 8 + (i * database_blocksize);
crc32 = *(p++) << 0;
crc32 |= *(p++) << 8;
crc32 |= *(p++) << 16;
crc32 |= *(p++) << 24;
if(crc32 == cartridge.info.crc32)break;
}
if(i >= database_size)return false;
db_read(dbi, database + 8 + (i * database_blocksize));
return true;
}
Binary file not shown.
+47
View File
@@ -0,0 +1,47 @@
[0x7aedd703]
name = "Der Langrisser (Japan) [!]"
pcb = "SHVC-1A3M-30"
rom = 16mbit
ram = 64kbit
[0x35f9eecc]
name = "Der Langrisser (Japan) (V1.1)"
pcb = "SHVC-1A3M-30" ;unverified (guess)
rom = 16mbit
ram = 64kbit
[0x19bdcb19]
name = "Derby Stallion '96 (Japan) [!]"
pcb = "BSC-1A5M-01"
rom = 24mbit
ram = 256kbit
[0x9684526d]
name = "Romancing SaGa (Japan) (V1.1) [!]"
pcb = "SHVC-1A3B-12"
rom = 8mbit
ram = 64kbit
[0x675b6382]
name = "RPG Tsukuru 2 (Japan)"
pcb = "BSC-1A7M-01" ;unverified
rom = 16mbit
ram = 512kbit
[0xa5c0045e]
name = "Secret of Evermore (USA) [!]"
pcb = "SHVC-1J3M-20"
rom = 32mbit
ram = 64kbit
[0x5ebf7246]
name = "Sound Novel Tsukuru (Japan) [!]"
pcb = "BSC-1A7M-10"
rom = 24mbit
ram = 512kbit
[0x64a91e64]
name = "Wanderers from Ys (USA) [!]"
pcb = "SHVC-1A3B-12"
rom = 8mbit
ram = 64kbit
+3
View File
@@ -0,0 +1,3 @@
cl /nologo /O2 dbcreate.cpp
@pause
@del *.obj
+1
View File
@@ -0,0 +1 @@
@del *.exe
+2
View File
@@ -0,0 +1,2 @@
dbcreate
@copy cart.db ..\..\..\cart.db
+47
View File
@@ -0,0 +1,47 @@
struct db_item {
uint32 crc32;
char name[128];
char pcb [32];
uint32 rom;
uint32 ram;
};
void db_write(FILE *fp, db_item &dbi) {
fputc(dbi.crc32 >> 0, fp);
fputc(dbi.crc32 >> 8, fp);
fputc(dbi.crc32 >> 16, fp);
fputc(dbi.crc32 >> 24, fp);
fwrite(dbi.name, 1, 128, fp);
fwrite(dbi.pcb, 1, 32, fp);
fputc(dbi.rom >> 0, fp);
fputc(dbi.rom >> 8, fp);
fputc(dbi.rom >> 16, fp);
fputc(dbi.rom >> 24, fp);
fputc(dbi.ram >> 0, fp);
fputc(dbi.ram >> 8, fp);
fputc(dbi.ram >> 16, fp);
fputc(dbi.ram >> 24, fp);
}
void db_read(db_item &dbi, uint8 *data) {
dbi.crc32 = (*data++) << 0;
dbi.crc32 |= (*data++) << 8;
dbi.crc32 |= (*data++) << 16;
dbi.crc32 |= (*data++) << 24;
memcpy(dbi.name, data, 128); dbi.name[127] = 0; data += 128;
memcpy(dbi.pcb, data, 32); dbi.pcb [ 31] = 0; data += 32;
dbi.rom = (*data++) << 0;
dbi.rom |= (*data++) << 8;
dbi.rom |= (*data++) << 16;
dbi.rom |= (*data++) << 24;
dbi.ram = (*data++) << 0;
dbi.ram |= (*data++) << 8;
dbi.ram |= (*data++) << 16;
dbi.ram |= (*data++) << 24;
}
+117
View File
@@ -0,0 +1,117 @@
#include "../../lib/libbase.h"
#include "../../lib/libvector.h"
#include "../../lib/libstring.h"
#include "../../lib/libstring.cpp"
#include "db.h"
FILE *fp;
uint decode_size(substring &str) {
//hex encoding
if(strbegin(str, "0x")) {
strltrim(str, "0x");
return strhex(str);
}
//mbit encoding
if(strend(str, "mbit")) {
strrtrim(str, "mbit");
return strdec(str) * 1024 * 1024 / 8;
}
//kbit encoding
if(strend(str, "kbit")) {
strrtrim(str, "kbit");
return strdec(str) * 1024 / 8;
}
//decimal encoding
return strdec(str);
}
void build_block(substring &block) {
string line, hashpart, part;
split(line, "\n", block);
if(strbegin(line[0], "[") == false) {
printf("error: invalid block detected: '%s'\n", strptr(line[0]));
return;
}
strltrim(line[0], "[");
strrtrim(line[0], "]");
replace(line[0], "0x", "");
split(hashpart, ",", line[0]);
db_item dbi;
dbi.crc32 = 0;
*dbi.name = 0;
*dbi.pcb = 0;
dbi.rom = 0;
dbi.ram = 0;
for(int i = 1; i < count(line); i++) {
uint pos;
if(strpos(line[i], ";", pos) == true) {
strset(line[i], pos, 0);
}
if(strmatch(line[i], ""))continue;
split(part, "=", line[i]);
strunquote(part[1]);
if(strmatch(part[0], "name")) {
strncpy(dbi.name, strptr(part[1]), 128);
dbi.name[128] = 0;
}
if(strmatch(part[0], "pcb")) {
strncpy(dbi.pcb, strptr(part[1]), 32);
dbi.pcb[31] = 0;
}
if(strmatch(part[0], "rom")) {
dbi.rom = decode_size(part[1]);
}
if(strmatch(part[0], "ram")) {
dbi.ram = decode_size(part[1]);
}
}
for(int i = 0; i < count(hashpart); i++) {
dbi.crc32 = strhex(hashpart[i]);
db_write(fp, dbi);
}
}
void build_database() {
string data, block;
if(strfread(data, "cartdb.txt") == false)return;
fp = fopen("cart.db", "wb");
fprintf(fp, "SNESDB");
uint blocksize = 4 + 128 + 32 + 4 + 4;
fputc(blocksize >> 0, fp);
fputc(blocksize >> 8, fp);
replace (data, "\r", "");
qreplace(data, " ", "");
qreplace(data, "\t", "");
split(block, "\n\n", data);
for(int i = 0; i < count(block); i++) {
build_block(block[i]);
}
fclose(fp);
}
int main() {
build_database();
return 0;
}
+13 -11
View File
@@ -1,5 +1,7 @@
#include "../base.h"
Cheat cheat;
/*****
* string <> binary code translation routines
* decode() "7e1234:56" -> 0x7e123456
@@ -7,7 +9,7 @@
*****/
bool Cheat::decode(char *str, uint32 &addr, uint8 &data, uint8 &type) {
string t, part;
stringarray t, part;
strcpy(t, str);
strlower(t);
if(strlen(t) == 8 || (strlen(t) == 9 && strptr(t)[6] == ':')) {
@@ -266,19 +268,19 @@ void Cheat::disable(uint32 n) {
* cheat file manipulation routines
*****/
bool Cheat::load(Reader *rf) {
if(!rf->ready())return false;
bool Cheat::load(Reader &rf) {
if(!rf.ready())return false;
uint8 *raw_data = rf->read();
string data;
raw_data[rf->size()] = 0;
uint8 *raw_data = rf.read();
stringarray data, line;
raw_data[rf.size()] = 0;
strcpy(data, (char*)raw_data);
SafeFree(raw_data);
replace(data, "\r\n", "\n");
string line;
split(line, "\n", data);
for(int i = 0; i < ::count(line); i++) {
string part;
stringarray part;
uint8 en = *(strptr(line[i]));
if(en == '+') {
strltrim(line[i], "+");
@@ -297,8 +299,8 @@ string line;
return true;
}
bool Cheat::save(Writer *wf) {
if(!wf->ready())return false;
bool Cheat::save(Writer &wf) {
if(!wf.ready())return false;
string data;
char t[4096];
@@ -308,7 +310,7 @@ char t[4096];
strcat(data, t);
}
wf->write((uint8*)strptr(data), strlen(data));
wf.write((uint8*)strptr(data), strlen(data));
return true;
}
+2 -2
View File
@@ -38,8 +38,8 @@ public:
bool enabled(uint32 n);
void enable (uint32 n);
void disable(uint32 n);
bool load(Reader *rf);
bool save(Writer *wf);
bool load(Reader &rf);
bool save(Writer &wf);
void clear();
Cheat();
+2
View File
@@ -7,6 +7,8 @@
#include "../../base.h"
C4 *c4;
#include "c4data.cpp"
#include "c4fn.cpp"
#include "c4oam.cpp"
+2
View File
@@ -92,3 +92,5 @@ public:
C4();
};
extern C4 *c4;
+57 -62
View File
@@ -1,7 +1,7 @@
//Build OAM
void C4::op00_00() {
uint32 oamptr = ram[0x626] << 2;
for(int32 i=0x1fd;i>oamptr && i>=0;i-=4) {
for(int32 i = 0x1fd; i > oamptr && i >= 0; i -= 4) {
//clear oam-to-be
if(i >= 0)ram[i] = 0xe0;
}
@@ -19,58 +19,55 @@ uint8 sprcount;
sprcount = 128 - ram[0x626];
uint8 offset = (ram[0x626] & 3) * 2;
for(int pri=0x30;pri>=0;pri-=0x10) {
uint32 srcptr = 0x220;
for(int i=ram[0x620];i>0 && sprcount>0;i--, srcptr+=16) {
if((ram[srcptr + 4] & 0x30) != pri)continue;
sprx = readw(srcptr) - globalx;
spry = readw(srcptr + 2) - globaly;
sprname = ram[srcptr + 5];
sprattr = ram[srcptr + 4] | ram[srcptr + 6];
uint32 srcptr = 0x220;
for(int i = ram[0x620]; i > 0 && sprcount > 0; i--, srcptr += 16) {
sprx = readw(srcptr) - globalx;
spry = readw(srcptr + 2) - globaly;
sprname = ram[srcptr + 5];
sprattr = ram[srcptr + 4] | ram[srcptr + 6];
uint32 spraddr = readl(srcptr + 7);
if(r_mem->read(spraddr)) {
int16 x, y;
for(int sprcnt=r_mem->read(spraddr++);sprcnt>0 && sprcount>0;sprcnt--, spraddr+=4) {
x = (int8)r_mem->read(spraddr + 1);
if(sprattr & 0x40) {
x = -x - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
uint32 spraddr = readl(srcptr + 7);
if(r_mem->read(spraddr)) {
int16 x, y;
for(int sprcnt = r_mem->read(spraddr++); sprcnt > 0 && sprcount > 0; sprcnt--, spraddr += 4) {
x = (int8)r_mem->read(spraddr + 1);
if(sprattr & 0x40) {
x = -x - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
}
x += sprx;
if(x >= -16 && x <= 272) {
y = (int8)r_mem->read(spraddr + 2);
if(sprattr & 0x80) {
y = -y - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
}
x += sprx;
if(x >= -16 && x <= 272) {
y = (int8)r_mem->read(spraddr + 2);
if(sprattr & 0x80) {
y = -y - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
}
y += spry;
if(y >= -16 && y <= 224) {
ram[oamptr ] = (uint8)x;
ram[oamptr + 1] = (uint8)y;
ram[oamptr + 2] = sprname + r_mem->read(spraddr + 3);
ram[oamptr + 3] = sprattr ^ (r_mem->read(spraddr) & 0xc0);
ram[oamptr2] &= ~(3 << offset);
if(x & 0x100)ram[oamptr2] |= 1 << offset;
if(r_mem->read(spraddr) & 0x20)ram[oamptr2] |= 2 << offset;
oamptr += 4;
sprcount--;
offset = (offset + 2) & 6;
if(!offset)oamptr2++;
}
y += spry;
if(y >= -16 && y <= 224) {
ram[oamptr ] = (uint8)x;
ram[oamptr + 1] = (uint8)y;
ram[oamptr + 2] = sprname + r_mem->read(spraddr + 3);
ram[oamptr + 3] = sprattr ^ (r_mem->read(spraddr) & 0xc0);
ram[oamptr2] &= ~(3 << offset);
if(x & 0x100)ram[oamptr2] |= 1 << offset;
if(r_mem->read(spraddr) & 0x20)ram[oamptr2] |= 2 << offset;
oamptr += 4;
sprcount--;
offset = (offset + 2) & 6;
if(!offset)oamptr2++;
}
}
} else if(sprcount > 0) {
ram[oamptr ] = (uint8)sprx;
ram[oamptr + 1] = (uint8)spry;
ram[oamptr + 2] = sprname;
ram[oamptr + 3] = sprattr;
ram[oamptr2] &= ~(3 << offset);
if(sprx & 0x100)ram[oamptr2] |= 3 << offset;
else ram[oamptr2] |= 2 << offset;
oamptr += 4;
sprcount--;
offset = (offset + 2) & 6;
if(!offset)oamptr2++;
}
} else if(sprcount > 0) {
ram[oamptr ] = (uint8)sprx;
ram[oamptr + 1] = (uint8)spry;
ram[oamptr + 2] = sprname;
ram[oamptr + 3] = sprattr;
ram[oamptr2] &= ~(3 << offset);
if(sprx & 0x100)ram[oamptr2] |= 3 << offset;
else ram[oamptr2] |= 2 << offset;
oamptr += 4;
sprcount--;
offset = (offset + 2) & 6;
if(!offset)oamptr2++;
}
}
}
@@ -178,13 +175,11 @@ uint32 waveptr = read(0x1f83);
uint16 mask1 = 0xc0c0;
uint16 mask2 = 0x3f3f;
int32 i, j;
int16 height, temp;
for(j = 0; j < 0x10; j++) {
for(int j = 0; j < 0x10; j++) {
do {
height = -((int8)ram[waveptr + 0xb00]) - 16;
for(i = 0; i < 40; i++) {
temp = readw(destptr + wave_data[i]) & mask2;
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
for(int i = 0; i < 40; i++) {
uint16 temp = readw(destptr + wave_data[i]) & mask2;
if(height >= 0) {
if(height < 8) {
temp |= mask1 & readw(0xa00 + height * 2);
@@ -202,22 +197,22 @@ int16 height, temp;
destptr += 16;
do {
height = -((int8)ram[waveptr + 0xb00]) - 16;
for(i = 0; i < 40; i++) {
temp = readw(destptr + wave_data[i]) & mask2;
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
for(int i = 0; i < 40; i++) {
uint16 temp = readw(destptr + wave_data[i]) & mask2;
if(height >= 0) {
if(height < 8) {
temp |= mask1 & readw(0xa10 + height * 2);
} else {
temp |= mask1 & 0xff00;
}
writew(destptr + wave_data[i], temp);
height++;
}
waveptr = (waveptr + 1) & 0x7f;
mask1 = (mask1 >> 2) | (mask1 << 6);
mask2 = (mask2 >> 2) | (mask2 << 6);
writew(destptr + wave_data[i], temp);
height++;
}
waveptr = (waveptr + 1) & 0x7f;
mask1 = (mask1 >> 2) | (mask1 << 6);
mask2 = (mask2 >> 2) | (mask2 << 6);
} while(mask1 != 0xc0c0);
destptr += 16;
}
+57
View File
@@ -0,0 +1,57 @@
#include "../../base.h"
DSP1 *dsp1;
#include "dsp1emu.cpp"
void DSP1::init() {}
void DSP1::enable() {}
void DSP1::power() {
reset();
}
void DSP1::reset() {
dsp1.reset();
}
/*****
* addr_decode()
* determine whether address is accessing
* data register (DR) or status register (SR)
* -- 0 (false) = DR
* -- 1 (true ) = SR
*
* note: there is no need to bounds check addresses,
* as memory mapper will not allow DSP1 accesses outside
* of expected ranges
*****/
bool DSP1::addr_decode(uint16 addr) {
switch(cartridge.info.dsp1_mapper) {
case Cartridge::DSP1_LOROM_1MB:
//$[20-3f]:[8000-bfff] = DR, $[20-3f]:[c000-ffff] = SR
return (addr >= 0xc000);
case Cartridge::DSP1_LOROM_2MB:
//$[60-6f]:[0000-3fff] = DR, $[60-6f]:[4000-7fff] = SR
return (addr >= 0x4000);
case Cartridge::DSP1_HIROM:
//$[00-1f]:[6000-6fff] = DR, $[00-1f]:[7000-7fff] = SR
return (addr >= 0x7000);
}
return 0;
}
uint8 DSP1::read(uint16 addr) {
return (addr_decode(addr) == 0) ? dsp1.getDr() : dsp1.getSr();
}
void DSP1::write(uint16 addr, uint8 data) {
if(addr_decode(addr) == 0) {
dsp1.setDr(data);
}
}
+18
View File
@@ -0,0 +1,18 @@
#include "dsp1emu.h"
class DSP1 {
private:
Dsp1 dsp1;
public:
void init();
void enable();
void power();
void reset();
bool addr_decode(uint16 addr);
uint8 read (uint16 addr);
void write(uint16 addr, uint8 data);
};
extern DSP1 *dsp1;
File diff suppressed because it is too large. Load diff
+127
View File
@@ -0,0 +1,127 @@
// DSP-1's emulation code
//
// Based on research by Overload, The Dumper, Neviksti and Andreas Naive
// Date: June 2006
#ifndef __DSP1EMUL_H
#define __DSP1EMUL_H
#define DSP1_VERSION 0x0102
class Dsp1
{
public:
// The DSP-1 status register has 16 bits, but only
// the upper 8 bits can be accessed from an external device, so all these
// positions are referred to the upper byte (bits D8 to D15)
enum SrFlags {DRC=0x04, DRS=0x10, RQM=0x80};
// According to Overload's docs, these are the meanings of the flags:
// DRC: The Data Register Control (DRC) bit specifies the data transfer length to and from the host CPU.
// 0: Data transfer to and from the DSP-1 is 16 bits.
// 1: Data transfer to and from the DSP-1 is 8 bits.
// DRS: The Data Register Status (DRS) bit indicates the data transfer status in the case of transfering 16-bit data.
// 0: Data transfer has terminated.
// 1: Data transfer in progress.
// RQM: The Request for Master (RQM) indicates that the DSP1 is requesting host CPU for data read/write.
// 0: Internal Data Register Transfer.
// 1: External Data Register Transfer.
Dsp1();
uint8 getSr(); // return the status register's high byte
uint8 getDr();
void setDr(uint8 iDr);
void reset();
private:
enum FsmMajorState {WAIT_COMMAND, READ_DATA, WRITE_DATA};
enum MaxDataAccesses {MAX_READS=7, MAX_WRITES=1024};
struct Command {
void (Dsp1::*callback)(int16 *, int16 *);
unsigned int reads;
unsigned int writes;
};
static const Command mCommandTable[];
static const int16 MaxAZS_Exp[16];
static const int16 SinTable[];
static const int16 MulTable[];
static const uint16 DataRom[];
struct SharedData { // some RAM variables shared between commands
int16 MatrixA[3][3]; // attitude matrix A
int16 MatrixB[3][3];
int16 MatrixC[3][3];
int16 CentreX, CentreY, CentreZ; // center of projection
int16 CentreZ_C, CentreZ_E;
int16 VOffset; // vertical offset of the screen with regard to the centre of projection
int16 Les, C_Les, E_Les;
int16 SinAas, CosAas;
int16 SinAzs, CosAzs;
int16 SinAZS, CosAZS;
int16 SecAZS_C1, SecAZS_E1;
int16 SecAZS_C2, SecAZS_E2;
int16 Nx, Ny, Nz; // normal vector to the screen (norm 1, points toward the center of projection)
int16 Gx, Gy, Gz; // center of the screen (global coordinates)
int16 Hx, Hy; // horizontal vector of the screen (Hz=0, norm 1, points toward the right of the screen)
int16 Vx, Vy, Vz; // vertical vector of the screen (norm 1, points toward the top of the screen)
} shared;
uint8 mSr; // status register
int mSrLowByteAccess;
uint16 mDr; // "internal" representation of the data register
FsmMajorState mFsmMajorState; // current major state of the FSM
uint8 mCommand; // current command processed by the FSM
uint8 mDataCounter; // #uint16 read/writes counter used by the FSM
int16 mReadBuffer[MAX_READS];
int16 mWriteBuffer[MAX_WRITES];
bool mFreeze; // need explanation? ;)
void fsmStep(bool read, uint8 &data); // FSM logic
// commands
void memoryTest(int16 *input, int16 *output);
void memoryDump(int16 *input, int16 *output);
void memorySize(int16 *input, int16 *output);
void multiply(int16* input, int16* output);
void multiply2(int16* input, int16* output);
void inverse(int16 *input, int16 *output);
void triangle(int16 *input, int16 *output);
void radius(int16 *input, int16 *output);
void range(int16 *input, int16 *output);
void range2(int16 *input, int16 *output);
void distance(int16 *input, int16 *output);
void rotate(int16 *input, int16 *output);
void polar(int16 *input, int16 *output);
void attitudeA(int16 *input, int16 *output);
void attitudeB(int16 *input, int16 *output);
void attitudeC(int16 *input, int16 *output);
void objectiveA(int16 *input, int16 *output);
void objectiveB(int16 *input, int16 *output);
void objectiveC(int16 *input, int16 *output);
void subjectiveA(int16 *input, int16 *output);
void subjectiveB(int16 *input, int16 *output);
void subjectiveC(int16 *input, int16 *output);
void scalarA(int16 *input, int16 *output);
void scalarB(int16 *input, int16 *output);
void scalarC(int16 *input, int16 *output);
void gyrate(int16 *input, int16 *output);
void parameter(int16 *input, int16 *output);
void raster(int16 *input, int16 *output);
void target(int16 *input, int16 *output);
void project(int16 *input, int16 *output);
// auxiliar functions
int16 sin(int16 Angle);
int16 cos(int16 Angle);
void inverse(int16 Coefficient, int16 Exponent, int16 &iCoefficient, int16 &iExponent);
int16 denormalizeAndClip(int16 C, int16 E);
void normalize(int16 m, int16 &Coefficient, int16 &Exponent);
void normalizeDouble(int32 Product, int16 &Coefficient, int16 &Exponent);
int16 shiftR(int16 C, int16 E);
};
#endif
+3
View File
@@ -1,4 +1,7 @@
#include "../../base.h"
DSP2 *dsp2;
#include "dsp2_op.cpp"
void DSP2::init() {}
+9 -6
View File
@@ -1,13 +1,13 @@
class DSP2 {
public:
struct {
bool waiting_for_command;
uint command;
uint in_count, in_index;
uint out_count, out_index;
bool waiting_for_command;
uint command;
uint in_count, in_index;
uint out_count, out_index;
uint8 parameters[512];
uint8 output[512];
uint8 parameters[512];
uint8 output[512];
uint8 op05transparent;
bool op05haslen;
@@ -20,6 +20,7 @@ struct {
int op0doutlen;
int op0dinlen;
} status;
void init();
void enable();
void power();
@@ -38,3 +39,5 @@ struct {
DSP2();
~DSP2();
};
extern DSP2 *dsp2;
+2
View File
@@ -1,5 +1,7 @@
#include "../../base.h"
OBC1 *obc1;
void OBC1::init() {}
void OBC1::enable() {}
+2
View File
@@ -16,3 +16,5 @@ struct {
OBC1();
~OBC1();
};
extern OBC1 *obc1;
+3
View File
@@ -1,4 +1,7 @@
#include "../../base.h"
SDD1 *sdd1;
#include "sdd1emu.cpp"
void SDD1::init() {}
+2
View File
@@ -28,3 +28,5 @@ struct {
SDD1();
};
extern SDD1 *sdd1;
+2
View File
@@ -52,6 +52,8 @@
#include "../../base.h"
SRTC *srtc;
void SRTC::set_time() {
time_t rawtime;
tm *t;
+2
View File
@@ -48,3 +48,5 @@ struct {
SRTC();
};
extern SRTC *srtc;
+37 -44
View File
@@ -2,66 +2,59 @@ Config config_file;
namespace config {
FS::Path FS::base_path(0, "fs.base_path", "Directory that bsnes resides in", "");
FS::Path FS::rom_path(&config_file, "fs.rom_path",
Setting FS::base_path(0, "fs.base_path",
"Directory that bsnes resides in", "");
Setting FS::rom_path(&config_file, "fs.rom_path",
"Default path to look for ROM files in (\"\" = use default directory)", "");
FS::Path FS::save_path(&config_file, "fs.save_path",
Setting FS::save_path(&config_file, "fs.save_path",
"Default path for all save RAM and cheat files (\"\" = use current directory)", "");
void FS::Path::sset(const char *_data) {
string path;
strcpy(path, _data);
strunquote(path);
replace(path, "\\", "/");
//blank path?
if(strlen(path) == 0) {
Setting::sset(strptr(path));
return;
}
//missing final directory marker?
if(strptr(path)[strlen(path) - 1] != '/') {
strcat(path, "/");
}
Setting::sset(strptr(path));
}
Setting FS::save_ext(&config_file, "fs.save_ext",
"Extension to be used for all save RAM files", "srm");
SNES::VideoColorAdjust SNES::gamma_ramp(&config_file, "snes.colorfilter.gamma_ramp",
Setting SNES::gamma_ramp(&config_file, "snes.colorfilter.gamma_ramp",
"Use precalculated TV-style gamma ramp", true, Setting::TRUE_FALSE);
SNES::VideoColorAdjust SNES::sepia(&config_file, "snes.colorfilter.sepia",
Setting SNES::sepia(&config_file, "snes.colorfilter.sepia",
"Convert color to sepia tone", false, Setting::TRUE_FALSE);
SNES::VideoColorAdjust SNES::grayscale(&config_file, "snes.colorfilter.grayscale",
Setting SNES::grayscale(&config_file, "snes.colorfilter.grayscale",
"Convert color to grayscale tone", false, Setting::TRUE_FALSE);
SNES::VideoColorAdjust SNES::invert(&config_file, "snes.colorfilter.invert",
Setting SNES::invert(&config_file, "snes.colorfilter.invert",
"Invert output image colors", false, Setting::TRUE_FALSE);
SNES::VideoColorAdjust SNES::contrast(&config_file, "snes.colorfilter.contrast",
"", 0, Setting::DEC);
SNES::VideoColorAdjust SNES::brightness(&config_file, "snes.colorfilter.brightness",
"", 0, Setting::DEC);
SNES::VideoColorAdjust SNES::gamma(&config_file, "snes.colorfilter.gamma",
"", 100, Setting::DEC);
void SNES::VideoColorAdjust::set(uint32 _data) {
Setting::set(_data);
::snes->update_color_lookup_table();
}
Setting SNES::contrast(&config_file, "snes.colorfilter.contrast",
"Contrast", 0, Setting::DEC);
Setting SNES::brightness(&config_file, "snes.colorfilter.brightness",
"Brightness", 0, Setting::DEC);
Setting SNES::gamma(&config_file, "snes.colorfilter.gamma",
"Gamma", 80, Setting::DEC);
Setting SNES::ntsc_merge_fields(&config_file, "snes.ntsc_merge_fields",
"Merge fields in NTSC video filter\n"
"Set to true if using filter at any refresh rate other than 60hz\n"
"", false, Setting::TRUE_FALSE);
"Merge fields in NTSC video filter\n"
"Set to true if using filter at any refresh rate other than 60hz\n"
"", true, Setting::TRUE_FALSE);
Setting SNES::mute(&config_file, "snes.mute", "Mutes SNES audio output when enabled",
false, Setting::TRUE_FALSE);
//do not save these settings to config_file
Setting CPU::hdma_enable(0, "cpu.hdma_enable", "Enable HDMA effects", true, Setting::TRUE_FALSE);
Setting SNES::controller_port0(&config_file, "snes.controller_port_1",
"Controller attached to SNES port 1", ::SNES::DEVICEID_JOYPAD1, Setting::DEC);
Setting SNES::controller_port1(&config_file, "snes.controller_port_2",
"Controller attached to SNES port 2", ::SNES::DEVICEID_JOYPAD2, Setting::DEC);
Setting CPU::ntsc_clock_rate(&config_file, "cpu.ntsc_clock_rate",
"NTSC S-CPU clock rate (in hz)", 21477272, Setting::DEC);
Setting CPU::pal_clock_rate(&config_file, "cpu.pal_clock_rate",
"PAL S-CPU clock rate (in hz)", 21241370, Setting::DEC);
Setting CPU::hdma_enable(0, "cpu.hdma_enable",
"Enable HDMA effects", true, Setting::TRUE_FALSE);
Setting SMP::ntsc_clock_rate(&config_file, "smp.ntsc_clock_rate",
"NTSC S-SMP clock rate (in hz)", 24576000, Setting::DEC);
Setting SMP::pal_clock_rate(&config_file, "smp.pal_clock_rate",
"PAL S-SMP clock rate (in hz)", 24576000, Setting::DEC);
Setting PPU::render_scanline_position(&config_file, "ppu.render_scanline_position",
"Approximate HCLOCK position to render at for scanline-based renderers",
256, Setting::DEC);
Setting PPU::opt_enable(0, "ppu.opt_enable", "Enable offset-per-tile effects", true, Setting::TRUE_FALSE);
Setting PPU::bg1_pri0_enable(0, "ppu.bg1_pri0_enable", "Enable BG1 Priority 0", true, Setting::TRUE_FALSE);
+10 -11
View File
@@ -3,30 +3,29 @@ extern Config config_file;
namespace config {
extern struct FS {
static class Path : public Setting {
public:
void sset(const char *_data);
SettingOperators(Path);
} base_path, rom_path, save_path;
static Setting base_path, rom_path, save_path;
static Setting save_ext;
} fs;
extern struct SNES {
static class VideoColorAdjust : public Setting {
public:
void set(uint32 _data);
SettingOperators(VideoColorAdjust);
} gamma_ramp, sepia, grayscale, invert, contrast, brightness, gamma;
static Setting gamma_ramp, sepia, grayscale, invert, contrast, brightness, gamma;
static Setting ntsc_merge_fields;
static Setting mute;
static Setting controller_port0;
static Setting controller_port1;
} snes;
extern struct CPU {
static Setting ntsc_clock_rate, pal_clock_rate;
static Setting hdma_enable;
} cpu;
extern struct SMP {
static Setting ntsc_clock_rate, pal_clock_rate;
} smp;
extern struct PPU {
static Setting render_scanline_position;
static Setting opt_enable;
static Setting bg1_pri0_enable, bg1_pri1_enable;
+6 -39
View File
@@ -22,53 +22,23 @@ void bCPU::run() {
return;
}
if(status.cycle_pos == 0) {
//interrupts only trigger on opcode edges
if(!run_state.irq && !run_state.stp) {
if(status.cycle_pos == 0) { //interrupts only trigger on opcode edges
if(run_state.irq && !run_state.stp) {
run_state.irq = false;
if(time.nmi_pending == true) {
time.nmi_pending = false;
aa.w = 0xffea;
run_state.irq = true;
aa.w = (regs.e == false) ? 0xffea : 0xfffa;
} else if(time.irq_pending == true) {
time.irq_pending = false;
aa.w = 0xffee;
run_state.irq = true;
aa.w = (regs.e == false) ? 0xffee : 0xfffe;
}
irq_run();
}
}
exec_cycle();
}
void bCPU::scanline() {
time.hdma_triggered = false;
if(vcounter() == (overscan() == false ? 227 : 242) && status.auto_joypad_poll == true) {
snes->poll_input(SNES::DEV_JOYPAD1);
snes->poll_input(SNES::DEV_JOYPAD2);
//When the SNES auto-polls the joypads, it writes 1, then 0 to
//$4016, then reads from each 16 times to get the joypad state
//information. As a result, the joypad read positions are set
//to 16 after such a poll. Position 16 is the controller
//connected status bit.
status.joypad1_read_pos = 16;
status.joypad2_read_pos = 16;
}
}
void bCPU::frame() {
time.nmi_read = 1;
time.nmi_line = 1;
time.nmi_transition = 0;
if(cpu_version == 2) {
time.hdmainit_trigger_pos = 12 + dma_counter();
} else {
time.hdmainit_trigger_pos = 12 + 8 - dma_counter();
}
time.hdmainit_triggered = false;
}
void bCPU::power() {
region = snes->region();
@@ -93,9 +63,6 @@ void bCPU::reset() {
regs.e = 1;
regs.mdr = 0x00;
//simulate pbr:pc push during reset irq vector
regs.s.l -= 3;
time_reset();
mmio_reset();
dma_reset();
+1 -3
View File
@@ -82,9 +82,7 @@ struct {
inline uint8 pio_status();
inline void run();
inline uint32 cycles_executed();
inline void scanline();
inline void frame();
inline uint32 clocks_executed();
inline void power();
inline void reset();
+8 -19
View File
@@ -1,8 +1,8 @@
void bCPU::last_cycle() {
//DMV27: keep previous nmi value,
//to allow wai and irq to work properly
time.nmi_pending = nmi_test() || time.nmi_pending;
time.irq_pending = irq_test();
time.nmi_pending |= nmi_test();
time.irq_pending |= irq_test();
run_state.irq = (time.nmi_pending || time.irq_pending);
}
void bCPU::pre_exec_cycle() {
@@ -56,12 +56,7 @@ static int z;
status.hdma_state = HDMASTATE_IDMASYNC3;
break;
case HDMASTATE_IDMASYNC3:
channel[z].hdma_active = channel[z].hdma_enabled;
if(channel[z].hdma_enabled) {
channel[z].hdma_addr = channel[z].srcaddr;
hdma_update(z); //updates status.hdma_cycle_count
}
if(++z < 8)break;
hdma_init();
if(!run_state.dma) {
status.hdma_state = HDMASTATE_ICPUSYNC;
} else {
@@ -89,7 +84,7 @@ static int z;
status.hdma_state = HDMASTATE_DMASYNC3;
break;
case HDMASTATE_DMASYNC3:
if(channel[z].hdma_active) {
if(channel[z].hdma_line_counter) {
add_cycles(8);
status.hdma_cycle_count += 8;
}
@@ -126,7 +121,7 @@ static int z;
status.dma_state = DMASTATE_DMASYNC3;
break;
case DMASTATE_DMASYNC3:
if(channel[z].active == true) {
if(channel[z].dma_enabled == true) {
add_cycles(8);
status.dma_cycle_count += 8;
}
@@ -144,12 +139,6 @@ static int z;
}
void bCPU::exec_cycle() {
//irq active? run one bus cycle of the irq event and return
if(run_state.irq) {
irq_run();
return;
}
if(status.cycle_pos) {
(this->*optbl[status.opcode])();
#ifdef DEBUGGER
@@ -164,7 +153,7 @@ void bCPU::exec_cycle() {
#ifdef DEBUGGER
snes->notify(SNES::CPU_EXEC_OPCODE_BEGIN);
#endif
status.opcode = op_read();
status.opcode = op_readpc();
status.cycle_pos = 1;
}
+17 -55
View File
@@ -1,57 +1,20 @@
/*
[IRQ cycles]
[0] pbr,pc ; opcode
[1] pbr,pc ; io
[2] 0,s ; pbr
[3] 0,s-1 ; pch
[4] 0,s-2 ; pcl
[5] 0,s-3 ; p
[6] 0,va ; aavl
[7] 0,va+1 ; aavh
*/
void bCPU::irq_run() {
//WDC documentation is incorrect, first cycle
//is a memory read fetch from PBR:PC
switch(status.cycle_pos++) {
case 0:
//read from PBR:PC, but do not increment PC counter
mem_read(regs.pc.d);
break;
case 1:
cpu_io();
if(regs.e)status.cycle_pos++;
break;
case 2:
stack_write(regs.pc.b);
break;
case 3:
stack_write(regs.pc.h);
break;
case 4:
stack_write(regs.pc.l);
break;
case 5:
//emulation-mode irqs clear brk bit 0x10
stack_write((regs.e) ? (regs.p & ~0x10) : regs.p);
break;
case 6:
//todo: test if NMI can override IRQ here...
rd.l = op_read(OPMODE_ADDR, aa.w);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
break;
case 7:
rd.h = op_read(OPMODE_ADDR, aa.w + 1);
regs.pc.w = rd.w;
#ifdef DEBUGGER
//let debugger know the new IRQ opcode address
snes->notify(SNES::CPU_EXEC_OPCODE_END);
#endif
status.cycle_pos = 0;
run_state.irq = false;
break;
}
mem_read(regs.pc.d);
cpu_io();
if(!regs.e)op_writestack(regs.pc.b);
op_writestack(regs.pc.h);
op_writestack(regs.pc.l);
op_writestack(regs.e ? (regs.p & ~0x10) : regs.p);
rd.l = op_readaddr(aa.w + 0);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
rd.h = op_readaddr(aa.w + 1);
regs.pc.w = rd.w;
#ifdef DEBUGGER
//let debugger know the new IRQ opcode address
snes->notify(SNES::CPU_EXEC_OPCODE_END);
#endif
}
bool bCPU::nmi_test() {
@@ -83,6 +46,5 @@ _true:
time.irq_transition = 0;
run_state.wai = false;
if(regs.p.i)return false;
return true;
return (regs.p.i) ? false : true;
}
+66 -68
View File
@@ -59,21 +59,21 @@ uint8 r;
r = regs.mdr & 0xfc;
if(status.joypad_strobe_latch == 1) {
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B);
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_B);
} else {
switch(status.joypad1_read_pos) {
case 0: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B); break;
case 1: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_Y); break;
case 2: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_SELECT); break;
case 3: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_START); break;
case 4: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_UP); break;
case 5: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_DOWN); break;
case 6: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_LEFT); break;
case 7: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_RIGHT); break;
case 8: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_A); break;
case 9: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_X); break;
case 10: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_L); break;
case 11: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_R); break;
case 0: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_B); break;
case 1: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_Y); break;
case 2: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_SELECT); break;
case 3: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_START); break;
case 4: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_UP); break;
case 5: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_DOWN); break;
case 6: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_LEFT); break;
case 7: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_RIGHT); break;
case 8: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_A); break;
case 9: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_X); break;
case 10: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_L); break;
case 11: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_R); break;
case 12: break;
case 13: break;
case 14: break;
@@ -97,21 +97,21 @@ uint8 r;
r |= 0x1c;
if(status.joypad_strobe_latch == 1) {
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_B);
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_B);
} else {
switch(status.joypad2_read_pos) {
case 0: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_B); break;
case 1: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_Y); break;
case 2: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_SELECT); break;
case 3: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_START); break;
case 4: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_UP); break;
case 5: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_DOWN); break;
case 6: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_LEFT); break;
case 7: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_RIGHT); break;
case 8: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_A); break;
case 9: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_X); break;
case 10: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_L); break;
case 11: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_R); break;
case 0: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_B); break;
case 1: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_Y); break;
case 2: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_SELECT); break;
case 3: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_START); break;
case 4: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_UP); break;
case 5: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_DOWN); break;
case 6: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_LEFT); break;
case 7: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_RIGHT); break;
case 8: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_A); break;
case 9: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_X); break;
case 10: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_L); break;
case 11: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_R); break;
case 12: break;
case 13: break;
case 14: break;
@@ -213,10 +213,10 @@ uint8 r = 0x00;
uint16 v = vcounter();
if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled
//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_A) << 7;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_X) << 6;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_L) << 5;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_R) << 4;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_A) << 7;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_X) << 6;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_L) << 5;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_R) << 4;
return r;
}
@@ -226,14 +226,14 @@ uint8 r = 0x00;
uint16 v = vcounter();
if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled
//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B) << 7;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_Y) << 6;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_SELECT) << 5;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_START) << 4;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_UP) << 3;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_DOWN) << 2;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_LEFT) << 1;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_RIGHT);
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_B) << 7;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_Y) << 6;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_SELECT) << 5;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_START) << 4;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_UP) << 3;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_DOWN) << 2;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_LEFT) << 1;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_RIGHT);
return r;
}
@@ -243,10 +243,10 @@ uint8 r = 0x00;
uint16 v = vcounter();
if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled
//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_A) << 7;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_X) << 6;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_L) << 5;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_R) << 4;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_A) << 7;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_X) << 6;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_L) << 5;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_R) << 4;
return r;
}
@@ -256,14 +256,14 @@ uint8 r = 0x00;
uint16 v = vcounter();
if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled
//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_B) << 7;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_Y) << 6;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_SELECT) << 5;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_START) << 4;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_UP) << 3;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_DOWN) << 2;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_LEFT) << 1;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_RIGHT);
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_B) << 7;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_Y) << 6;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_SELECT) << 5;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_START) << 4;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_UP) << 3;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_DOWN) << 2;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_LEFT) << 1;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_RIGHT);
return r;
}
@@ -329,12 +329,12 @@ uint8 bCPU::mmio_r43xb(uint8 i) {
uint8 bCPU::mmio_read(uint16 addr) {
//APU
if(addr >= 0x2140 && addr <= 0x217f) {
return r_apu->port_read(addr & 3);
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
return r_smp->port_read(addr & 3);
}
//HDMA
if(addr >= 0x4300 && addr <= 0x437f) {
if((addr & 0xff80) == 0x4300) { //$4300-$437f
uint i = (addr >> 4) & 7;
switch(addr & 0xf) {
case 0x0: return mmio_r43x0(i);
@@ -414,8 +414,7 @@ void bCPU::mmio_w4016(uint8 value) {
status.joypad_strobe_latch = bool(value & 1);
if(status.joypad_strobe_latch == 1) {
snes->poll_input(SNES::DEV_JOYPAD1);
snes->poll_input(SNES::DEV_JOYPAD2);
snes->poll_input();
status.joypad1_read_pos = 0;
status.joypad2_read_pos = 0;
}
@@ -457,6 +456,7 @@ void bCPU::mmio_w4202(uint8 value) {
status.mul_a = value;
}
//WRMPYB
void bCPU::mmio_w4203(uint8 value) {
status.mul_b = value;
status.r4216 = status.mul_a * status.mul_b;
@@ -464,7 +464,7 @@ void bCPU::mmio_w4203(uint8 value) {
//WRDIVL
void bCPU::mmio_w4204(uint8 value) {
status.div_a = (status.div_a & 0xff00) | value;
status.div_a = (status.div_a & 0xff00) | (value);
}
//WRDIVH
@@ -481,29 +481,30 @@ void bCPU::mmio_w4206(uint8 value) {
//HTIMEL
void bCPU::mmio_w4207(uint8 value) {
status.hirq_pos = (status.hirq_pos & 0xff00) | value;
status.hirq_pos = ((status.hirq_pos & 0xff00) | value) & 0x01ff;
update_interrupts();
}
//HTIMEH
void bCPU::mmio_w4208(uint8 value) {
status.hirq_pos = (status.hirq_pos & 0x00ff) | (value << 8);
status.hirq_pos = ((status.hirq_pos & 0x00ff) | (value << 8)) & 0x01ff;
update_interrupts();
}
//VTIMEL
void bCPU::mmio_w4209(uint8 value) {
status.virq_pos = (status.virq_pos & 0xff00) | value;
status.virq_pos = ((status.virq_pos & 0xff00) | value) & 0x01ff;
update_interrupts();
}
//VTIMEH
void bCPU::mmio_w420a(uint8 value) {
status.virq_pos = (status.virq_pos & 0x00ff) | (value << 8);
status.virq_pos = ((status.virq_pos & 0x00ff) | (value << 8)) & 0x01ff;
update_interrupts();
}
//DMAEN
//DMA enable does not disable active HDMA channels
void bCPU::mmio_w420b(uint8 value) {
if(value != 0x00) {
run_state.dma = true;
@@ -511,11 +512,9 @@ void bCPU::mmio_w420b(uint8 value) {
}
for(int i = 0; i < 8; i++) {
if(value & (1 << i)) {
//DMA enable does not disable active HDMA channels
channel[i].active = true;
channel[i].read_index = 0;
}
channel[i].dma_enabled = bool(value & (1 << i));
//TODO: clearing read_index may interfere with DMA+HDMA occurring simultaneously
if(channel[i].dma_enabled)channel[i].read_index = 0;
}
}
@@ -523,7 +522,6 @@ void bCPU::mmio_w420b(uint8 value) {
void bCPU::mmio_w420c(uint8 value) {
for(int i = 0; i < 8; i++) {
channel[i].hdma_enabled = bool(value & (1 << i));
channel[i].hdma_active = bool(value & (1 << i));
}
}
@@ -599,13 +597,13 @@ void bCPU::mmio_w43xb(uint8 value, uint8 i) {
void bCPU::mmio_write(uint16 addr, uint8 data) {
//APU
if(addr >= 0x2140 && addr <= 0x217f) {
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
port_write(addr & 3, data);
return;
}
//HDMA
if(addr >= 0x4300 && addr <= 0x437f) {
if((addr & 0xff80) == 0x4300) { //$4300-$437f
uint i = (addr >> 4) & 7;
switch(addr & 0xf) {
case 0x0: mmio_w43x0(data, i); return;
-7
View File
@@ -1,8 +1 @@
@del *.exe
@del op_misc.cpp
@del op_pc.cpp
@del op_read.cpp
@del op_rmw.cpp
@del op_write.cpp
@del optable.cpp
@del op.h
+1 -63
View File
@@ -12,7 +12,7 @@ void bCPU::cpu_c2() {
}
void bCPU::cpu_c4(uint16 x, uint16 y) {
if(!regs.p.x && (x & 0xff00) != (y & 0xff00)) {
if(!regs.p.x || (x & 0xff00) != (y & 0xff00)) {
cpu_io();
}
}
@@ -23,68 +23,6 @@ void bCPU::cpu_c6(uint16 addr) {
}
}
uint32 bCPU::op_addr(uint8 mode, uint32 addr) {
switch(mode) {
case OPMODE_ADDR:
addr &= 0xffff;
break;
case OPMODE_LONG:
addr &= 0xffffff;
break;
case OPMODE_DBR:
addr = ((regs.db << 16) + addr) & 0xffffff;
break;
case OPMODE_PBR:
addr &= 0xffff;
addr = (regs.pc.b << 16) + addr;
break;
case OPMODE_DP:
addr &= 0xffff;
addr = (regs.d + addr) & 0xffff;
break;
case OPMODE_SP:
addr &= 0xffff;
addr = (regs.s + addr) & 0xffff;
break;
}
return addr;
}
uint8 bCPU::op_read() {
uint8 r;
r = mem_read(regs.pc.d);
regs.pc.w++;
return r;
}
uint8 bCPU::op_read(uint8 mode, uint32 addr) {
addr = op_addr(mode, addr);
return mem_read(addr);
}
void bCPU::op_write(uint8 mode, uint32 addr, uint8 value) {
addr = op_addr(mode, addr);
mem_write(addr, value);
}
uint8 bCPU::stack_read() {
if(regs.e) {
regs.s.l++;
} else {
regs.s.w++;
}
return mem_read(regs.s);
}
void bCPU::stack_write(uint8 value) {
mem_write(regs.s, value);
if(regs.e) {
regs.s.l--;
} else {
regs.s.w--;
}
}
void bCPU::init_op_tables() {
#include "optable.cpp"
}
-12
View File
@@ -57,18 +57,6 @@ uint8 dp, sp;
inline void cpu_c4(uint16 x, uint16 y);
inline void cpu_c6(uint16 addr);
enum {
OPMODE_ADDR, OPMODE_LONG,
OPMODE_DBR, OPMODE_PBR,
OPMODE_DP, OPMODE_SP
};
inline uint32 op_addr(uint8 mode, uint32 addr);
inline uint8 op_read();
inline uint8 op_read(uint8 mode, uint32 addr);
inline void op_write(uint8 mode, uint32 addr, uint8 value);
inline uint8 stack_read();
inline void stack_write(uint8 value);
inline void init_op_tables();
#include "op.h"
+33 -33
View File
@@ -5,7 +5,7 @@ nop(0xea) {
wdm(0x42) {
1:last_cycle();
op_read();
op_readpc();
}
xba(0xeb) {
@@ -21,11 +21,11 @@ xba(0xeb) {
mvn(0x54, ++),
mvp(0x44, --) {
1:dp = op_read();
2:sp = op_read();
1:dp = op_readpc();
2:sp = op_readpc();
3:regs.db = dp;
rd.l = op_read(OPMODE_LONG, (sp << 16) | regs.x.w);
4:op_write(OPMODE_LONG, (dp << 16) | regs.y.w, rd.l);
rd.l = op_readlong((sp << 16) | regs.x.w);
4:op_writelong((dp << 16) | regs.y.w, rd.l);
5:cpu_io();
if(regs.p.x) { regs.x.l$1; regs.y.l$1; }
else { regs.x.w$1; regs.y.w$1; }
@@ -36,18 +36,18 @@ mvp(0x44, --) {
brk(0x00, 0xfffe, 0xffff, 0xffe6, 0xffe7),
cop(0x02, 0xfff4, 0xfff5, 0xffe4, 0xffe5) {
1:op_read();
1:op_readpc();
if(regs.e)skip;
2:stack_write(regs.pc.b);
3:stack_write(regs.pc.h);
4:stack_write(regs.pc.l);
5:stack_write(regs.p);
6:rd.l = op_read(OPMODE_LONG, (regs.e) ? $1 : $3);
2:op_writestack(regs.pc.b);
3:op_writestack(regs.pc.h);
4:op_writestack(regs.pc.l);
5:op_writestack(regs.p);
6:rd.l = op_readlong((regs.e) ? $1 : $3);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
7:last_cycle();
rd.h = op_read(OPMODE_LONG, (regs.e) ? $2 : $4);
rd.h = op_readlong((regs.e) ? $2 : $4);
regs.pc.w = rd.w;
}
@@ -104,7 +104,7 @@ sei(0x78, regs.p.i = 1) {
rep(0xc2, &=~),
sep(0xe2, |=) {
1:rd.l = op_read();
1:rd.l = op_readpc();
2:last_cycle();
cpu_io();
regs.p $1 rd.l;
@@ -200,9 +200,9 @@ phy(0x5a, regs.p.x, y),
phd(0x0b, 0, d) {
1:cpu_io();
if($1)skip;
2:stack_write(regs.$2.h);
2:op_writestack(regs.$2.h);
3:last_cycle();
stack_write(regs.$2.l);
op_writestack(regs.$2.l);
}
phb(0x8b, regs.db),
@@ -210,7 +210,7 @@ phk(0x4b, regs.pc.b),
php(0x08, regs.p) {
1:cpu_io();
2:last_cycle();
stack_write($1);
op_writestack($1);
}
pla(0x68, regs.p.m, a),
@@ -220,14 +220,14 @@ pld(0x2b, 0, d) {
1:cpu_io();
2:cpu_io();
3:if($1)last_cycle();
regs.$2.l = stack_read();
regs.$2.l = op_readstack();
if($1) {
regs.p.n = !!(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0);
end;
}
4:last_cycle();
regs.$2.h = stack_read();
regs.$2.h = op_readstack();
regs.p.n = !!(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0);
}
@@ -236,7 +236,7 @@ plb(0xab) {
1:cpu_io();
2:cpu_io();
3:last_cycle();
regs.db = stack_read();
regs.db = op_readstack();
regs.p.n = !!(regs.db & 0x80);
regs.p.z = (regs.db == 0);
}
@@ -245,7 +245,7 @@ plp(0x28) {
1:cpu_io();
2:cpu_io();
3:last_cycle();
regs.p = stack_read();
regs.p = op_readstack();
if(regs.e)regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
@@ -254,29 +254,29 @@ plp(0x28) {
}
pea(0xf4) {
1:aa.l = op_read();
2:aa.h = op_read();
3:stack_write(aa.h);
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_writestack(aa.h);
4:last_cycle();
stack_write(aa.l);
op_writestack(aa.l);
}
pei(0xd4) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
5:stack_write(aa.h);
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:op_writestack(aa.h);
6:last_cycle();
stack_write(aa.l);
op_writestack(aa.l);
}
per(0x62) {
1:aa.l = op_read();
2:aa.h = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_io();
rd.w = regs.pc.d + (int16)aa.w;
4:stack_write(rd.h);
4:op_writestack(rd.h);
5:last_cycle();
stack_write(rd.l);
op_writestack(rd.l);
}
+59 -59
View File
@@ -12,7 +12,7 @@ void bCPU::op_wdm() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
op_read();
op_readpc();
status.cycle_pos = 0;
} break;
}
@@ -39,17 +39,17 @@ void bCPU::op_xba() {
void bCPU::op_mvn() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
sp = op_read();
sp = op_readpc();
} break;
case 3: {
regs.db = dp;
rd.l = op_read(OPMODE_LONG, (sp << 16) | regs.x.w);
rd.l = op_readlong((sp << 16) | regs.x.w);
} break;
case 4: {
op_write(OPMODE_LONG, (dp << 16) | regs.y.w, rd.l);
op_writelong((dp << 16) | regs.y.w, rd.l);
} break;
case 5: {
cpu_io();
@@ -68,17 +68,17 @@ void bCPU::op_mvn() {
void bCPU::op_mvp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
sp = op_read();
sp = op_readpc();
} break;
case 3: {
regs.db = dp;
rd.l = op_read(OPMODE_LONG, (sp << 16) | regs.x.w);
rd.l = op_readlong((sp << 16) | regs.x.w);
} break;
case 4: {
op_write(OPMODE_LONG, (dp << 16) | regs.y.w, rd.l);
op_writelong((dp << 16) | regs.y.w, rd.l);
} break;
case 5: {
cpu_io();
@@ -97,30 +97,30 @@ void bCPU::op_mvp() {
void bCPU::op_brk() {
switch(status.cycle_pos++) {
case 1: {
op_read();
op_readpc();
if(regs.e)status.cycle_pos++;
} break;
case 2: {
stack_write(regs.pc.b);
op_writestack(regs.pc.b);
} break;
case 3: {
stack_write(regs.pc.h);
op_writestack(regs.pc.h);
} break;
case 4: {
stack_write(regs.pc.l);
op_writestack(regs.pc.l);
} break;
case 5: {
stack_write(regs.p);
op_writestack(regs.p);
} break;
case 6: {
rd.l = op_read(OPMODE_LONG, (regs.e) ? 0xfffe : 0xffe6);
rd.l = op_readlong((regs.e) ? 0xfffe : 0xffe6);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
} break;
case 7: {
last_cycle();
rd.h = op_read(OPMODE_LONG, (regs.e) ? 0xffff : 0xffe7);
rd.h = op_readlong((regs.e) ? 0xffff : 0xffe7);
regs.pc.w = rd.w;
status.cycle_pos = 0;
} break;
@@ -130,30 +130,30 @@ void bCPU::op_brk() {
void bCPU::op_cop() {
switch(status.cycle_pos++) {
case 1: {
op_read();
op_readpc();
if(regs.e)status.cycle_pos++;
} break;
case 2: {
stack_write(regs.pc.b);
op_writestack(regs.pc.b);
} break;
case 3: {
stack_write(regs.pc.h);
op_writestack(regs.pc.h);
} break;
case 4: {
stack_write(regs.pc.l);
op_writestack(regs.pc.l);
} break;
case 5: {
stack_write(regs.p);
op_writestack(regs.p);
} break;
case 6: {
rd.l = op_read(OPMODE_LONG, (regs.e) ? 0xfff4 : 0xffe4);
rd.l = op_readlong((regs.e) ? 0xfff4 : 0xffe4);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
} break;
case 7: {
last_cycle();
rd.h = op_read(OPMODE_LONG, (regs.e) ? 0xfff5 : 0xffe5);
rd.h = op_readlong((regs.e) ? 0xfff5 : 0xffe5);
regs.pc.w = rd.w;
status.cycle_pos = 0;
} break;
@@ -302,7 +302,7 @@ void bCPU::op_sei() {
void bCPU::op_rep() {
switch(status.cycle_pos++) {
case 1: {
rd.l = op_read();
rd.l = op_readpc();
} break;
case 2: {
last_cycle();
@@ -321,7 +321,7 @@ void bCPU::op_rep() {
void bCPU::op_sep() {
switch(status.cycle_pos++) {
case 1: {
rd.l = op_read();
rd.l = op_readpc();
} break;
case 2: {
last_cycle();
@@ -548,11 +548,11 @@ void bCPU::op_pha() {
if(regs.p.m)status.cycle_pos++;
} break;
case 2: {
stack_write(regs.a.h);
op_writestack(regs.a.h);
} break;
case 3: {
last_cycle();
stack_write(regs.a.l);
op_writestack(regs.a.l);
status.cycle_pos = 0;
} break;
}
@@ -565,11 +565,11 @@ void bCPU::op_phx() {
if(regs.p.x)status.cycle_pos++;
} break;
case 2: {
stack_write(regs.x.h);
op_writestack(regs.x.h);
} break;
case 3: {
last_cycle();
stack_write(regs.x.l);
op_writestack(regs.x.l);
status.cycle_pos = 0;
} break;
}
@@ -582,11 +582,11 @@ void bCPU::op_phy() {
if(regs.p.x)status.cycle_pos++;
} break;
case 2: {
stack_write(regs.y.h);
op_writestack(regs.y.h);
} break;
case 3: {
last_cycle();
stack_write(regs.y.l);
op_writestack(regs.y.l);
status.cycle_pos = 0;
} break;
}
@@ -599,11 +599,11 @@ void bCPU::op_phd() {
if(0)status.cycle_pos++;
} break;
case 2: {
stack_write(regs. d.h);
op_writestack(regs. d.h);
} break;
case 3: {
last_cycle();
stack_write(regs. d.l);
op_writestack(regs. d.l);
status.cycle_pos = 0;
} break;
}
@@ -616,7 +616,7 @@ void bCPU::op_phb() {
} break;
case 2: {
last_cycle();
stack_write(regs.db);
op_writestack(regs.db);
status.cycle_pos = 0;
} break;
}
@@ -629,7 +629,7 @@ void bCPU::op_phk() {
} break;
case 2: {
last_cycle();
stack_write(regs.pc.b);
op_writestack(regs.pc.b);
status.cycle_pos = 0;
} break;
}
@@ -642,7 +642,7 @@ void bCPU::op_php() {
} break;
case 2: {
last_cycle();
stack_write(regs.p);
op_writestack(regs.p);
status.cycle_pos = 0;
} break;
}
@@ -658,7 +658,7 @@ void bCPU::op_pla() {
} break;
case 3: {
if(regs.p.m)last_cycle();
regs.a.l = stack_read();
regs.a.l = op_readstack();
if(regs.p.m) {
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
@@ -667,7 +667,7 @@ void bCPU::op_pla() {
} break;
case 4: {
last_cycle();
regs.a.h = stack_read();
regs.a.h = op_readstack();
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
status.cycle_pos = 0;
@@ -685,7 +685,7 @@ void bCPU::op_plx() {
} break;
case 3: {
if(regs.p.x)last_cycle();
regs.x.l = stack_read();
regs.x.l = op_readstack();
if(regs.p.x) {
regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
@@ -694,7 +694,7 @@ void bCPU::op_plx() {
} break;
case 4: {
last_cycle();
regs.x.h = stack_read();
regs.x.h = op_readstack();
regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
status.cycle_pos = 0;
@@ -712,7 +712,7 @@ void bCPU::op_ply() {
} break;
case 3: {
if(regs.p.x)last_cycle();
regs.y.l = stack_read();
regs.y.l = op_readstack();
if(regs.p.x) {
regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
@@ -721,7 +721,7 @@ void bCPU::op_ply() {
} break;
case 4: {
last_cycle();
regs.y.h = stack_read();
regs.y.h = op_readstack();
regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
status.cycle_pos = 0;
@@ -739,7 +739,7 @@ void bCPU::op_pld() {
} break;
case 3: {
if(0)last_cycle();
regs. d.l = stack_read();
regs. d.l = op_readstack();
if(0) {
regs.p.n = !!(regs. d.l & 0x80);
regs.p.z = (regs. d.l == 0);
@@ -748,7 +748,7 @@ void bCPU::op_pld() {
} break;
case 4: {
last_cycle();
regs. d.h = stack_read();
regs. d.h = op_readstack();
regs.p.n = !!(regs. d.w & 0x8000);
regs.p.z = (regs. d.w == 0);
status.cycle_pos = 0;
@@ -766,7 +766,7 @@ void bCPU::op_plb() {
} break;
case 3: {
last_cycle();
regs.db = stack_read();
regs.db = op_readstack();
regs.p.n = !!(regs.db & 0x80);
regs.p.z = (regs.db == 0);
status.cycle_pos = 0;
@@ -784,7 +784,7 @@ void bCPU::op_plp() {
} break;
case 3: {
last_cycle();
regs.p = stack_read();
regs.p = op_readstack();
if(regs.e)regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
@@ -798,17 +798,17 @@ void bCPU::op_plp() {
void bCPU::op_pea() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
stack_write(aa.h);
op_writestack(aa.h);
} break;
case 4: {
last_cycle();
stack_write(aa.l);
op_writestack(aa.l);
status.cycle_pos = 0;
} break;
}
@@ -817,23 +817,23 @@ void bCPU::op_pea() {
void bCPU::op_pei() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
aa.l = op_read(OPMODE_DP, dp);
aa.l = op_readdp(dp);
} break;
case 4: {
aa.h = op_read(OPMODE_DP, dp + 1);
aa.h = op_readdp(dp + 1);
} break;
case 5: {
stack_write(aa.h);
op_writestack(aa.h);
} break;
case 6: {
last_cycle();
stack_write(aa.l);
op_writestack(aa.l);
status.cycle_pos = 0;
} break;
}
@@ -842,21 +842,21 @@ void bCPU::op_pei() {
void bCPU::op_per() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
rd.w = regs.pc.d + (int16)aa.w;
} break;
case 4: {
stack_write(rd.h);
op_writestack(rd.h);
} break;
case 5: {
last_cycle();
stack_write(rd.l);
op_writestack(rd.l);
status.cycle_pos = 0;
} break;
}
+47 -47
View File
@@ -7,7 +7,7 @@ bmi(0x30, regs.p.n),
bvc(0x50, !regs.p.v),
bvs(0x70, regs.p.v) {
1:if(!$1)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if($1) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
@@ -20,7 +20,7 @@ bvs(0x70, regs.p.v) {
}
bra(0x80) {
1:rd.l = op_read();
1:rd.l = op_readpc();
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
2:cpu_c6(aa.w);
@@ -29,119 +29,119 @@ bra(0x80) {
}
brl(0x82) {
1:rd.l = op_read();
2:rd.h = op_read();
1:rd.l = op_readpc();
2:rd.h = op_readpc();
3:last_cycle();
cpu_io();
regs.pc.w = regs.pc.d + (int16)rd.w;
}
jmp_addr(0x4c) {
1:rd.l = op_read();
1:rd.l = op_readpc();
2:last_cycle();
rd.h = op_read();
rd.h = op_readpc();
regs.pc.w = rd.w;
}
jmp_long(0x5c) {
1:rd.l = op_read();
2:rd.h = op_read();
1:rd.l = op_readpc();
2:rd.h = op_readpc();
3:last_cycle();
rd.b = op_read();
rd.b = op_readpc();
regs.pc.d = rd.d & 0xffffff;
}
jmp_iaddr(0x6c) {
1:aa.l = op_read();
2:aa.h = op_read();
3:rd.l = op_read(OPMODE_ADDR, aa.w);
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:rd.l = op_readaddr(aa.w);
4:last_cycle();
rd.h = op_read(OPMODE_ADDR, aa.w + 1);
rd.h = op_readaddr(aa.w + 1);
regs.pc.w = rd.w;
}
jmp_iaddrx(0x7c) {
1:aa.l = op_read();
2:aa.h = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_io();
4:rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w);
4:rd.l = op_readpbr(aa.w + regs.x.w);
5:last_cycle();
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1);
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
}
jmp_iladdr(0xdc) {
1:aa.l = op_read();
2:aa.h = op_read();
3:rd.l = op_read(OPMODE_ADDR, aa.w);
4:rd.h = op_read(OPMODE_ADDR, aa.w + 1);
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:rd.l = op_readaddr(aa.w);
4:rd.h = op_readaddr(aa.w + 1);
5:last_cycle();
rd.b = op_read(OPMODE_ADDR, aa.w + 2);
rd.b = op_readaddr(aa.w + 2);
regs.pc.d = rd.d & 0xffffff;
}
jsr_addr(0x20) {
1:aa.l = op_read();
2:aa.h = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_io();
4:regs.pc.w--;
stack_write(regs.pc.h);
op_writestack(regs.pc.h);
5:last_cycle();
stack_write(regs.pc.l);
op_writestack(regs.pc.l);
regs.pc.w = aa.w;
}
jsr_long(0x22) {
1:aa.l = op_read();
2:aa.h = op_read();
3:stack_write(regs.pc.b);
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_writestack(regs.pc.b);
4:cpu_io();
5:aa.b = op_read();
5:aa.b = op_readpc();
6:regs.pc.w--;
stack_write(regs.pc.h);
op_writestack(regs.pc.h);
7:last_cycle();
stack_write(regs.pc.l);
op_writestack(regs.pc.l);
regs.pc.d = aa.d & 0xffffff;
}
jsr_iaddrx(0xfc) {
1:aa.l = op_read();
2:stack_write(regs.pc.h);
3:stack_write(regs.pc.l);
4:aa.h = op_read();
1:aa.l = op_readpc();
2:op_writestack(regs.pc.h);
3:op_writestack(regs.pc.l);
4:aa.h = op_readpc();
5:cpu_io();
6:rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w);
6:rd.l = op_readpbr(aa.w + regs.x.w);
7:last_cycle();
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1);
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
}
rti(0x40) {
1:cpu_io();
2:cpu_io();
3:regs.p = stack_read();
3:regs.p = op_readstack();
if(regs.e)regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
4:rd.l = stack_read();
4:rd.l = op_readstack();
5:if(regs.e)last_cycle();
rd.h = stack_read();
rd.h = op_readstack();
if(regs.e) {
regs.pc.w = rd.w;
end;
}
6:last_cycle();
rd.b = stack_read();
rd.b = op_readstack();
regs.pc.d = rd.d & 0xffffff;
}
rts(0x60) {
1:cpu_io();
2:cpu_io();
3:rd.l = stack_read();
4:rd.h = stack_read();
3:rd.l = op_readstack();
4:rd.h = op_readstack();
5:last_cycle();
cpu_io();
regs.pc.w = rd.w;
@@ -151,10 +151,10 @@ rts(0x60) {
rtl(0x6b) {
1:cpu_io();
2:cpu_io();
3:rd.l = stack_read();
4:rd.h = stack_read();
3:rd.l = op_readstack();
4:rd.h = op_readstack();
5:last_cycle();
rd.b = stack_read();
rd.b = op_readstack();
regs.pc.d = rd.d & 0xffffff;
regs.pc.w++;
}
+54 -54
View File
@@ -2,7 +2,7 @@ void bCPU::op_bcc() {
switch(status.cycle_pos++) {
case 1: {
if(!!regs.p.c)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if(!regs.p.c) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
@@ -25,7 +25,7 @@ void bCPU::op_bcs() {
switch(status.cycle_pos++) {
case 1: {
if(!regs.p.c)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if(regs.p.c) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
@@ -48,7 +48,7 @@ void bCPU::op_bne() {
switch(status.cycle_pos++) {
case 1: {
if(!!regs.p.z)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if(!regs.p.z) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
@@ -71,7 +71,7 @@ void bCPU::op_beq() {
switch(status.cycle_pos++) {
case 1: {
if(!regs.p.z)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if(regs.p.z) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
@@ -94,7 +94,7 @@ void bCPU::op_bpl() {
switch(status.cycle_pos++) {
case 1: {
if(!!regs.p.n)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if(!regs.p.n) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
@@ -117,7 +117,7 @@ void bCPU::op_bmi() {
switch(status.cycle_pos++) {
case 1: {
if(!regs.p.n)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if(regs.p.n) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
@@ -140,7 +140,7 @@ void bCPU::op_bvc() {
switch(status.cycle_pos++) {
case 1: {
if(!!regs.p.v)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if(!regs.p.v) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
@@ -163,7 +163,7 @@ void bCPU::op_bvs() {
switch(status.cycle_pos++) {
case 1: {
if(!regs.p.v)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if(regs.p.v) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
@@ -185,7 +185,7 @@ void bCPU::op_bvs() {
void bCPU::op_bra() {
switch(status.cycle_pos++) {
case 1: {
rd.l = op_read();
rd.l = op_readpc();
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} break;
@@ -203,10 +203,10 @@ void bCPU::op_bra() {
void bCPU::op_brl() {
switch(status.cycle_pos++) {
case 1: {
rd.l = op_read();
rd.l = op_readpc();
} break;
case 2: {
rd.h = op_read();
rd.h = op_readpc();
} break;
case 3: {
last_cycle();
@@ -220,11 +220,11 @@ void bCPU::op_brl() {
void bCPU::op_jmp_addr() {
switch(status.cycle_pos++) {
case 1: {
rd.l = op_read();
rd.l = op_readpc();
} break;
case 2: {
last_cycle();
rd.h = op_read();
rd.h = op_readpc();
regs.pc.w = rd.w;
status.cycle_pos = 0;
} break;
@@ -234,14 +234,14 @@ void bCPU::op_jmp_addr() {
void bCPU::op_jmp_long() {
switch(status.cycle_pos++) {
case 1: {
rd.l = op_read();
rd.l = op_readpc();
} break;
case 2: {
rd.h = op_read();
rd.h = op_readpc();
} break;
case 3: {
last_cycle();
rd.b = op_read();
rd.b = op_readpc();
regs.pc.d = rd.d & 0xffffff;
status.cycle_pos = 0;
} break;
@@ -251,17 +251,17 @@ void bCPU::op_jmp_long() {
void bCPU::op_jmp_iaddr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_ADDR, aa.w);
rd.l = op_readaddr(aa.w);
} break;
case 4: {
last_cycle();
rd.h = op_read(OPMODE_ADDR, aa.w + 1);
rd.h = op_readaddr(aa.w + 1);
regs.pc.w = rd.w;
status.cycle_pos = 0;
} break;
@@ -271,20 +271,20 @@ void bCPU::op_jmp_iaddr() {
void bCPU::op_jmp_iaddrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w);
rd.l = op_readpbr(aa.w + regs.x.w);
} break;
case 5: {
last_cycle();
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1);
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
status.cycle_pos = 0;
} break;
@@ -294,20 +294,20 @@ void bCPU::op_jmp_iaddrx() {
void bCPU::op_jmp_iladdr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_ADDR, aa.w);
rd.l = op_readaddr(aa.w);
} break;
case 4: {
rd.h = op_read(OPMODE_ADDR, aa.w + 1);
rd.h = op_readaddr(aa.w + 1);
} break;
case 5: {
last_cycle();
rd.b = op_read(OPMODE_ADDR, aa.w + 2);
rd.b = op_readaddr(aa.w + 2);
regs.pc.d = rd.d & 0xffffff;
status.cycle_pos = 0;
} break;
@@ -317,21 +317,21 @@ void bCPU::op_jmp_iladdr() {
void bCPU::op_jsr_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
} break;
case 4: {
regs.pc.w--;
stack_write(regs.pc.h);
op_writestack(regs.pc.h);
} break;
case 5: {
last_cycle();
stack_write(regs.pc.l);
op_writestack(regs.pc.l);
regs.pc.w = aa.w;
status.cycle_pos = 0;
} break;
@@ -341,27 +341,27 @@ void bCPU::op_jsr_addr() {
void bCPU::op_jsr_long() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
stack_write(regs.pc.b);
op_writestack(regs.pc.b);
} break;
case 4: {
cpu_io();
} break;
case 5: {
aa.b = op_read();
aa.b = op_readpc();
} break;
case 6: {
regs.pc.w--;
stack_write(regs.pc.h);
op_writestack(regs.pc.h);
} break;
case 7: {
last_cycle();
stack_write(regs.pc.l);
op_writestack(regs.pc.l);
regs.pc.d = aa.d & 0xffffff;
status.cycle_pos = 0;
} break;
@@ -371,26 +371,26 @@ void bCPU::op_jsr_long() {
void bCPU::op_jsr_iaddrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
stack_write(regs.pc.h);
op_writestack(regs.pc.h);
} break;
case 3: {
stack_write(regs.pc.l);
op_writestack(regs.pc.l);
} break;
case 4: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 5: {
cpu_io();
} break;
case 6: {
rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w);
rd.l = op_readpbr(aa.w + regs.x.w);
} break;
case 7: {
last_cycle();
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1);
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
status.cycle_pos = 0;
} break;
@@ -406,7 +406,7 @@ void bCPU::op_rti() {
cpu_io();
} break;
case 3: {
regs.p = stack_read();
regs.p = op_readstack();
if(regs.e)regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
@@ -414,11 +414,11 @@ void bCPU::op_rti() {
}
} break;
case 4: {
rd.l = stack_read();
rd.l = op_readstack();
} break;
case 5: {
if(regs.e)last_cycle();
rd.h = stack_read();
rd.h = op_readstack();
if(regs.e) {
regs.pc.w = rd.w;
status.cycle_pos = 0;
@@ -426,7 +426,7 @@ void bCPU::op_rti() {
} break;
case 6: {
last_cycle();
rd.b = stack_read();
rd.b = op_readstack();
regs.pc.d = rd.d & 0xffffff;
status.cycle_pos = 0;
} break;
@@ -442,10 +442,10 @@ void bCPU::op_rts() {
cpu_io();
} break;
case 3: {
rd.l = stack_read();
rd.l = op_readstack();
} break;
case 4: {
rd.h = stack_read();
rd.h = op_readstack();
} break;
case 5: {
last_cycle();
@@ -466,14 +466,14 @@ void bCPU::op_rtl() {
cpu_io();
} break;
case 3: {
rd.l = stack_read();
rd.l = op_readstack();
} break;
case 4: {
rd.h = stack_read();
rd.h = op_readstack();
} break;
case 5: {
last_cycle();
rd.b = stack_read();
rd.b = op_readstack();
regs.pc.d = rd.d & 0xffffff;
regs.pc.w++;
status.cycle_pos = 0;
+70 -70
View File
@@ -10,10 +10,10 @@ ldy_const(0xa0, ldy, regs.p.x),
ora_const(0x09, ora, regs.p.m),
sbc_const(0xe9, sbc, regs.p.m) {
1:if($2)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if($2) { op_$1_b(); end; }
2:last_cycle();
rd.h = op_read();
rd.h = op_readpc();
op_$1_w();
}
@@ -29,13 +29,13 @@ ldx_addr(0xae, ldx, regs.p.x),
ldy_addr(0xac, ldy, regs.p.x),
ora_addr(0x0d, ora, regs.p.m),
sbc_addr(0xed, sbc, regs.p.m) {
1:aa.l = op_read();
2:aa.h = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:if($2)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if($2) { op_$1_b(); end; }
4:last_cycle();
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
op_$1_w();
}
@@ -48,14 +48,14 @@ lda_addrx(0xbd, lda, regs.p.m),
ldy_addrx(0xbc, ldy, regs.p.x),
ora_addrx(0x1d, ora, regs.p.m),
sbc_addrx(0xfd, sbc, regs.p.m) {
1:aa.l = op_read();
2:aa.h = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_c4(aa.w, aa.w + regs.x.w);
4:if($2)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w);
rd.l = op_readdbr(aa.w + regs.x.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1);
rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_$1_w();
}
@@ -67,14 +67,14 @@ lda_addry(0xb9, lda, regs.p.m),
ldx_addry(0xbe, ldx, regs.p.x),
ora_addry(0x19, ora, regs.p.m),
sbc_addry(0xf9, sbc, regs.p.m) {
1:aa.l = op_read();
2:aa.h = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_c4(aa.w, aa.w + regs.y.w);
4:if($2)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w);
rd.l = op_readdbr(aa.w + regs.y.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1);
rd.h = op_readdbr(aa.w + regs.y.w + 1);
op_$1_w();
}
@@ -85,14 +85,14 @@ eor_long(0x4f, eor, regs.p.m),
lda_long(0xaf, lda, regs.p.m),
ora_long(0x0f, ora, regs.p.m),
sbc_long(0xef, sbc, regs.p.m) {
1:aa.l = op_read();
2:aa.h = op_read();
3:aa.b = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if($2)last_cycle();
rd.l = op_read(OPMODE_LONG, aa.d);
rd.l = op_readlong(aa.d);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_read(OPMODE_LONG, aa.d + 1);
rd.h = op_readlong(aa.d + 1);
op_$1_w();
}
@@ -103,14 +103,14 @@ eor_longx(0x5f, eor, regs.p.m),
lda_longx(0xbf, lda, regs.p.m),
ora_longx(0x1f, ora, regs.p.m),
sbc_longx(0xff, sbc, regs.p.m) {
1:aa.l = op_read();
2:aa.h = op_read();
3:aa.b = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if($2)last_cycle();
rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w);
rd.l = op_readlong(aa.d + regs.x.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1);
rd.h = op_readlong(aa.d + regs.x.w + 1);
op_$1_w();
}
@@ -126,13 +126,13 @@ ldx_dp(0xa6, ldx, regs.p.x),
ldy_dp(0xa4, ldy, regs.p.x),
ora_dp(0x05, ora, regs.p.m),
sbc_dp(0xe5, sbc, regs.p.m) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:if($2)last_cycle();
rd.l = op_read(OPMODE_DP, dp);
rd.l = op_readdp(dp);
if($2) { op_$1_b(); end; }
4:last_cycle();
rd.h = op_read(OPMODE_DP, dp + 1);
rd.h = op_readdp(dp + 1);
op_$1_w();
}
@@ -145,26 +145,26 @@ lda_dpx(0xb5, lda, regs.p.m),
ldy_dpx(0xb4, ldy, regs.p.x),
ora_dpx(0x15, ora, regs.p.m),
sbc_dpx(0xf5, sbc, regs.p.m) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
4:if($2)last_cycle();
rd.l = op_read(OPMODE_DP, dp + regs.x.w);
rd.l = op_readdp(dp + regs.x.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
rd.h = op_readdp(dp + regs.x.w + 1);
op_$1_w();
}
ldx_dpy(0xb6, ldx, regs.p.x) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
4:if($2)last_cycle();
rd.l = op_read(OPMODE_DP, dp + regs.y.w);
rd.l = op_readdp(dp + regs.y.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_read(OPMODE_DP, dp + regs.y.w + 1);
rd.h = op_readdp(dp + regs.y.w + 1);
op_$1_w();
}
@@ -175,15 +175,15 @@ eor_idp(0x52, eor, regs.p.m),
lda_idp(0xb2, lda, regs.p.m),
ora_idp(0x12, ora, regs.p.m),
sbc_idp(0xf2, sbc, regs.p.m) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:if($2)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if($2) { op_$1_b(); end; }
6:last_cycle();
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
op_$1_w();
}
@@ -194,16 +194,16 @@ eor_idpx(0x41, eor, regs.p.m),
lda_idpx(0xa1, lda, regs.p.m),
ora_idpx(0x01, ora, regs.p.m),
sbc_idpx(0xe1, sbc, regs.p.m) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
4:aa.l = op_read(OPMODE_DP, dp + regs.x.w);
5:aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
4:aa.l = op_readdp(dp + regs.x.w);
5:aa.h = op_readdp(dp + regs.x.w + 1);
6:if($2)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
op_$1_w();
}
@@ -214,16 +214,16 @@ eor_idpy(0x51, eor, regs.p.m),
lda_idpy(0xb1, lda, regs.p.m),
ora_idpy(0x11, ora, regs.p.m),
sbc_idpy(0xf1, sbc, regs.p.m) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:cpu_c4(aa.w, aa.w + regs.y.w);
6:if($2)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w);
rd.l = op_readdbr(aa.w + regs.y.w);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1);
rd.h = op_readdbr(aa.w + regs.y.w + 1);
op_$1_w();
}
@@ -234,16 +234,16 @@ eor_ildp(0x47, eor, regs.p.m),
lda_ildp(0xa7, lda, regs.p.m),
ora_ildp(0x07, ora, regs.p.m),
sbc_ildp(0xe7, sbc, regs.p.m) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
5:aa.b = op_read(OPMODE_DP, dp + 2);
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if($2)last_cycle();
rd.l = op_read(OPMODE_LONG, aa.d);
rd.l = op_readlong(aa.d);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_read(OPMODE_LONG, aa.d + 1);
rd.h = op_readlong(aa.d + 1);
op_$1_w();
}
@@ -254,16 +254,16 @@ eor_ildpy(0x57, eor, regs.p.m),
lda_ildpy(0xb7, lda, regs.p.m),
ora_ildpy(0x17, ora, regs.p.m),
sbc_ildpy(0xf7, sbc, regs.p.m) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
5:aa.b = op_read(OPMODE_DP, dp + 2);
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if($2)last_cycle();
rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w);
rd.l = op_readlong(aa.d + regs.y.w);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1);
rd.h = op_readlong(aa.d + regs.y.w + 1);
op_$1_w();
}
@@ -274,13 +274,13 @@ eor_sr(0x43, eor, regs.p.m),
lda_sr(0xa3, lda, regs.p.m),
ora_sr(0x03, ora, regs.p.m),
sbc_sr(0xe3, sbc, regs.p.m) {
1:sp = op_read();
1:sp = op_readpc();
2:cpu_io();
3:if($2)last_cycle();
rd.l = op_read(OPMODE_SP, sp);
rd.l = op_readsp(sp);
if($2) { op_$1_b(); end; }
4:last_cycle();
rd.h = op_read(OPMODE_SP, sp + 1);
rd.h = op_readsp(sp + 1);
op_$1_w();
}
@@ -291,27 +291,27 @@ eor_isry(0x53, eor),
lda_isry(0xb3, lda),
ora_isry(0x13, ora),
sbc_isry(0xf3, sbc) {
1:sp = op_read();
1:sp = op_readpc();
2:cpu_io();
3:aa.l = op_read(OPMODE_SP, sp);
4:aa.h = op_read(OPMODE_SP, sp + 1);
3:aa.l = op_readsp(sp);
4:aa.h = op_readsp(sp + 1);
5:cpu_io();
6:if(regs.p.m)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w);
rd.l = op_readdbr(aa.w + regs.y.w);
if(regs.p.m) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1);
rd.h = op_readdbr(aa.w + regs.y.w + 1);
op_$1_w();
}
bit_const(0x89) {
1:if(regs.p.m)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if(regs.p.m) {
regs.p.z = ((rd.l & regs.a.l) == 0);
end;
}
2:last_cycle();
rd.h = op_read();
rd.h = op_readpc();
regs.p.z = ((rd.w & regs.a.w) == 0);
}
File diff suppressed because it is too large. Load diff
+22 -22
View File
@@ -110,17 +110,17 @@ rol_addr(0x2e, rol),
ror_addr(0x6e, ror),
trb_addr(0x1c, trb),
tsb_addr(0x0c, tsb) {
1:aa.l = op_read();
2:aa.h = op_read();
3:rd.l = op_read(OPMODE_DBR, aa.w);
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:rd.l = op_readdbr(aa.w);
if(regs.p.m)skip;
4:rd.h = op_read(OPMODE_DBR, aa.w + 1);
4:rd.h = op_readdbr(aa.w + 1);
5:cpu_io();
if(regs.p.m) { op_$1_b(); skip; }
else op_$1_w();
6:op_write(OPMODE_DBR, aa.w + 1, rd.h);
6:op_writedbr(aa.w + 1, rd.h);
7:last_cycle();
op_write(OPMODE_DBR, aa.w, rd.l);
op_writedbr(aa.w, rd.l);
}
inc_addrx(0xfe, inc),
@@ -129,18 +129,18 @@ asl_addrx(0x1e, asl),
lsr_addrx(0x5e, lsr),
rol_addrx(0x3e, rol),
ror_addrx(0x7e, ror) {
1:aa.l = op_read();
2:aa.h = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_io();
4:rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w);
4:rd.l = op_readdbr(aa.w + regs.x.w);
if(regs.p.m)skip;
5:rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1);
5:rd.h = op_readdbr(aa.w + regs.x.w + 1);
6:cpu_io();
if(regs.p.m) { op_$1_b(); skip; }
else op_$1_w();
7:op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h);
7:op_writedbr(aa.w + regs.x.w + 1, rd.h);
8:last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l);
op_writedbr(aa.w + regs.x.w, rd.l);
}
inc_dp(0xe6, inc),
@@ -151,17 +151,17 @@ rol_dp(0x26, rol),
ror_dp(0x66, ror),
trb_dp(0x14, trb),
tsb_dp(0x04, tsb) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:rd.l = op_read(OPMODE_DP, dp);
3:rd.l = op_readdp(dp);
if(regs.p.m)skip;
4:rd.h = op_read(OPMODE_DP, dp + 1);
4:rd.h = op_readdp(dp + 1);
5:cpu_io();
if(regs.p.m) { op_$1_b(); skip; }
else op_$1_w();
6:op_write(OPMODE_DP, dp + 1, rd.h);
6:op_writedp(dp + 1, rd.h);
7:last_cycle();
op_write(OPMODE_DP, dp, rd.l);
op_writedp(dp, rd.l);
}
inc_dpx(0xf6, inc),
@@ -170,16 +170,16 @@ asl_dpx(0x16, asl),
lsr_dpx(0x56, lsr),
rol_dpx(0x36, rol),
ror_dpx(0x76, ror) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
4:rd.l = op_read(OPMODE_DP, dp + regs.x.w);
4:rd.l = op_readdp(dp + regs.x.w);
if(regs.p.m)skip;
5:rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
5:rd.h = op_readdp(dp + regs.x.w + 1);
6:cpu_io();
if(regs.p.m) { op_$1_b(); skip; }
else op_$1_w();
7:op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h);
7:op_writedp(dp + regs.x.w + 1, rd.h);
8:last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, rd.l);
op_writedp(dp + regs.x.w, rd.l);
}
+154 -154
View File
@@ -207,17 +207,17 @@ void bCPU::op_ror() {
void bCPU::op_inc_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
} break;
case 5: {
cpu_io();
@@ -225,11 +225,11 @@ void bCPU::op_inc_addr() {
else op_inc_w();
} break;
case 6: {
op_write(OPMODE_DBR, aa.w + 1, rd.h);
op_writedbr(aa.w + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w, rd.l);
op_writedbr(aa.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -238,17 +238,17 @@ void bCPU::op_inc_addr() {
void bCPU::op_dec_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
} break;
case 5: {
cpu_io();
@@ -256,11 +256,11 @@ void bCPU::op_dec_addr() {
else op_dec_w();
} break;
case 6: {
op_write(OPMODE_DBR, aa.w + 1, rd.h);
op_writedbr(aa.w + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w, rd.l);
op_writedbr(aa.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -269,17 +269,17 @@ void bCPU::op_dec_addr() {
void bCPU::op_asl_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
} break;
case 5: {
cpu_io();
@@ -287,11 +287,11 @@ void bCPU::op_asl_addr() {
else op_asl_w();
} break;
case 6: {
op_write(OPMODE_DBR, aa.w + 1, rd.h);
op_writedbr(aa.w + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w, rd.l);
op_writedbr(aa.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -300,17 +300,17 @@ void bCPU::op_asl_addr() {
void bCPU::op_lsr_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
} break;
case 5: {
cpu_io();
@@ -318,11 +318,11 @@ void bCPU::op_lsr_addr() {
else op_lsr_w();
} break;
case 6: {
op_write(OPMODE_DBR, aa.w + 1, rd.h);
op_writedbr(aa.w + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w, rd.l);
op_writedbr(aa.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -331,17 +331,17 @@ void bCPU::op_lsr_addr() {
void bCPU::op_rol_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
} break;
case 5: {
cpu_io();
@@ -349,11 +349,11 @@ void bCPU::op_rol_addr() {
else op_rol_w();
} break;
case 6: {
op_write(OPMODE_DBR, aa.w + 1, rd.h);
op_writedbr(aa.w + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w, rd.l);
op_writedbr(aa.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -362,17 +362,17 @@ void bCPU::op_rol_addr() {
void bCPU::op_ror_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
} break;
case 5: {
cpu_io();
@@ -380,11 +380,11 @@ void bCPU::op_ror_addr() {
else op_ror_w();
} break;
case 6: {
op_write(OPMODE_DBR, aa.w + 1, rd.h);
op_writedbr(aa.w + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w, rd.l);
op_writedbr(aa.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -393,17 +393,17 @@ void bCPU::op_ror_addr() {
void bCPU::op_trb_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
} break;
case 5: {
cpu_io();
@@ -411,11 +411,11 @@ void bCPU::op_trb_addr() {
else op_trb_w();
} break;
case 6: {
op_write(OPMODE_DBR, aa.w + 1, rd.h);
op_writedbr(aa.w + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w, rd.l);
op_writedbr(aa.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -424,17 +424,17 @@ void bCPU::op_trb_addr() {
void bCPU::op_tsb_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
} break;
case 5: {
cpu_io();
@@ -442,11 +442,11 @@ void bCPU::op_tsb_addr() {
else op_tsb_w();
} break;
case 6: {
op_write(OPMODE_DBR, aa.w + 1, rd.h);
op_writedbr(aa.w + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w, rd.l);
op_writedbr(aa.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -455,20 +455,20 @@ void bCPU::op_tsb_addr() {
void bCPU::op_inc_addrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w);
rd.l = op_readdbr(aa.w + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1);
rd.h = op_readdbr(aa.w + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -476,11 +476,11 @@ void bCPU::op_inc_addrx() {
else op_inc_w();
} break;
case 7: {
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h);
op_writedbr(aa.w + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l);
op_writedbr(aa.w + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -489,20 +489,20 @@ void bCPU::op_inc_addrx() {
void bCPU::op_dec_addrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w);
rd.l = op_readdbr(aa.w + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1);
rd.h = op_readdbr(aa.w + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -510,11 +510,11 @@ void bCPU::op_dec_addrx() {
else op_dec_w();
} break;
case 7: {
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h);
op_writedbr(aa.w + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l);
op_writedbr(aa.w + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -523,20 +523,20 @@ void bCPU::op_dec_addrx() {
void bCPU::op_asl_addrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w);
rd.l = op_readdbr(aa.w + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1);
rd.h = op_readdbr(aa.w + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -544,11 +544,11 @@ void bCPU::op_asl_addrx() {
else op_asl_w();
} break;
case 7: {
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h);
op_writedbr(aa.w + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l);
op_writedbr(aa.w + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -557,20 +557,20 @@ void bCPU::op_asl_addrx() {
void bCPU::op_lsr_addrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w);
rd.l = op_readdbr(aa.w + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1);
rd.h = op_readdbr(aa.w + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -578,11 +578,11 @@ void bCPU::op_lsr_addrx() {
else op_lsr_w();
} break;
case 7: {
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h);
op_writedbr(aa.w + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l);
op_writedbr(aa.w + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -591,20 +591,20 @@ void bCPU::op_lsr_addrx() {
void bCPU::op_rol_addrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w);
rd.l = op_readdbr(aa.w + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1);
rd.h = op_readdbr(aa.w + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -612,11 +612,11 @@ void bCPU::op_rol_addrx() {
else op_rol_w();
} break;
case 7: {
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h);
op_writedbr(aa.w + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l);
op_writedbr(aa.w + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -625,20 +625,20 @@ void bCPU::op_rol_addrx() {
void bCPU::op_ror_addrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w);
rd.l = op_readdbr(aa.w + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1);
rd.h = op_readdbr(aa.w + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -646,11 +646,11 @@ void bCPU::op_ror_addrx() {
else op_ror_w();
} break;
case 7: {
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h);
op_writedbr(aa.w + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l);
op_writedbr(aa.w + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -659,17 +659,17 @@ void bCPU::op_ror_addrx() {
void bCPU::op_inc_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
rd.l = op_read(OPMODE_DP, dp);
rd.l = op_readdp(dp);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DP, dp + 1);
rd.h = op_readdp(dp + 1);
} break;
case 5: {
cpu_io();
@@ -677,11 +677,11 @@ void bCPU::op_inc_dp() {
else op_inc_w();
} break;
case 6: {
op_write(OPMODE_DP, dp + 1, rd.h);
op_writedp(dp + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DP, dp, rd.l);
op_writedp(dp, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -690,17 +690,17 @@ void bCPU::op_inc_dp() {
void bCPU::op_dec_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
rd.l = op_read(OPMODE_DP, dp);
rd.l = op_readdp(dp);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DP, dp + 1);
rd.h = op_readdp(dp + 1);
} break;
case 5: {
cpu_io();
@@ -708,11 +708,11 @@ void bCPU::op_dec_dp() {
else op_dec_w();
} break;
case 6: {
op_write(OPMODE_DP, dp + 1, rd.h);
op_writedp(dp + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DP, dp, rd.l);
op_writedp(dp, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -721,17 +721,17 @@ void bCPU::op_dec_dp() {
void bCPU::op_asl_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
rd.l = op_read(OPMODE_DP, dp);
rd.l = op_readdp(dp);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DP, dp + 1);
rd.h = op_readdp(dp + 1);
} break;
case 5: {
cpu_io();
@@ -739,11 +739,11 @@ void bCPU::op_asl_dp() {
else op_asl_w();
} break;
case 6: {
op_write(OPMODE_DP, dp + 1, rd.h);
op_writedp(dp + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DP, dp, rd.l);
op_writedp(dp, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -752,17 +752,17 @@ void bCPU::op_asl_dp() {
void bCPU::op_lsr_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
rd.l = op_read(OPMODE_DP, dp);
rd.l = op_readdp(dp);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DP, dp + 1);
rd.h = op_readdp(dp + 1);
} break;
case 5: {
cpu_io();
@@ -770,11 +770,11 @@ void bCPU::op_lsr_dp() {
else op_lsr_w();
} break;
case 6: {
op_write(OPMODE_DP, dp + 1, rd.h);
op_writedp(dp + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DP, dp, rd.l);
op_writedp(dp, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -783,17 +783,17 @@ void bCPU::op_lsr_dp() {
void bCPU::op_rol_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
rd.l = op_read(OPMODE_DP, dp);
rd.l = op_readdp(dp);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DP, dp + 1);
rd.h = op_readdp(dp + 1);
} break;
case 5: {
cpu_io();
@@ -801,11 +801,11 @@ void bCPU::op_rol_dp() {
else op_rol_w();
} break;
case 6: {
op_write(OPMODE_DP, dp + 1, rd.h);
op_writedp(dp + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DP, dp, rd.l);
op_writedp(dp, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -814,17 +814,17 @@ void bCPU::op_rol_dp() {
void bCPU::op_ror_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
rd.l = op_read(OPMODE_DP, dp);
rd.l = op_readdp(dp);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DP, dp + 1);
rd.h = op_readdp(dp + 1);
} break;
case 5: {
cpu_io();
@@ -832,11 +832,11 @@ void bCPU::op_ror_dp() {
else op_ror_w();
} break;
case 6: {
op_write(OPMODE_DP, dp + 1, rd.h);
op_writedp(dp + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DP, dp, rd.l);
op_writedp(dp, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -845,17 +845,17 @@ void bCPU::op_ror_dp() {
void bCPU::op_trb_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
rd.l = op_read(OPMODE_DP, dp);
rd.l = op_readdp(dp);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DP, dp + 1);
rd.h = op_readdp(dp + 1);
} break;
case 5: {
cpu_io();
@@ -863,11 +863,11 @@ void bCPU::op_trb_dp() {
else op_trb_w();
} break;
case 6: {
op_write(OPMODE_DP, dp + 1, rd.h);
op_writedp(dp + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DP, dp, rd.l);
op_writedp(dp, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -876,17 +876,17 @@ void bCPU::op_trb_dp() {
void bCPU::op_tsb_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
rd.l = op_read(OPMODE_DP, dp);
rd.l = op_readdp(dp);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DP, dp + 1);
rd.h = op_readdp(dp + 1);
} break;
case 5: {
cpu_io();
@@ -894,11 +894,11 @@ void bCPU::op_tsb_dp() {
else op_tsb_w();
} break;
case 6: {
op_write(OPMODE_DP, dp + 1, rd.h);
op_writedp(dp + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DP, dp, rd.l);
op_writedp(dp, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -907,7 +907,7 @@ void bCPU::op_tsb_dp() {
void bCPU::op_inc_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -916,11 +916,11 @@ void bCPU::op_inc_dpx() {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DP, dp + regs.x.w);
rd.l = op_readdp(dp + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
rd.h = op_readdp(dp + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -928,11 +928,11 @@ void bCPU::op_inc_dpx() {
else op_inc_w();
} break;
case 7: {
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h);
op_writedp(dp + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, rd.l);
op_writedp(dp + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -941,7 +941,7 @@ void bCPU::op_inc_dpx() {
void bCPU::op_dec_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -950,11 +950,11 @@ void bCPU::op_dec_dpx() {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DP, dp + regs.x.w);
rd.l = op_readdp(dp + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
rd.h = op_readdp(dp + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -962,11 +962,11 @@ void bCPU::op_dec_dpx() {
else op_dec_w();
} break;
case 7: {
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h);
op_writedp(dp + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, rd.l);
op_writedp(dp + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -975,7 +975,7 @@ void bCPU::op_dec_dpx() {
void bCPU::op_asl_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -984,11 +984,11 @@ void bCPU::op_asl_dpx() {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DP, dp + regs.x.w);
rd.l = op_readdp(dp + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
rd.h = op_readdp(dp + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -996,11 +996,11 @@ void bCPU::op_asl_dpx() {
else op_asl_w();
} break;
case 7: {
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h);
op_writedp(dp + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, rd.l);
op_writedp(dp + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -1009,7 +1009,7 @@ void bCPU::op_asl_dpx() {
void bCPU::op_lsr_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -1018,11 +1018,11 @@ void bCPU::op_lsr_dpx() {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DP, dp + regs.x.w);
rd.l = op_readdp(dp + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
rd.h = op_readdp(dp + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -1030,11 +1030,11 @@ void bCPU::op_lsr_dpx() {
else op_lsr_w();
} break;
case 7: {
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h);
op_writedp(dp + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, rd.l);
op_writedp(dp + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -1043,7 +1043,7 @@ void bCPU::op_lsr_dpx() {
void bCPU::op_rol_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -1052,11 +1052,11 @@ void bCPU::op_rol_dpx() {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DP, dp + regs.x.w);
rd.l = op_readdp(dp + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
rd.h = op_readdp(dp + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -1064,11 +1064,11 @@ void bCPU::op_rol_dpx() {
else op_rol_w();
} break;
case 7: {
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h);
op_writedp(dp + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, rd.l);
op_writedp(dp + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -1077,7 +1077,7 @@ void bCPU::op_rol_dpx() {
void bCPU::op_ror_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -1086,11 +1086,11 @@ void bCPU::op_ror_dpx() {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DP, dp + regs.x.w);
rd.l = op_readdp(dp + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
rd.h = op_readdp(dp + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -1098,11 +1098,11 @@ void bCPU::op_ror_dpx() {
else op_ror_w();
} break;
case 7: {
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h);
op_writedp(dp + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, rd.l);
op_writedp(dp + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
+69 -69
View File
@@ -2,180 +2,180 @@ sta_addr(0x8d, regs.p.m, regs.a.w),
stx_addr(0x8e, regs.p.x, regs.x.w),
sty_addr(0x8c, regs.p.x, regs.y.w),
stz_addr(0x9c, regs.p.m, 0x0000) {
1:aa.l = op_read();
2:aa.h = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:if($1)last_cycle();
op_write(OPMODE_DBR, aa.w, $2);
op_writedbr(aa.w, $2);
if($1)end;
4:last_cycle();
op_write(OPMODE_DBR, aa.w + 1, $2 >> 8);
op_writedbr(aa.w + 1, $2 >> 8);
}
sta_addrx(0x9d, regs.p.m, regs.a.w),
stz_addrx(0x9e, regs.p.m, 0x0000) {
1:aa.l = op_read();
2:aa.h = op_read();
3:cpu_c4(aa.w, aa.w + regs.x.w);
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_io();
4:if($1)last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, $2);
op_writedbr(aa.w + regs.x.w, $2);
if($1)end;
5:last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, $2 >> 8);
op_writedbr(aa.w + regs.x.w + 1, $2 >> 8);
}
sta_addry(0x99) {
1:aa.l = op_read();
2:aa.h = op_read();
3:cpu_c4(aa.w, aa.w + regs.y.w);
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_io();
4:if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l);
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)end;
5:last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h);
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}
sta_long(0x8f) {
1:aa.l = op_read();
2:aa.h = op_read();
3:aa.b = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if(regs.p.m)last_cycle();
op_write(OPMODE_LONG, aa.d, regs.a.l);
op_writelong(aa.d, regs.a.l);
if(regs.p.m)end;
5:last_cycle();
op_write(OPMODE_LONG, aa.d + 1, regs.a.h);
op_writelong(aa.d + 1, regs.a.h);
}
sta_longx(0x9f) {
1:aa.l = op_read();
2:aa.h = op_read();
3:aa.b = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if(regs.p.m)last_cycle();
op_write(OPMODE_LONG, aa.d + regs.x.w, regs.a.l);
op_writelong(aa.d + regs.x.w, regs.a.l);
if(regs.p.m)end;
5:last_cycle();
op_write(OPMODE_LONG, aa.d + regs.x.w + 1, regs.a.h);
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
}
sta_dp(0x85, regs.p.m, regs.a.w),
stx_dp(0x86, regs.p.x, regs.x.w),
sty_dp(0x84, regs.p.x, regs.y.w),
stz_dp(0x64, regs.p.m, 0x0000) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:if($1)last_cycle();
op_write(OPMODE_DP, dp, $2);
op_writedp(dp, $2);
if($1)end;
4:last_cycle();
op_write(OPMODE_DP, dp + 1, $2 >> 8);
op_writedp(dp + 1, $2 >> 8);
}
sta_dpx(0x95, regs.p.m, regs.a.w),
sty_dpx(0x94, regs.p.x, regs.y.w),
stz_dpx(0x74, regs.p.m, 0x0000) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
4:if($1)last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, $2);
op_writedp(dp + regs.x.w, $2);
if($1)end;
5:last_cycle();
op_write(OPMODE_DP, dp + regs.x.w + 1, $2 >> 8);
op_writedp(dp + regs.x.w + 1, $2 >> 8);
}
stx_dpy(0x96) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
4:if(regs.p.x)last_cycle();
op_write(OPMODE_DP, dp + regs.y.w, regs.x.l);
op_writedp(dp + regs.y.w, regs.x.l);
if(regs.p.x)end;
5:last_cycle();
op_write(OPMODE_DP, dp + regs.y.w + 1, regs.x.h);
op_writedp(dp + regs.y.w + 1, regs.x.h);
}
sta_idp(0x92) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w, regs.a.l);
op_writedbr(aa.w, regs.a.l);
if(regs.p.m)end;
6:last_cycle();
op_write(OPMODE_DBR, aa.w + 1, regs.a.h);
op_writedbr(aa.w + 1, regs.a.h);
}
sta_ildp(0x87) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
5:aa.b = op_read(OPMODE_DP, dp + 2);
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if(regs.p.m)last_cycle();
op_write(OPMODE_LONG, aa.d, regs.a.l);
op_writelong(aa.d, regs.a.l);
if(regs.p.m)end;
7:last_cycle();
op_write(OPMODE_LONG, aa.d + 1, regs.a.h);
op_writelong(aa.d + 1, regs.a.h);
}
sta_idpx(0x81) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
4:aa.l = op_read(OPMODE_DP, dp + regs.x.w);
5:aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
4:aa.l = op_readdp(dp + regs.x.w);
5:aa.h = op_readdp(dp + regs.x.w + 1);
6:if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w, regs.a.l);
op_writedbr(aa.w, regs.a.l);
if(regs.p.m)end;
7:last_cycle();
op_write(OPMODE_DBR, aa.w + 1, regs.a.h);
op_writedbr(aa.w + 1, regs.a.h);
}
sta_idpy(0x91) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
5:cpu_c4(aa.w, aa.w + regs.y.w);
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:cpu_io();
6:if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l);
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)end;
7:last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h);
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}
sta_ildpy(0x97) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
5:aa.b = op_read(OPMODE_DP, dp + 2);
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if(regs.p.m)last_cycle();
op_write(OPMODE_LONG, aa.d + regs.y.w, regs.a.l);
op_writelong(aa.d + regs.y.w, regs.a.l);
if(regs.p.m)end;
7:last_cycle();
op_write(OPMODE_LONG, aa.d + regs.y.w + 1, regs.a.h);
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
}
sta_sr(0x83) {
1:sp = op_read();
1:sp = op_readpc();
2:cpu_io();
3:if(regs.p.m)last_cycle();
op_write(OPMODE_SP, sp, regs.a.l);
op_writesp(sp, regs.a.l);
if(regs.p.m)end;
4:last_cycle();
op_write(OPMODE_SP, sp + 1, regs.a.h);
op_writesp(sp + 1, regs.a.h);
}
sta_isry(0x93) {
1:sp = op_read();
1:sp = op_readpc();
2:cpu_io();
3:aa.l = op_read(OPMODE_SP, sp);
4:aa.h = op_read(OPMODE_SP, sp + 1);
3:aa.l = op_readsp(sp);
4:aa.h = op_readsp(sp + 1);
5:cpu_io();
6:if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l);
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)end;
7:last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h);
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}
+97 -97
View File
@@ -1,19 +1,19 @@
void bCPU::op_sta_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w, regs.a.w);
op_writedbr(aa.w, regs.a.w);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_write(OPMODE_DBR, aa.w + 1, regs.a.w >> 8);
op_writedbr(aa.w + 1, regs.a.w >> 8);
status.cycle_pos = 0;
} break;
}
@@ -22,19 +22,19 @@ void bCPU::op_sta_addr() {
void bCPU::op_stx_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
if(regs.p.x)last_cycle();
op_write(OPMODE_DBR, aa.w, regs.x.w);
op_writedbr(aa.w, regs.x.w);
if(regs.p.x)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_write(OPMODE_DBR, aa.w + 1, regs.x.w >> 8);
op_writedbr(aa.w + 1, regs.x.w >> 8);
status.cycle_pos = 0;
} break;
}
@@ -43,19 +43,19 @@ void bCPU::op_stx_addr() {
void bCPU::op_sty_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
if(regs.p.x)last_cycle();
op_write(OPMODE_DBR, aa.w, regs.y.w);
op_writedbr(aa.w, regs.y.w);
if(regs.p.x)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_write(OPMODE_DBR, aa.w + 1, regs.y.w >> 8);
op_writedbr(aa.w + 1, regs.y.w >> 8);
status.cycle_pos = 0;
} break;
}
@@ -64,19 +64,19 @@ void bCPU::op_sty_addr() {
void bCPU::op_stz_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w, 0x0000);
op_writedbr(aa.w, 0x0000);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_write(OPMODE_DBR, aa.w + 1, 0x0000 >> 8);
op_writedbr(aa.w + 1, 0x0000 >> 8);
status.cycle_pos = 0;
} break;
}
@@ -85,22 +85,22 @@ void bCPU::op_stz_addr() {
void bCPU::op_sta_addrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_c4(aa.w, aa.w + regs.x.w);
} break;
case 4: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, regs.a.w);
op_writedbr(aa.w + regs.x.w, regs.a.w);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, regs.a.w >> 8);
op_writedbr(aa.w + regs.x.w + 1, regs.a.w >> 8);
status.cycle_pos = 0;
} break;
}
@@ -109,22 +109,22 @@ void bCPU::op_sta_addrx() {
void bCPU::op_stz_addrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_c4(aa.w, aa.w + regs.x.w);
} break;
case 4: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, 0x0000);
op_writedbr(aa.w + regs.x.w, 0x0000);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, 0x0000 >> 8);
op_writedbr(aa.w + regs.x.w + 1, 0x0000 >> 8);
status.cycle_pos = 0;
} break;
}
@@ -133,22 +133,22 @@ void bCPU::op_stz_addrx() {
void bCPU::op_sta_addry() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_c4(aa.w, aa.w + regs.y.w);
} break;
case 4: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l);
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h);
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
@@ -157,22 +157,22 @@ void bCPU::op_sta_addry() {
void bCPU::op_sta_long() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
aa.b = op_read();
aa.b = op_readpc();
} break;
case 4: {
if(regs.p.m)last_cycle();
op_write(OPMODE_LONG, aa.d, regs.a.l);
op_writelong(aa.d, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_write(OPMODE_LONG, aa.d + 1, regs.a.h);
op_writelong(aa.d + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
@@ -181,22 +181,22 @@ void bCPU::op_sta_long() {
void bCPU::op_sta_longx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
aa.b = op_read();
aa.b = op_readpc();
} break;
case 4: {
if(regs.p.m)last_cycle();
op_write(OPMODE_LONG, aa.d + regs.x.w, regs.a.l);
op_writelong(aa.d + regs.x.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_write(OPMODE_LONG, aa.d + regs.x.w + 1, regs.a.h);
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
@@ -205,19 +205,19 @@ void bCPU::op_sta_longx() {
void bCPU::op_sta_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DP, dp, regs.a.w);
op_writedp(dp, regs.a.w);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_write(OPMODE_DP, dp + 1, regs.a.w >> 8);
op_writedp(dp + 1, regs.a.w >> 8);
status.cycle_pos = 0;
} break;
}
@@ -226,19 +226,19 @@ void bCPU::op_sta_dp() {
void bCPU::op_stx_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
if(regs.p.x)last_cycle();
op_write(OPMODE_DP, dp, regs.x.w);
op_writedp(dp, regs.x.w);
if(regs.p.x)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_write(OPMODE_DP, dp + 1, regs.x.w >> 8);
op_writedp(dp + 1, regs.x.w >> 8);
status.cycle_pos = 0;
} break;
}
@@ -247,19 +247,19 @@ void bCPU::op_stx_dp() {
void bCPU::op_sty_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
if(regs.p.x)last_cycle();
op_write(OPMODE_DP, dp, regs.y.w);
op_writedp(dp, regs.y.w);
if(regs.p.x)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_write(OPMODE_DP, dp + 1, regs.y.w >> 8);
op_writedp(dp + 1, regs.y.w >> 8);
status.cycle_pos = 0;
} break;
}
@@ -268,19 +268,19 @@ void bCPU::op_sty_dp() {
void bCPU::op_stz_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DP, dp, 0x0000);
op_writedp(dp, 0x0000);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_write(OPMODE_DP, dp + 1, 0x0000 >> 8);
op_writedp(dp + 1, 0x0000 >> 8);
status.cycle_pos = 0;
} break;
}
@@ -289,7 +289,7 @@ void bCPU::op_stz_dp() {
void bCPU::op_sta_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -299,12 +299,12 @@ void bCPU::op_sta_dpx() {
} break;
case 4: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, regs.a.w);
op_writedp(dp + regs.x.w, regs.a.w);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_write(OPMODE_DP, dp + regs.x.w + 1, regs.a.w >> 8);
op_writedp(dp + regs.x.w + 1, regs.a.w >> 8);
status.cycle_pos = 0;
} break;
}
@@ -313,7 +313,7 @@ void bCPU::op_sta_dpx() {
void bCPU::op_sty_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -323,12 +323,12 @@ void bCPU::op_sty_dpx() {
} break;
case 4: {
if(regs.p.x)last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, regs.y.w);
op_writedp(dp + regs.x.w, regs.y.w);
if(regs.p.x)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_write(OPMODE_DP, dp + regs.x.w + 1, regs.y.w >> 8);
op_writedp(dp + regs.x.w + 1, regs.y.w >> 8);
status.cycle_pos = 0;
} break;
}
@@ -337,7 +337,7 @@ void bCPU::op_sty_dpx() {
void bCPU::op_stz_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -347,12 +347,12 @@ void bCPU::op_stz_dpx() {
} break;
case 4: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, 0x0000);
op_writedp(dp + regs.x.w, 0x0000);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_write(OPMODE_DP, dp + regs.x.w + 1, 0x0000 >> 8);
op_writedp(dp + regs.x.w + 1, 0x0000 >> 8);
status.cycle_pos = 0;
} break;
}
@@ -361,7 +361,7 @@ void bCPU::op_stz_dpx() {
void bCPU::op_stx_dpy() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -371,12 +371,12 @@ void bCPU::op_stx_dpy() {
} break;
case 4: {
if(regs.p.x)last_cycle();
op_write(OPMODE_DP, dp + regs.y.w, regs.x.l);
op_writedp(dp + regs.y.w, regs.x.l);
if(regs.p.x)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_write(OPMODE_DP, dp + regs.y.w + 1, regs.x.h);
op_writedp(dp + regs.y.w + 1, regs.x.h);
status.cycle_pos = 0;
} break;
}
@@ -385,25 +385,25 @@ void bCPU::op_stx_dpy() {
void bCPU::op_sta_idp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
aa.l = op_read(OPMODE_DP, dp);
aa.l = op_readdp(dp);
} break;
case 4: {
aa.h = op_read(OPMODE_DP, dp + 1);
aa.h = op_readdp(dp + 1);
} break;
case 5: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w, regs.a.l);
op_writedbr(aa.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 6: {
last_cycle();
op_write(OPMODE_DBR, aa.w + 1, regs.a.h);
op_writedbr(aa.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
@@ -412,28 +412,28 @@ void bCPU::op_sta_idp() {
void bCPU::op_sta_ildp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
aa.l = op_read(OPMODE_DP, dp);
aa.l = op_readdp(dp);
} break;
case 4: {
aa.h = op_read(OPMODE_DP, dp + 1);
aa.h = op_readdp(dp + 1);
} break;
case 5: {
aa.b = op_read(OPMODE_DP, dp + 2);
aa.b = op_readdp(dp + 2);
} break;
case 6: {
if(regs.p.m)last_cycle();
op_write(OPMODE_LONG, aa.d, regs.a.l);
op_writelong(aa.d, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 7: {
last_cycle();
op_write(OPMODE_LONG, aa.d + 1, regs.a.h);
op_writelong(aa.d + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
@@ -442,7 +442,7 @@ void bCPU::op_sta_ildp() {
void bCPU::op_sta_idpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -451,19 +451,19 @@ void bCPU::op_sta_idpx() {
cpu_io();
} break;
case 4: {
aa.l = op_read(OPMODE_DP, dp + regs.x.w);
aa.l = op_readdp(dp + regs.x.w);
} break;
case 5: {
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
aa.h = op_readdp(dp + regs.x.w + 1);
} break;
case 6: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w, regs.a.l);
op_writedbr(aa.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w + 1, regs.a.h);
op_writedbr(aa.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
@@ -472,28 +472,28 @@ void bCPU::op_sta_idpx() {
void bCPU::op_sta_idpy() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
aa.l = op_read(OPMODE_DP, dp);
aa.l = op_readdp(dp);
} break;
case 4: {
aa.h = op_read(OPMODE_DP, dp + 1);
aa.h = op_readdp(dp + 1);
} break;
case 5: {
cpu_c4(aa.w, aa.w + regs.y.w);
} break;
case 6: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l);
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h);
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
@@ -502,28 +502,28 @@ void bCPU::op_sta_idpy() {
void bCPU::op_sta_ildpy() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
aa.l = op_read(OPMODE_DP, dp);
aa.l = op_readdp(dp);
} break;
case 4: {
aa.h = op_read(OPMODE_DP, dp + 1);
aa.h = op_readdp(dp + 1);
} break;
case 5: {
aa.b = op_read(OPMODE_DP, dp + 2);
aa.b = op_readdp(dp + 2);
} break;
case 6: {
if(regs.p.m)last_cycle();
op_write(OPMODE_LONG, aa.d + regs.y.w, regs.a.l);
op_writelong(aa.d + regs.y.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 7: {
last_cycle();
op_write(OPMODE_LONG, aa.d + regs.y.w + 1, regs.a.h);
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
@@ -532,19 +532,19 @@ void bCPU::op_sta_ildpy() {
void bCPU::op_sta_sr() {
switch(status.cycle_pos++) {
case 1: {
sp = op_read();
sp = op_readpc();
} break;
case 2: {
cpu_io();
} break;
case 3: {
if(regs.p.m)last_cycle();
op_write(OPMODE_SP, sp, regs.a.l);
op_writesp(sp, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_write(OPMODE_SP, sp + 1, regs.a.h);
op_writesp(sp + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
@@ -553,28 +553,28 @@ void bCPU::op_sta_sr() {
void bCPU::op_sta_isry() {
switch(status.cycle_pos++) {
case 1: {
sp = op_read();
sp = op_readpc();
} break;
case 2: {
cpu_io();
} break;
case 3: {
aa.l = op_read(OPMODE_SP, sp);
aa.l = op_readsp(sp);
} break;
case 4: {
aa.h = op_read(OPMODE_SP, sp + 1);
aa.h = op_readsp(sp + 1);
} break;
case 5: {
cpu_io();
} break;
case 6: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l);
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h);
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
+41 -46
View File
@@ -24,13 +24,27 @@ uint8 r;
//read from address bus b, write to address bus a
//block invalid writes, see comments above
r = (bbus == 0x80) ? r_cpu->regs.mdr : r_mem->read(0x2100 | bbus);
r = r_mem->read(0x2100 | bbus);
if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300 ||
(abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c)return;
r_mem->write(abus, r);
}
}
uint8 bCPU::dma_bbus(uint8 i, uint8 index) {
switch(channel[i].xfermode) {
default:
case 0: return (channel[i].destaddr); break; //0
case 1: return (channel[i].destaddr + (index & 1)); break; //0,1
case 2: return (channel[i].destaddr); break; //0,0
case 3: return (channel[i].destaddr + ((index >> 1) & 1)); break; //0,0,1,1
case 4: return (channel[i].destaddr + (index & 3)); break; //0,1,2,3
case 5: return (channel[i].destaddr + (index & 1)); break; //0,1,0,1
case 6: return (channel[i].destaddr); break; //0,0 [2]
case 7: return (channel[i].destaddr + ((index >> 1) & 1)); break; //0,0,1,1 [3]
}
}
void bCPU::dma_add_cycles(uint32 cycles) {
status.dma_cycle_count += cycles;
}
@@ -53,19 +67,19 @@ uint32 r;
return r;
}
void bCPU::dma_cputommio(uint8 i, uint8 index) {
if(sdd1->dma_active() == true) {
r_mem->write(0x2100 | ((channel[i].destaddr + index) & 0xff), sdd1->dma_read());
void bCPU::dma_cputommio(uint8 i, uint8 bbus) {
if(cartridge.info.sdd1 == true && sdd1->dma_active() == true) {
r_mem->write(0x2100 | bbus, sdd1->dma_read());
} else {
dma_transfer_byte(0, ((channel[i].destaddr + index) & 0xff), dma_addr(i));
dma_transfer_byte(0, bbus, dma_addr(i));
}
add_cycles(8);
channel[i].xfersize--;
}
void bCPU::dma_mmiotocpu(uint8 i, uint8 index) {
dma_transfer_byte(1, ((channel[i].destaddr + index) & 0xff), dma_addr(i));
void bCPU::dma_mmiotocpu(uint8 i, uint8 bbus) {
dma_transfer_byte(1, bbus, dma_addr(i));
add_cycles(8);
channel[i].xfersize--;
@@ -81,30 +95,19 @@ void bCPU::dma_write(uint8 i, uint8 index) {
void bCPU::dma_run() {
for(int i = 0; i < 8; i++) {
if(channel[i].active == false)continue;
if(channel[i].dma_enabled == false)continue;
//first byte transferred?
if(channel[i].read_index == 0) {
if(cartridge.info.sdd1 == true && channel[i].read_index == 0) {
sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr),
channel[i].xfersize);
}
switch(channel[i].xfermode) {
case 0: dma_write(i, 0); break; //0
case 1: dma_write(i, channel[i].read_index & 1); break; //0,1
case 2: dma_write(i, 0); break; //0,0
case 3: dma_write(i, (channel[i].read_index >> 1) & 1); break; //0,0,1,1
case 4: dma_write(i, channel[i].read_index & 3); break; //0,1,2,3
case 5: dma_write(i, channel[i].read_index & 1); break; //0,1,0,1
case 6: dma_write(i, 0); break; //0,0 [2]
case 7: dma_write(i, (channel[i].read_index >> 1) & 1); break; //0,0,1,1 [3]
}
channel[i].read_index++;
dma_write(i, dma_bbus(i, channel[i].read_index++));
dma_add_cycles(8);
if(channel[i].xfersize == 0) {
channel[i].active = false;
channel[i].dma_enabled = false;
}
return;
@@ -121,23 +124,6 @@ uint32 bCPU::hdma_iaddr(uint8 i) {
return (channel[i].hdma_ibank << 16) | (channel[i].hdma_iaddr++);
}
uint16 bCPU::hdma_mmio(uint8 i) {
uint8 l = channel[i].read_index;
uint16 index;
switch(channel[i].xfermode) {
case 0: index = 0; break; //0
case 1: index = l & 1; break; //0,1
case 2: index = 0; break; //0,0
case 3: index = (l >> 1) & 1; break; //0,0,1,1
case 4: index = l & 3; break; //0,1,2,3
case 5: index = l & 1; break; //0,1,0,1
case 6: index = 0; break; //0,0 [2]
case 7: index = (l >> 1) & 1; break; //0,0,1,1 [3]
}
return (0x2100 | ((channel[i].destaddr + index) & 0xff));
}
void bCPU::hdma_update(uint8 i) {
channel[i].hdma_line_counter = r_mem->read(hdma_addr(i));
add_cycles(8);
@@ -150,7 +136,7 @@ void bCPU::hdma_update(uint8 i) {
}
if(channel[i].hdma_line_counter == 0) {
channel[i].hdma_active = false;
channel[i].hdma_completed = true;
channel[i].hdma_do_transfer = false;
return;
}
@@ -168,13 +154,13 @@ void bCPU::hdma_update(uint8 i) {
void bCPU::hdma_run() {
static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
for(int i = 0; i < 8; i++) {
if(!channel[i].hdma_enabled || !channel[i].hdma_active)continue;
if(!channel[i].hdma_enabled || channel[i].hdma_completed)continue;
if(channel[i].hdma_do_transfer) {
int xferlen = hdma_xferlen[channel[i].xfermode];
for(channel[i].read_index = 0; channel[i].read_index < xferlen; channel[i].read_index++) {
if(bool(config::cpu.hdma_enable) == true) {
dma_transfer_byte(channel[i].direction, hdma_mmio(i),
dma_transfer_byte(channel[i].direction, dma_bbus(i, channel[i].read_index),
channel[i].hdma_indirect ? hdma_iaddr(i) : hdma_addr(i));
}
add_cycles(8);
@@ -190,6 +176,15 @@ static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
}
}
void bCPU::hdma_init() {
for(int i = 0; i < 8; i++) {
if(!channel[i].hdma_enabled)continue;
channel[i].hdma_addr = channel[i].srcaddr;
hdma_update(i);
}
}
uint8 bCPU::hdma_enabled_channels() {
int r = 0;
for(int i = 0; i < 8; i++) {
@@ -201,7 +196,7 @@ int r = 0;
uint8 bCPU::hdma_active_channels() {
int r = 0;
for(int i = 0; i < 8; i++) {
if(channel[i].hdma_enabled && channel[i].hdma_active)r++;
if(channel[i].hdma_enabled && !channel[i].hdma_completed)r++;
}
return r;
}
@@ -215,7 +210,7 @@ int r = 0;
void bCPU::hdmainit_activate() {
for(int i = 0; i < 8; i++) {
channel[i].hdma_active = false;
channel[i].hdma_completed = false;
channel[i].hdma_do_transfer = false;
}
@@ -240,7 +235,7 @@ void bCPU::dma_reset() {
for(int i = 0; i < 8; i++) {
channel[i].read_index = 0;
channel[i].active = false;
channel[i].dma_enabled = false;
channel[i].hdma_enabled = false;
channel[i].dmap = 0xff;
channel[i].direction = 1;
@@ -259,7 +254,7 @@ void bCPU::dma_reset() {
channel[i].hdma_line_counter = 0xff;
channel[i].hdma_unknown = 0xff;
channel[i].hdma_active = false;
channel[i].hdma_completed = false;
channel[i].hdma_do_transfer = false;
}
}
+4 -3
View File
@@ -2,7 +2,7 @@ struct {
uint32 read_index; //set to 0 at beginning of DMA/HDMA
//$420b
bool active;
bool dma_enabled;
//$420c
bool hdma_enabled;
//$43x0
@@ -33,7 +33,7 @@ struct {
uint8 hdma_unknown;
//hdma-specific
bool hdma_active;
bool hdma_completed; //for this frame
bool hdma_do_transfer;
uint8 hdma_current_channel;
@@ -41,10 +41,12 @@ struct {
} channel[8];
inline void dma_transfer_byte(bool direction, uint8 bbus, uint32 abus);
inline uint8 dma_bbus(uint8 i, uint8 index);
inline void dma_add_cycles(uint32 cycles);
inline void hdma_add_cycles(uint32 cycles);
inline void dma_run();
inline void hdma_run();
inline void hdma_init();
inline void hdma_update(uint8 i);
inline uint8 hdma_enabled_channels();
inline uint8 hdma_active_channels();
@@ -56,5 +58,4 @@ struct {
inline uint32 dma_addr(uint8 i);
inline uint32 hdma_addr(uint8 i);
inline uint32 hdma_iaddr(uint8 i);
inline uint16 hdma_mmio(uint8 i);
inline void dma_reset();
+20
View File
@@ -5,3 +5,23 @@ uint8 apu_port[4];
inline void cpu_io();
inline uint8 mem_read(uint32 addr);
inline void mem_write(uint32 addr, uint8 value);
/*****
* helper memory addressing functions used by CPU core
*****/
uint8 op_readpc () { return mem_read((regs.pc.b << 16) + regs.pc.w++); }
uint8 op_readstack() { (regs.e) ? regs.s.l++ : regs.s.w++; return mem_read(regs.s.w); }
uint8 op_readaddr (uint32 addr) { return mem_read(uclip<16>(addr)); }
uint8 op_readlong (uint32 addr) { return mem_read(uclip<24>(addr)); }
uint8 op_readdbr (uint32 addr) { return mem_read(uclip<24>((regs.db << 16) + addr)); }
uint8 op_readpbr (uint32 addr) { return mem_read((regs.pc.b << 16) + uclip<16>(addr)); }
uint8 op_readdp (uint32 addr) { return mem_read(uclip<16>(regs.d + uclip<16>(addr))); }
uint8 op_readsp (uint32 addr) { return mem_read(uclip<16>(regs.s + uclip<16>(addr))); }
void op_writestack(uint8 data) { mem_write(regs.s.w, data); (regs.e) ? regs.s.l-- : regs.s.w--; }
void op_writeaddr (uint32 addr, uint8 data) { mem_write(uclip<16>(addr), data); }
void op_writelong (uint32 addr, uint8 data) { mem_write(uclip<24>(addr), data); }
void op_writedbr (uint32 addr, uint8 data) { mem_write(uclip<24>((regs.db << 16) + addr), data); }
void op_writepbr (uint32 addr, uint8 data) { mem_write((regs.pc.b << 16) + uclip<16>(addr), data); }
void op_writedp (uint32 addr, uint8 data) { mem_write(uclip<16>(regs.d + uclip<16>(addr)), data); }
void op_writesp (uint32 addr, uint8 data) { mem_write(uclip<16>(regs.s + uclip<16>(addr)), data); }
+107 -127
View File
@@ -26,8 +26,7 @@
*/
uint16 bCPU::vcounter() { return time.v; }
uint16 bCPU::hcounter() { return get_hcounter(); }
uint16 bCPU::hcycles() { return time.hc; }
uint16 bCPU::hclock() { return time.hc; }
bool bCPU::interlace() { return time.interlace; }
bool bCPU::interlace_field() { return time.interlace_field; }
@@ -39,6 +38,13 @@ void bCPU::set_overscan (bool r) { time.overscan = r; update_interrupts(); }
uint8 bCPU::dma_counter() { return (time.dma_counter + time.hc) & 6; }
uint16 bCPU::hcounter() {
if(time.v == 240 && time.interlace == false && time.interlace_field == 1) {
return time.hc >> 2;
}
return (time.hc - ((time.hc > 1292) << 1) - ((time.hc > 1310) << 1)) >> 2;
}
bool bCPU::nmi_trigger_pos_match(uint32 offset) {
uint16 v = overscan() ? 240 : 225;
uint16 hc = 2 + offset;
@@ -48,15 +54,16 @@ uint16 hc = 2 + offset;
bool bCPU::irq_trigger_pos_match(uint32 offset) {
uint16 v = status.virq_pos;
uint16 hc = (status.hirq_enabled) ? status.hirq_pos : 0;
uint16 vlimit = region_scanlines() >> 1;
//positions that can never be latched
//region_scanlines() = 262/NTSC, 312/PAL
//region_scanlines() = 525/NTSC, 625/PAL
//PAL results are unverified on hardware
if(v == 240 && hc == 339 && interlace() == false && interlace_field() == 1)return false;
if(v == (region_scanlines() - 1) && hc == 339 && interlace() == false)return false;
if(v == region_scanlines() && interlace() == false)return false;
if(v == region_scanlines() && hc == 339)return false;
if(v > region_scanlines())return false;
if(v == (vlimit - 1) && hc == 339 && interlace() == false)return false;
if(v == vlimit && interlace() == false)return false;
if(v == vlimit && hc == 339)return false;
if(v > vlimit)return false;
if(hc > 339)return false;
hc = (hc != 0) ? ((hc << 2) + 14) : 10;
@@ -88,15 +95,16 @@ void bCPU::update_nmi() {
void bCPU::update_irq() {
int vpos = status.virq_pos;
int hpos = (status.hirq_enabled) ? status.hirq_pos : 0;
int vlimit = region_scanlines() >> 1;
//positions that can never be latched
//region_scanlines() = 262/NTSC, 312/PAL
//PAL results are unverified on hardware
if(vpos == 240 && hpos == 339 && interlace() == false && interlace_field() == 1)goto _nolatch;
if(vpos == (region_scanlines() - 1) && hpos == 339 && interlace() == false)goto _nolatch;
if(vpos == region_scanlines() && interlace() == false)goto _nolatch;
if(vpos == region_scanlines() && hpos == 339)goto _nolatch;
if(vpos > region_scanlines())goto _nolatch;
if(vpos == (vlimit - 1) && hpos == 339 && interlace() == false)goto _nolatch;
if(vpos == vlimit && interlace() == false)goto _nolatch;
if(vpos == vlimit && hpos == 339)goto _nolatch;
if(vpos > vlimit)goto _nolatch;
if(hpos > 339)goto _nolatch;
hpos = (hpos != 0) ? ((hpos << 2) + 14) : 10;
@@ -177,36 +185,63 @@ int16 hc, hc_end;
}
}
//all scanlines are 1364 cycles long, except scanline 240
//on non-interlace odd-frames, which is 1360 cycles long.
//[NTSC]
//interlace mode has 525 scanlines: 263 on the even frame,
//and 262 on the odd.
//non-interlace mode has 524 scanlines: 262 scanlines on
//both even and odd frames.
//[PAL] <PAL info is unverified on hardware>
//interlace mode has 625 scanlines: 313 on the even frame,
//and 312 on the odd.
//non-interlace mode has 624 scanlines: 312 scanlines on
//both even and odd frames.
//
//cycles per frame:
// 263 * 1364 = 358732
// 262 * 1364 = 357368
// 262 * 1364 - 4 = 357364
void bCPU::inc_vcounter() {
time.v++;
if(time.v >= time.frame_lines) {
time.v = 0;
time.interlace_field ^= 1;
uint32 bCPU::clocks_executed() {
uint32 r = status.cycles_executed;
status.cycles_executed = 0;
return r;
}
if(interlace() == true && interlace_field() == 0) {
time.frame_lines = time.region_scanlines + 1;
} else {
time.frame_lines = time.region_scanlines;
void bCPU::cycle_edge() {
if(time.line_rendered == false) {
if(time.hc >= 192) {
time.line_rendered = true;
r_ppu->render_scanline();
}
}
if(time.hdmainit_triggered == false) {
if(time.hc >= time.hdmainit_trigger_pos || time.v) {
time.hdmainit_triggered = true;
hdmainit_activate();
}
}
if(time.hdma_triggered == false) {
//hdma_triggered only set to false for v <= (overscan ? 239 : 224)
if(time.hc >= 1106) {
time.hdma_triggered = true;
hdma_activate();
}
}
}
void bCPU::add_cycles(int cycles) {
status.cycles_executed += cycles;
poll_interrupts(cycles);
if(time.hc + cycles >= time.line_cycles) {
cycles = (time.hc + cycles) - time.line_cycles;
time.hc = 0;
scanline();
poll_interrupts(cycles);
}
time.hc += cycles;
if(time.dram_refreshed == false) {
if(time.hc >= time.dram_refresh_pos) {
time.dram_refreshed = true;
add_cycles(40);
return;
}
}
}
void bCPU::scanline() {
if(++time.v >= time.frame_lines) {
frame();
}
time.dma_counter += time.line_cycles;
if(time.v == 240 && time.interlace == false && time.interlace_field == 1) {
time.line_cycles = 1360;
@@ -215,103 +250,48 @@ void bCPU::inc_vcounter() {
}
time.dram_refreshed = false;
time.line_rendered =
time.hdma_triggered = (time.v <= (!overscan() ? 224 : 239)) ? false : true;
r_ppu->scanline();
snes->scanline();
update_interrupts();
}
//all dots are 4 cycles long, except dots 323 and 327. dots 323 and 327
//are 6 cycles long. this holds true for all scanlines except scanline
//240 on non-interlace odd frames. the reason for this is because this
//scanline is only 1360 cycles long, instead of 1364 like all other
//scanlines.
//this makes the effective range of hscan_pos 0-339 at all times.
//dot 323 range = { 1292, 1294, 1296 }
//dot 327 range = { 1310, 1312, 1314 }
uint16 bCPU::get_hcounter() {
if(time.v == 240 && time.interlace == false && time.interlace_field == 1) {
return time.hc >> 2;
}
return (time.hc - ((time.hc > 1292) << 1) - ((time.hc > 1310) << 1)) >> 2;
}
uint32 bCPU::cycles_executed() {
uint32 r = status.cycles_executed;
status.cycles_executed = 0;
return r;
}
void bCPU::cycle_edge() {
if(time.hdmainit_triggered == false) {
if(time.hc >= time.hdmainit_trigger_pos || time.v) {
time.hdmainit_triggered = true;
hdmainit_activate();
}
}
if(time.hdma_triggered == false) {
if(time.v <= (overscan() ? 239 : 224)) {
if(time.hc >= 1106) {
time.hdma_triggered = true;
hdma_activate();
}
}
if(vcounter() == (!overscan() ? 227 : 242) && status.auto_joypad_poll == true) {
snes->poll_input();
//When the SNES auto-polls the joypads, it writes 1, then 0 to
//$4016, then reads from each 16 times to get the joypad state
//information. As a result, the joypad read positions are set
//to 16 after such a poll. Position 16 is the controller
//connected status bit.
status.joypad1_read_pos = 16;
status.joypad2_read_pos = 16;
}
}
void bCPU::add_cycles(int cycles) {
status.cycles_executed += cycles;
void bCPU::frame() {
time.nmi_read = 1;
time.nmi_line = 1;
time.nmi_transition = 0;
poll_interrupts(cycles);
if(time.hc + cycles >= time.line_cycles) {
cycles = (time.hc + cycles) - time.line_cycles;
time.hc = 0;
inc_vcounter();
poll_interrupts(cycles);
if(time.v == 0) {
frame();
r_ppu->frame();
snes->frame();
}
scanline();
r_ppu->scanline();
snes->scanline();
time.line_rendered = false;
time.v = 0;
time.interlace_field ^= 1;
if(interlace() == true && interlace_field() == 0) {
time.frame_lines = (time.region_scanlines >> 1) + 1;
} else {
time.frame_lines = (time.region_scanlines >> 1);
}
if(time.dram_refreshed == false) {
if(time.hc + cycles >= time.dram_refresh_pos) {
time.dram_refreshed = true;
status.cycles_executed += 40;
cycles = (time.hc + cycles) - time.dram_refresh_pos;
time.hc = time.dram_refresh_pos + 40;
if(cpu_version == 2) {
if(time.v != 240 || time.interlace != false || time.interlace_field != 1) {
if(time.dram_refresh_pos == 534) {
time.dram_refresh_pos = 538;
} else {
time.dram_refresh_pos = 534;
}
}
}
}
if(cpu_version == 2) {
time.hdmainit_trigger_pos = 12 + dma_counter();
} else {
time.hdmainit_trigger_pos = 12 + 8 - dma_counter();
}
time.hdmainit_triggered = false;
if(time.line_rendered == false) {
//rendering should start at H=18 (+256=274), but since the
//current PPU emulation renders the entire scanline at once,
//PPU register changes mid-scanline do not show up.
//therefore, wait a few dots before rendering the scanline
if(time.hc + cycles >= (48 * 4)) {
time.line_rendered = true;
r_ppu->render_scanline();
}
}
time.hc += cycles;
r_ppu->frame();
snes->frame();
}
void bCPU::time_reset() {
@@ -347,12 +327,12 @@ void bCPU::time_reset() {
switch(region) {
case NTSC:
time.region_scanlines = 262;
time.region_scanlines = 525;
break;
case PAL:
time.region_scanlines = 312;
time.region_scanlines = 625;
break;
}
time.frame_lines = time.region_scanlines;
time.frame_lines = time.region_scanlines >> 1;
}
+3 -3
View File
@@ -48,7 +48,7 @@ struct {
inline uint16 vcounter();
inline uint16 hcounter();
inline uint16 hcycles();
inline uint16 hclock();
inline bool interlace();
inline bool interlace_field();
inline bool overscan();
@@ -67,8 +67,8 @@ struct {
inline uint8 dma_counter();
inline void inc_vcounter();
inline uint16 get_hcounter();
inline void cycle_edge();
inline void add_cycles(int cycles);
inline void scanline();
inline void frame();
inline void time_reset();
+3
View File
@@ -4,3 +4,6 @@
CPU::CPU() {
cpu_version = 1;
}
CPU::~CPU() {
}
+30 -11
View File
@@ -11,10 +11,10 @@ uint8 cpu_version;
//timing
virtual uint16 vcounter() = 0;
virtual uint16 hcounter() = 0;
virtual uint16 hcycles() = 0;
virtual bool overscan() = 0;
virtual uint16 hclock() = 0;
virtual bool interlace() = 0;
virtual bool interlace_field() = 0;
virtual bool overscan() = 0;
virtual uint16 region_scanlines() = 0;
virtual void set_interlace(bool r) = 0;
virtual void set_overscan (bool r) = 0;
@@ -30,14 +30,32 @@ CPURegs regs;
FLAG_Z = 0x02, FLAG_C = 0x01
};
virtual uint8 pio_status() = 0;
virtual void main() {}
virtual void run() = 0;
virtual uint32 cycles_executed() = 0;
virtual uint32 clocks_executed() = 0;
virtual void scanline() = 0;
virtual void frame() = 0;
virtual void power() = 0;
virtual void reset() = 0;
//opcode disassembler
/*****
* in opcode-based CPU emulators, the main emulation routine
* will only be able to call the disassemble_opcode() function
* on clean opcode edges. but with cycle-based CPU emulators,
* the CPU may be in the middle of executing an opcode when the
* emulator (e.g. debugger) wants to disassemble an opcode. this
* would mean that important registers may not reflect what they
* did at the start of the opcode (especially regs.pc), so in
* cycle-based emulators, this function should be overridden to
* reflect whether or not an opcode has only been partially
* executed. if not, the debugger should abort attempts to skip,
* disable, or disassemble the current opcode.
*****/
virtual bool in_opcode() { return false; }
/*****
* opcode disassembler
*****/
enum {
OPTYPE_DP = 0, //dp
OPTYPE_DPX, //dp,x
@@ -57,17 +75,18 @@ enum {
OPTYPE_SR, //sr,s
OPTYPE_ISRY, //(sr,s),y
OPTYPE_ADDR_PC, //pbr:addr
OPTYPE_IADDR_PC //pbr:(addr)
OPTYPE_IADDR_PC, //pbr:(addr)
OPTYPE_RELB, //relb
OPTYPE_RELW, //relw
};
//see dcpu.cpp for notes on this function
virtual bool in_opcode();
void disassemble_opcode(char *output);
uint32 resolve_offset(uint8 offset_type, uint32 addr);
uint8 dreadb(uint32 addr);
uint16 dreadw(uint32 addr);
uint32 dreadl(uint32 addr);
uint32 decode(uint8 offset_type, uint32 addr);
uint8 opcode_length();
uint16 __relb(int8 offset);
uint16 __relw(int16 offset);
CPU();
virtual ~CPU() {}
virtual ~CPU();
};
+45 -66
View File
@@ -1,88 +1,66 @@
class CPURegFlags {
private:
template <uint8 B> class bit {
public:
uint8 _b;
inline operator bool() { return (_b & B); }
inline bool operator = (bool i) { (i) ? _b |= B : _b &= ~B; return (_b & B); }
inline bool operator & (bool i) { if(i)_b &= ~B; return (_b & B); }
inline bool operator &= (bool i) { if(i)_b &= ~B; return (_b & B); }
inline bool operator | (bool i) { if(i)_b |= B; return (_b & B); }
inline bool operator |= (bool i) { if(i)_b |= B; return (_b & B); }
inline bool operator ^ (bool i) { if(i)_b ^= B; return (_b & B); }
inline bool operator ^= (bool i) { if(i)_b ^= B; return (_b & B); }
};
public:
union {
uint8 _b;
bit<0x80> n;
bit<0x40> v;
bit<0x20> m, p;
bit<0x10> x, b;
bit<0x08> d;
bit<0x04> i;
bit<0x02> z;
bit<0x01> c;
uint8 data;
struct {
uint8 order_msb8(n:1, v:1, m:1, x:1, d:1, i:1, z:1, c:1);
};
};
CPURegFlags() { _b = 0; }
inline operator uint8() { return _b; }
inline unsigned operator = (uint8 i) { _b = i; return _b; }
inline unsigned operator &= (uint8 i) { _b &= i; return _b; }
inline unsigned operator |= (uint8 i) { _b |= i; return _b; }
inline unsigned operator ^= (uint8 i) { _b ^= i; return _b; }
inline operator unsigned() const { return data; }
template<typename T> inline unsigned operator = (const T i) { data = i; return data; }
template<typename T> inline unsigned operator |= (const T i) { data |= i; return data; }
template<typename T> inline unsigned operator ^= (const T i) { data ^= i; return data; }
template<typename T> inline unsigned operator &= (const T i) { data &= i; return data; }
CPURegFlags() : data(0) {}
};
class CPUReg16 {
public:
union {
uint16 w;
#ifdef ARCH_LSB
struct { uint8 l, h; };
#else
struct { uint8 h, l; };
#endif
struct { uint8 order_lsb2(l, h); };
};
CPUReg16() { w = 0; }
inline operator uint16() { return w; }
inline unsigned operator = (uint16 i) { w = i; return w; }
inline unsigned operator += (uint16 i) { w += i; return w; }
inline unsigned operator -= (uint16 i) { w -= i; return w; }
inline unsigned operator *= (uint16 i) { w *= i; return w; }
inline unsigned operator /= (uint16 i) { w /= i; return w; }
inline unsigned operator &= (uint16 i) { w &= i; return w; }
inline unsigned operator |= (uint16 i) { w |= i; return w; }
inline unsigned operator ^= (uint16 i) { w ^= i; return w; }
inline unsigned operator <<= (uint16 i) { w <<= i; return w; }
inline unsigned operator >>= (uint16 i) { w >>= i; return w; }
inline operator unsigned() const { return w; }
template<typename T> inline unsigned operator = (const T i) { w = i; return w; }
template<typename T> inline unsigned operator |= (const T i) { w |= i; return w; }
template<typename T> inline unsigned operator ^= (const T i) { w ^= i; return w; }
template<typename T> inline unsigned operator &= (const T i) { w &= i; return w; }
template<typename T> inline unsigned operator <<= (const T i) { w <<= i; return w; }
template<typename T> inline unsigned operator >>= (const T i) { w >>= i; return w; }
template<typename T> inline unsigned operator += (const T i) { w += i; return w; }
template<typename T> inline unsigned operator -= (const T i) { w -= i; return w; }
template<typename T> inline unsigned operator *= (const T i) { w *= i; return w; }
template<typename T> inline unsigned operator /= (const T i) { w /= i; return w; }
template<typename T> inline unsigned operator %= (const T i) { w %= i; return w; }
CPUReg16() : w(0) {}
};
class CPUReg24 {
public:
union {
uint32 d;
#ifdef ARCH_LSB
struct { uint16 w, null_w; };
struct { uint8 l, h, b, null_b; };
#else
struct { uint16 null_w, w; };
struct { uint8 null_b, b, h, l; };
#endif
struct { uint16 order_lsb2(w, wh); };
struct { uint8 order_lsb4(l, h, b, bh); };
};
CPUReg24() { d = 0; }
inline operator uint32() { return (d & 0xffffff); }
inline unsigned operator = (uint16 i) { d = i; return d; }
inline unsigned operator += (uint16 i) { d += i; return d; }
inline unsigned operator -= (uint16 i) { d -= i; return d; }
inline unsigned operator *= (uint16 i) { d *= i; return d; }
inline unsigned operator /= (uint16 i) { d /= i; return d; }
inline unsigned operator &= (uint16 i) { d &= i; return d; }
inline unsigned operator |= (uint16 i) { d |= i; return d; }
inline unsigned operator ^= (uint16 i) { d ^= i; return d; }
inline unsigned operator <<= (uint16 i) { d <<= i; return d; }
inline unsigned operator >>= (uint16 i) { d >>= i; return d; }
inline operator unsigned() const { return d; }
template<typename T> inline unsigned operator = (const T i) { d = uclip<24>(i); return d; }
template<typename T> inline unsigned operator |= (const T i) { d = uclip<24>(d | i); return d; }
template<typename T> inline unsigned operator ^= (const T i) { d = uclip<24>(d ^ i); return d; }
template<typename T> inline unsigned operator &= (const T i) { d = uclip<24>(d & i); return d; }
template<typename T> inline unsigned operator <<= (const T i) { d = uclip<24>(d << i); return d; }
template<typename T> inline unsigned operator >>= (const T i) { d = uclip<24>(d >> i); return d; }
template<typename T> inline unsigned operator += (const T i) { d = uclip<24>(d + i); return d; }
template<typename T> inline unsigned operator -= (const T i) { d = uclip<24>(d - i); return d; }
template<typename T> inline unsigned operator *= (const T i) { d = uclip<24>(d * i); return d; }
template<typename T> inline unsigned operator /= (const T i) { d = uclip<24>(d / i); return d; }
template<typename T> inline unsigned operator %= (const T i) { d = uclip<24>(d % i); return d; }
CPUReg24() : d(0) {}
};
class CPURegs {
@@ -91,7 +69,8 @@ CPUReg24 pc;
CPUReg16 a, x, y, s, d;
CPURegFlags p;
uint8 db;
uint8 mdr; //memory data register (openbus)
uint8 mdr;
bool e;
CPURegs() { db = 0; mdr = 0x00; e = false; }
bool acc_8b, idx_8b;
CPURegs() : db(0), mdr(0x00), e(false), acc_8b(true), idx_8b(true) {}
};
+354 -344
View File
@@ -1,30 +1,28 @@
//this is a virtual function.
//in opcode-based CPU emulators, the main emulation routine
//will only be able to call the disassemble_opcode() function
//on clean opcode edges. but with cycle-based CPU emulators,
//the CPU may be in the middle of executing an opcode when the
//emulator (e.g. debugger) wants to disassemble an opcode. this
//would mean that important registers may not reflect what they
//did at the start of the opcode (especially regs.pc), so in
//cycle-based emulators, this function should be overridden to
//reflect whether or not an opcode has only been partially
//executed. if not, the debugger should abort attempts to skip,
//disable, or disassemble the current opcode.
bool CPU::in_opcode() { return false; }
uint16 CPU::__relb(int8 offset) {
uint32 addr;
addr = (regs.pc.d & 0xff0000) | ((regs.pc.d + 2) & 0xffff);
return addr + offset;
uint8 CPU::dreadb(uint32 addr) {
if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) {
//$[00-3f|80-bf]:[2000-5fff]
//do not read MMIO registers within debugger
return 0x00;
}
return r_mem->read(addr);
}
uint16 CPU::__relw(int16 offset) {
uint32 addr;
addr = (regs.pc.d & 0xff0000) | ((regs.pc.d + 3) & 0xffff);
return addr + offset;
uint16 CPU::dreadw(uint32 addr) {
uint16 r;
r = dreadb((addr + 0) & 0xffffff) << 0;
r |= dreadb((addr + 1) & 0xffffff) << 8;
return r;
}
uint32 CPU::resolve_offset(uint8 offset_type, uint32 addr) {
uint32 CPU::dreadl(uint32 addr) {
uint32 r;
r = dreadb((addr + 0) & 0xffffff) << 0;
r |= dreadb((addr + 1) & 0xffffff) << 8;
r |= dreadb((addr + 2) & 0xffffff) << 16;
return r;
}
uint32 CPU::decode(uint8 offset_type, uint32 addr) {
uint32 r = 0;
switch(offset_type) {
case OPTYPE_DP:
@@ -38,23 +36,23 @@ uint32 r = 0;
break;
case OPTYPE_IDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + r_mem->read_word(addr);
r = (regs.db << 16) + dreadw(addr);
break;
case OPTYPE_IDPX:
addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + r_mem->read_word(addr);
r = (regs.db << 16) + dreadw(addr);
break;
case OPTYPE_IDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + r_mem->read_word(addr) + regs.y;
r = (regs.db << 16) + dreadw(addr) + regs.y;
break;
case OPTYPE_ILDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = r_mem->read_long(addr);
r = dreadl(addr);
break;
case OPTYPE_ILDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = r_mem->read_long(addr) + regs.y;
r = dreadl(addr) + regs.y;
break;
case OPTYPE_ADDR:
r = (regs.db << 16) + (addr & 0xffff);
@@ -75,31 +73,37 @@ uint32 r = 0;
r = (regs.pc.b << 16) + ((addr + regs.x) & 0xffff);
break;
case OPTYPE_ILADDR:
r = addr & 0xffffff;
r = addr;
break;
case OPTYPE_LONG:
r = addr & 0xffffff;
r = addr;
break;
case OPTYPE_LONGX:
r = (addr + regs.x) & 0xffffff;
r = (addr + regs.x);
break;
case OPTYPE_SR:
r = (regs.s + (addr & 0xff)) & 0xffff;
break;
case OPTYPE_ISRY:
addr = (regs.s + (addr & 0xff)) & 0xffff;
r = (regs.db << 16) + r_mem->read_word(addr) + regs.y;
r = (regs.db << 16) + dreadw(addr) + regs.y;
break;
case OPTYPE_RELB:
r = (regs.pc.b << 16) + ((regs.pc.w + 2) & 0xffff);
r += int8(addr);
break;
case OPTYPE_RELW:
r = (regs.pc.b << 16) + ((regs.pc.w + 3) & 0xffff);
r += int16(addr);
break;
}
return r;
return(r & 0xffffff);
}
void CPU::disassemble_opcode(char *output) {
char *s;
char t[256];
uint8 op, op0, op1, op2;
static CPUReg24 pc;
s = output;
char t[256];
char *s = output;
if(in_opcode() == true) {
strcpy(s, "?????? <CPU within opcode>");
@@ -107,332 +111,338 @@ static CPUReg24 pc;
}
pc.d = regs.pc.d;
sprintf(s, "%0.6x ", pc.d);
sprintf(s, "%0.6x ", uint32(pc.d));
op = r_mem->read(pc.d); pc.w++;
op0 = r_mem->read(pc.d); pc.w++;
op1 = r_mem->read(pc.d); pc.w++;
op2 = r_mem->read(pc.d);
uint8 op = dreadb(pc.d); pc.w++;
uint8 op0 = dreadb(pc.d); pc.w++;
uint8 op1 = dreadb(pc.d); pc.w++;
uint8 op2 = dreadb(pc.d);
#define op8 ((op0))
#define op16 ((op0) | (op1 << 8))
#define op24 ((op0) | (op1 << 8) | (op2 << 16))
#define a8 (regs.e || regs.p.m)
#define x8 (regs.e || regs.p.x)
switch(op) {
case 0x00:sprintf(t, "brk #$%0.2x ", op0);break;
case 0x01:sprintf(t, "ora ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0x02:sprintf(t, "cop #$%0.2x ", op0);break;
case 0x03:sprintf(t, "ora $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0x04:sprintf(t, "tsb $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x05:sprintf(t, "ora $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x06:sprintf(t, "asl $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x07:sprintf(t, "ora [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0x08:sprintf(t, "php ");break;
case 0x09:
if(regs.p.m)sprintf(t, "ora #$%0.2x ", op0);
else sprintf(t, "ora #$%0.4x ", op0|op1<<8);break;
case 0x0a:sprintf(t, "asl a ");break;
case 0x0b:sprintf(t, "phd ");break;
case 0x0c:sprintf(t, "tsb $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x0d:sprintf(t, "ora $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x0e:sprintf(t, "asl $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x0f:sprintf(t, "ora $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x10:sprintf(t, "bpl $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0x11:sprintf(t, "ora ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0x12:sprintf(t, "ora ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0x13:sprintf(t, "ora ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0x14:sprintf(t, "trb $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x15:sprintf(t, "ora $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x16:sprintf(t, "asl $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x17:sprintf(t, "ora [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0x18:sprintf(t, "clc ");break;
case 0x19:sprintf(t, "ora $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0x1a:sprintf(t, "inc ");break;
case 0x1b:sprintf(t, "tcs ");break;
case 0x1c:sprintf(t, "trb $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x1d:sprintf(t, "ora $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x1e:sprintf(t, "asl $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x1f:sprintf(t, "ora $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0x20:sprintf(t, "jsr $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR_PC, (op0|op1<<8)));break;
case 0x21:sprintf(t, "and ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0x22:sprintf(t, "jsl $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x23:sprintf(t, "and $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0x24:sprintf(t, "bit $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x25:sprintf(t, "and $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x26:sprintf(t, "rol $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x27:sprintf(t, "and [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0x28:sprintf(t, "plp ");break;
case 0x29:
if(regs.p.m)sprintf(t, "and #$%0.2x ", op0);
else sprintf(t, "and #$%0.4x ", op0|op1<<8);break;
case 0x2a:sprintf(t, "rol a ");break;
case 0x2b:sprintf(t, "pld ");break;
case 0x2c:sprintf(t, "bit $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x2d:sprintf(t, "and $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x2e:sprintf(t, "rol $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x2f:sprintf(t, "and $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x30:sprintf(t, "bmi $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0x31:sprintf(t, "and ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0x32:sprintf(t, "and ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0x33:sprintf(t, "and ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0x34:sprintf(t, "bit $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x35:sprintf(t, "and $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x36:sprintf(t, "rol $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x37:sprintf(t, "and [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0x38:sprintf(t, "sec ");break;
case 0x39:sprintf(t, "and $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0x3a:sprintf(t, "dec ");break;
case 0x3b:sprintf(t, "tsc ");break;
case 0x3c:sprintf(t, "bit $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x3d:sprintf(t, "and $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x3e:sprintf(t, "rol $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x3f:sprintf(t, "and $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0x40:sprintf(t, "rti ");break;
case 0x41:sprintf(t, "eor ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0x42:sprintf(t, "wdm ");break;
case 0x43:sprintf(t, "eor $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0x44:sprintf(t, "mvp $%0.2x,$%0.2x ", op1, op0);break;
case 0x45:sprintf(t, "eor $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x46:sprintf(t, "lsr $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x47:sprintf(t, "eor [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0x48:sprintf(t, "pha ");break;
case 0x49:
if(regs.p.m)sprintf(t, "eor #$%0.2x ", op0);
else sprintf(t, "eor #$%0.4x ", op0|op1<<8);break;
case 0x4a:sprintf(t, "lsr a ");break;
case 0x4b:sprintf(t, "phk ");break;
case 0x4c:sprintf(t, "jmp $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR_PC, (op0|op1<<8)));break;
case 0x4d:sprintf(t, "eor $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x4e:sprintf(t, "lsr $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x4f:sprintf(t, "eor $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x50:sprintf(t, "bvc $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0x51:sprintf(t, "eor ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0x52:sprintf(t, "eor ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0x53:sprintf(t, "eor ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0x54:sprintf(t, "mvn $%0.2x,$%0.2x ", op1, op0);break;
case 0x55:sprintf(t, "eor $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x56:sprintf(t, "lsr $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x57:sprintf(t, "eor [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0x58:sprintf(t, "cli ");break;
case 0x59:sprintf(t, "eor $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0x5a:sprintf(t, "phy ");break;
case 0x5b:sprintf(t, "tcd ");break;
case 0x5c:sprintf(t, "jml $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x5d:sprintf(t, "eor $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x5e:sprintf(t, "lsr $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x5f:sprintf(t, "eor $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0x60:sprintf(t, "rts ");break;
case 0x61:sprintf(t, "adc ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0x62:sprintf(t, "per $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x63:sprintf(t, "adc $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0x64:sprintf(t, "stz $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x65:sprintf(t, "adc $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x66:sprintf(t, "ror $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x67:sprintf(t, "adc [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0x68:sprintf(t, "pla ");break;
case 0x69:
if(regs.p.m)sprintf(t, "adc #$%0.2x ", op0);
else sprintf(t, "adc #$%0.4x ", op0|op1<<8);break;
case 0x6a:sprintf(t, "ror a ");break;
case 0x6b:sprintf(t, "rtl ");break;
case 0x6c:sprintf(t, "jmp ($%0.4x) [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_IADDR_PC, (op0|op1<<8)));break;
case 0x6d:sprintf(t, "adc $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x6e:sprintf(t, "ror $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x6f:sprintf(t, "adc $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x70:sprintf(t, "bvs $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0x71:sprintf(t, "adc ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0x72:sprintf(t, "adc ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0x73:sprintf(t, "adc ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0x74:sprintf(t, "stz $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x75:sprintf(t, "adc $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x76:sprintf(t, "ror $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x77:sprintf(t, "adc [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0x78:sprintf(t, "sei ");break;
case 0x79:sprintf(t, "adc $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0x7a:sprintf(t, "ply ");break;
case 0x7b:sprintf(t, "tdc ");break;
case 0x7c:sprintf(t, "jmp ($%0.4x,x) [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_IADDRX, (op0|op1<<8)));break;
case 0x7d:sprintf(t, "adc $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x7e:sprintf(t, "ror $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x7f:sprintf(t, "adc $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0x80:sprintf(t, "bra $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0x81:sprintf(t, "sta ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0x82:sprintf(t, "brl $%0.4x [$%0.6x]", __relw(op0|op1<<8)&0xffff, __relw(op0|op1<<8)&0xffffff);break;
case 0x83:sprintf(t, "sta $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0x84:sprintf(t, "sty $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x85:sprintf(t, "sta $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x86:sprintf(t, "stx $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x87:sprintf(t, "sta [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0x88:sprintf(t, "dey ");break;
case 0x89:
if(regs.p.m)sprintf(t, "bit #$%0.2x ", op0);
else sprintf(t, "bit #$%0.4x ", op0|op1<<8);break;
case 0x8a:sprintf(t, "txa ");break;
case 0x8b:sprintf(t, "phb ");break;
case 0x8c:sprintf(t, "sty $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x8d:sprintf(t, "sta $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x8e:sprintf(t, "stx $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x8f:sprintf(t, "sta $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x90:sprintf(t, "bcc $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0x91:sprintf(t, "sta ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0x92:sprintf(t, "sta ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0x93:sprintf(t, "sta ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0x94:sprintf(t, "sty $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x95:sprintf(t, "sta $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x96:sprintf(t, "stx $%0.2x,y [$%0.6x]", op0, resolve_offset(OPTYPE_DPY, op0));break;
case 0x97:sprintf(t, "sta [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0x98:sprintf(t, "tya ");break;
case 0x99:sprintf(t, "sta $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0x9a:sprintf(t, "txs ");break;
case 0x9b:sprintf(t, "txy ");break;
case 0x9c:sprintf(t, "stz $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x9d:sprintf(t, "sta $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x9e:sprintf(t, "stz $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x9f:sprintf(t, "sta $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0xa0:
if(regs.p.x)sprintf(t, "ldy #$%0.2x ", op0);
else sprintf(t, "ldy #$%0.4x ", op0|op1<<8);break;
case 0xa1:sprintf(t, "lda ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0xa2:
if(regs.p.x)sprintf(t, "ldx #$%0.2x ", op0);
else sprintf(t, "ldx #$%0.4x ", op0|op1<<8);break;
case 0xa3:sprintf(t, "lda $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0xa4:sprintf(t, "ldy $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xa5:sprintf(t, "lda $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xa6:sprintf(t, "ldx $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xa7:sprintf(t, "lda [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0xa8:sprintf(t, "tay ");break;
case 0xa9:
if(regs.p.m)sprintf(t, "lda #$%0.2x ", op0);
else sprintf(t, "lda #$%0.4x ", op0|op1<<8);break;
case 0xaa:sprintf(t, "tax ");break;
case 0xab:sprintf(t, "plb ");break;
case 0xac:sprintf(t, "ldy $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xad:sprintf(t, "lda $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xae:sprintf(t, "ldx $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xaf:sprintf(t, "lda $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0xb0:sprintf(t, "bcs $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0xb1:sprintf(t, "lda ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0xb2:sprintf(t, "lda ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0xb3:sprintf(t, "lda ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0xb4:sprintf(t, "ldy $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0xb5:sprintf(t, "lda $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0xb6:sprintf(t, "ldx $%0.2x,y [$%0.6x]", op0, resolve_offset(OPTYPE_DPY, op0));break;
case 0xb7:sprintf(t, "lda [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0xb8:sprintf(t, "clv ");break;
case 0xb9:sprintf(t, "lda $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0xba:sprintf(t, "tsx ");break;
case 0xbb:sprintf(t, "tyx ");break;
case 0xbc:sprintf(t, "ldy $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0xbd:sprintf(t, "lda $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0xbe:sprintf(t, "ldx $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0xbf:sprintf(t, "lda $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0xc0:
if(regs.p.x)sprintf(t, "cpy #$%0.2x ", op0);
else sprintf(t, "cpy #$%0.4x ", op0|op1<<8);break;
case 0xc1:sprintf(t, "cmp ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0xc2:sprintf(t, "rep #$%0.2x ", op0);break;
case 0xc3:sprintf(t, "cmp $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0xc4:sprintf(t, "cpy $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xc5:sprintf(t, "cmp $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xc6:sprintf(t, "dec $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xc7:sprintf(t, "cmp [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0xc8:sprintf(t, "iny ");break;
case 0xc9:
if(regs.p.m)sprintf(t, "cmp #$%0.2x ", op0);
else sprintf(t, "cmp #$%0.4x ", op0|op1<<8);break;
case 0xca:sprintf(t, "dex ");break;
case 0xcb:sprintf(t, "wai ");break;
case 0xcc:sprintf(t, "cpy $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xcd:sprintf(t, "cmp $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xce:sprintf(t, "dec $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xcf:sprintf(t, "cmp $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0xd0:sprintf(t, "bne $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0xd1:sprintf(t, "cmp ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0xd2:sprintf(t, "cmp ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0xd3:sprintf(t, "cmp ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0xd4:sprintf(t, "pei ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0xd5:sprintf(t, "cmp $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0xd6:sprintf(t, "dec $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0xd7:sprintf(t, "cmp [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0xd8:sprintf(t, "cld ");break;
case 0xd9:sprintf(t, "cmp $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0xda:sprintf(t, "phx ");break;
case 0xdb:sprintf(t, "stp ");break;
case 0xdc:sprintf(t, "jmp [$%0.4x] [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ILADDR, (op0|op1<<8)));break;
case 0xdd:sprintf(t, "cmp $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0xde:sprintf(t, "dec $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0xdf:sprintf(t, "cmp $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0xe0:
if(regs.p.x)sprintf(t, "cpx #$%0.2x ", op0);
else sprintf(t, "cpx #$%0.4x ", op0|op1<<8);break;
case 0xe1:sprintf(t, "sbc ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0xe2:sprintf(t, "sep #$%0.2x ", op0);break;
case 0xe3:sprintf(t, "sbc $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0xe4:sprintf(t, "cpx $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xe5:sprintf(t, "sbc $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xe6:sprintf(t, "inc $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xe7:sprintf(t, "sbc [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0xe8:sprintf(t, "inx ");break;
case 0xe9:
if(regs.p.m)sprintf(t, "sbc #$%0.2x ", op0);
else sprintf(t, "sbc #$%0.4x ", op0|op1<<8);break;
case 0xea:sprintf(t, "nop ");break;
case 0xeb:sprintf(t, "xba ");break;
case 0xec:sprintf(t, "cpx $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xed:sprintf(t, "sbc $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xee:sprintf(t, "inc $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xef:sprintf(t, "sbc $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0xf0:sprintf(t, "beq $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0xf1:sprintf(t, "sbc ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0xf2:sprintf(t, "sbc ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0xf3:sprintf(t, "sbc ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0xf4:sprintf(t, "pea $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xf5:sprintf(t, "sbc $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0xf6:sprintf(t, "inc $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0xf7:sprintf(t, "sbc [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0xf8:sprintf(t, "sed ");break;
case 0xf9:sprintf(t, "sbc $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0xfa:sprintf(t, "plx ");break;
case 0xfb:sprintf(t, "xce ");break;
case 0xfc:sprintf(t, "jsr ($%0.4x,x) [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_IADDRX, (op0|op1<<8)));break;
case 0xfd:sprintf(t, "sbc $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0xfe:sprintf(t, "inc $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0xff:sprintf(t, "sbc $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0x00: sprintf(t, "brk #$%0.2x ", op8); break;
case 0x01: sprintf(t, "ora ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x02: sprintf(t, "cop #$%0.2x ", op8); break;
case 0x03: sprintf(t, "ora $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x04: sprintf(t, "tsb $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x05: sprintf(t, "ora $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x06: sprintf(t, "asl $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x07: sprintf(t, "ora [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x08: sprintf(t, "php "); break;
case 0x09: if(a8)sprintf(t, "ora #$%0.2x ", op8);
else sprintf(t, "ora #$%0.4x ", op16); break;
case 0x0a: sprintf(t, "asl a "); break;
case 0x0b: sprintf(t, "phd "); break;
case 0x0c: sprintf(t, "tsb $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0d: sprintf(t, "ora $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0e: sprintf(t, "asl $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0f: sprintf(t, "ora $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x10: sprintf(t, "bpl $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x11: sprintf(t, "ora ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x12: sprintf(t, "ora ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x13: sprintf(t, "ora ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x14: sprintf(t, "trb $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x15: sprintf(t, "ora $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x16: sprintf(t, "asl $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x17: sprintf(t, "ora [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x18: sprintf(t, "clc "); break;
case 0x19: sprintf(t, "ora $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x1a: sprintf(t, "inc "); break;
case 0x1b: sprintf(t, "tcs "); break;
case 0x1c: sprintf(t, "trb $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x1d: sprintf(t, "ora $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x1e: sprintf(t, "asl $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x1f: sprintf(t, "ora $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x20: sprintf(t, "jsr $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break;
case 0x21: sprintf(t, "and ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x22: sprintf(t, "jsl $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x23: sprintf(t, "and $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x24: sprintf(t, "bit $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x25: sprintf(t, "and $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x26: sprintf(t, "rol $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x27: sprintf(t, "and [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x28: sprintf(t, "plp "); break;
case 0x29: if(a8)sprintf(t, "and #$%0.2x ", op8);
else sprintf(t, "and #$%0.4x ", op16); break;
case 0x2a: sprintf(t, "rol a "); break;
case 0x2b: sprintf(t, "pld "); break;
case 0x2c: sprintf(t, "bit $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2d: sprintf(t, "and $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2e: sprintf(t, "rol $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2f: sprintf(t, "and $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x30: sprintf(t, "bmi $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x31: sprintf(t, "and ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x32: sprintf(t, "and ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x33: sprintf(t, "and ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x34: sprintf(t, "bit $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x35: sprintf(t, "and $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x36: sprintf(t, "rol $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x37: sprintf(t, "and [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x38: sprintf(t, "sec "); break;
case 0x39: sprintf(t, "and $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x3a: sprintf(t, "dec "); break;
case 0x3b: sprintf(t, "tsc "); break;
case 0x3c: sprintf(t, "bit $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3d: sprintf(t, "and $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3e: sprintf(t, "rol $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3f: sprintf(t, "and $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x40: sprintf(t, "rti "); break;
case 0x41: sprintf(t, "eor ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x42: sprintf(t, "wdm "); break;
case 0x43: sprintf(t, "eor $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x44: sprintf(t, "mvp $%0.2x,$%0.2x ", op1, op8); break;
case 0x45: sprintf(t, "eor $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x46: sprintf(t, "lsr $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x47: sprintf(t, "eor [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x48: sprintf(t, "pha "); break;
case 0x49: if(a8)sprintf(t, "eor #$%0.2x ", op8);
else sprintf(t, "eor #$%0.4x ", op16); break;
case 0x4a: sprintf(t, "lsr a "); break;
case 0x4b: sprintf(t, "phk "); break;
case 0x4c: sprintf(t, "jmp $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break;
case 0x4d: sprintf(t, "eor $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x4e: sprintf(t, "lsr $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x4f: sprintf(t, "eor $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x50: sprintf(t, "bvc $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x51: sprintf(t, "eor ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x52: sprintf(t, "eor ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x53: sprintf(t, "eor ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x54: sprintf(t, "mvn $%0.2x,$%0.2x ", op1, op8); break;
case 0x55: sprintf(t, "eor $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x56: sprintf(t, "lsr $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x57: sprintf(t, "eor [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x58: sprintf(t, "cli "); break;
case 0x59: sprintf(t, "eor $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x5a: sprintf(t, "phy "); break;
case 0x5b: sprintf(t, "tcd "); break;
case 0x5c: sprintf(t, "jml $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x5d: sprintf(t, "eor $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x5e: sprintf(t, "lsr $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x5f: sprintf(t, "eor $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x60: sprintf(t, "rts "); break;
case 0x61: sprintf(t, "adc ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x62: sprintf(t, "per $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x63: sprintf(t, "adc $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x64: sprintf(t, "stz $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x65: sprintf(t, "adc $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x66: sprintf(t, "ror $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x67: sprintf(t, "adc [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x68: sprintf(t, "pla "); break;
case 0x69: if(a8)sprintf(t, "adc #$%0.2x ", op8);
else sprintf(t, "adc #$%0.4x ", op16); break;
case 0x6a: sprintf(t, "ror a "); break;
case 0x6b: sprintf(t, "rtl "); break;
case 0x6c: sprintf(t, "jmp ($%0.4x) [$%0.6x]", op16, decode(OPTYPE_IADDR_PC, op16)); break;
case 0x6d: sprintf(t, "adc $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x6e: sprintf(t, "ror $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x6f: sprintf(t, "adc $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x70: sprintf(t, "bvs $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x71: sprintf(t, "adc ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x72: sprintf(t, "adc ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x73: sprintf(t, "adc ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x74: sprintf(t, "stz $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x75: sprintf(t, "adc $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x76: sprintf(t, "ror $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x77: sprintf(t, "adc [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x78: sprintf(t, "sei "); break;
case 0x79: sprintf(t, "adc $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x7a: sprintf(t, "ply "); break;
case 0x7b: sprintf(t, "tdc "); break;
case 0x7c: sprintf(t, "jmp ($%0.4x,x) [$%0.6x]", op16, decode(OPTYPE_IADDRX, op16)); break;
case 0x7d: sprintf(t, "adc $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x7e: sprintf(t, "ror $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x7f: sprintf(t, "adc $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x80: sprintf(t, "bra $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x81: sprintf(t, "sta ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x82: sprintf(t, "brl $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELW, op16)), decode(OPTYPE_RELW, op16)); break;
case 0x83: sprintf(t, "sta $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x84: sprintf(t, "sty $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x85: sprintf(t, "sta $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x86: sprintf(t, "stx $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x87: sprintf(t, "sta [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x88: sprintf(t, "dey "); break;
case 0x89: if(a8)sprintf(t, "bit #$%0.2x ", op8);
else sprintf(t, "bit #$%0.4x ", op16); break;
case 0x8a: sprintf(t, "txa "); break;
case 0x8b: sprintf(t, "phb "); break;
case 0x8c: sprintf(t, "sty $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8d: sprintf(t, "sta $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8e: sprintf(t, "stx $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8f: sprintf(t, "sta $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x90: sprintf(t, "bcc $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x91: sprintf(t, "sta ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x92: sprintf(t, "sta ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x93: sprintf(t, "sta ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x94: sprintf(t, "sty $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x95: sprintf(t, "sta $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x96: sprintf(t, "stx $%0.2x,y [$%0.6x]", op8, decode(OPTYPE_DPY, op8)); break;
case 0x97: sprintf(t, "sta [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x98: sprintf(t, "tya "); break;
case 0x99: sprintf(t, "sta $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x9a: sprintf(t, "txs "); break;
case 0x9b: sprintf(t, "txy "); break;
case 0x9c: sprintf(t, "stz $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x9d: sprintf(t, "sta $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x9e: sprintf(t, "stz $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x9f: sprintf(t, "sta $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xa0: if(x8)sprintf(t, "ldy #$%0.2x ", op8);
else sprintf(t, "ldy #$%0.4x ", op16); break;
case 0xa1: sprintf(t, "lda ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xa2: if(x8)sprintf(t, "ldx #$%0.2x ", op8);
else sprintf(t, "ldx #$%0.4x ", op16); break;
case 0xa3: sprintf(t, "lda $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xa4: sprintf(t, "ldy $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa5: sprintf(t, "lda $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa6: sprintf(t, "ldx $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa7: sprintf(t, "lda [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xa8: sprintf(t, "tay "); break;
case 0xa9: if(a8)sprintf(t, "lda #$%0.2x ", op8);
else sprintf(t, "lda #$%0.4x ", op16); break;
case 0xaa: sprintf(t, "tax "); break;
case 0xab: sprintf(t, "plb "); break;
case 0xac: sprintf(t, "ldy $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xad: sprintf(t, "lda $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xae: sprintf(t, "ldx $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xaf: sprintf(t, "lda $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xb0: sprintf(t, "bcs $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xb1: sprintf(t, "lda ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xb2: sprintf(t, "lda ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xb3: sprintf(t, "lda ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xb4: sprintf(t, "ldy $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xb5: sprintf(t, "lda $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xb6: sprintf(t, "ldx $%0.2x,y [$%0.6x]", op8, decode(OPTYPE_DPY, op8)); break;
case 0xb7: sprintf(t, "lda [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xb8: sprintf(t, "clv "); break;
case 0xb9: sprintf(t, "lda $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xba: sprintf(t, "tsx "); break;
case 0xbb: sprintf(t, "tyx "); break;
case 0xbc: sprintf(t, "ldy $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xbd: sprintf(t, "lda $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xbe: sprintf(t, "ldx $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xbf: sprintf(t, "lda $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xc0: if(x8)sprintf(t, "cpy #$%0.2x ", op8);
else sprintf(t, "cpy #$%0.4x ", op16); break;
case 0xc1: sprintf(t, "cmp ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xc2: sprintf(t, "rep #$%0.2x ", op8); break;
case 0xc3: sprintf(t, "cmp $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xc4: sprintf(t, "cpy $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc5: sprintf(t, "cmp $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc6: sprintf(t, "dec $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc7: sprintf(t, "cmp [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xc8: sprintf(t, "iny "); break;
case 0xc9: if(a8)sprintf(t, "cmp #$%0.2x ", op8);
else sprintf(t, "cmp #$%0.4x ", op16); break;
case 0xca: sprintf(t, "dex "); break;
case 0xcb: sprintf(t, "wai "); break;
case 0xcc: sprintf(t, "cpy $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xcd: sprintf(t, "cmp $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xce: sprintf(t, "dec $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xcf: sprintf(t, "cmp $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xd0: sprintf(t, "bne $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xd1: sprintf(t, "cmp ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xd2: sprintf(t, "cmp ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xd3: sprintf(t, "cmp ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xd4: sprintf(t, "pei ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xd5: sprintf(t, "cmp $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xd6: sprintf(t, "dec $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xd7: sprintf(t, "cmp [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xd8: sprintf(t, "cld "); break;
case 0xd9: sprintf(t, "cmp $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xda: sprintf(t, "phx "); break;
case 0xdb: sprintf(t, "stp "); break;
case 0xdc: sprintf(t, "jmp [$%0.4x] [$%0.6x]", op16, decode(OPTYPE_ILADDR, op16)); break;
case 0xdd: sprintf(t, "cmp $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xde: sprintf(t, "dec $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xdf: sprintf(t, "cmp $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xe0: if(x8)sprintf(t, "cpx #$%0.2x ", op8);
else sprintf(t, "cpx #$%0.4x ", op16); break;
case 0xe1: sprintf(t, "sbc ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xe2: sprintf(t, "sep #$%0.2x ", op8); break;
case 0xe3: sprintf(t, "sbc $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xe4: sprintf(t, "cpx $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe5: sprintf(t, "sbc $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe6: sprintf(t, "inc $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe7: sprintf(t, "sbc [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xe8: sprintf(t, "inx "); break;
case 0xe9: if(a8)sprintf(t, "sbc #$%0.2x ", op8);
else sprintf(t, "sbc #$%0.4x ", op16); break;
case 0xea: sprintf(t, "nop "); break;
case 0xeb: sprintf(t, "xba "); break;
case 0xec: sprintf(t, "cpx $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xed: sprintf(t, "sbc $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xee: sprintf(t, "inc $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xef: sprintf(t, "sbc $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xf0: sprintf(t, "beq $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xf1: sprintf(t, "sbc ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xf2: sprintf(t, "sbc ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xf3: sprintf(t, "sbc ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xf4: sprintf(t, "pea $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xf5: sprintf(t, "sbc $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xf6: sprintf(t, "inc $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xf7: sprintf(t, "sbc [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xf8: sprintf(t, "sed "); break;
case 0xf9: sprintf(t, "sbc $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xfa: sprintf(t, "plx "); break;
case 0xfb: sprintf(t, "xce "); break;
case 0xfc: sprintf(t, "jsr ($%0.4x,x) [$%0.6x]", op16, decode(OPTYPE_IADDRX, op16)); break;
case 0xfd: sprintf(t, "sbc $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xfe: sprintf(t, "inc $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xff: sprintf(t, "sbc $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
}
#undef op8
#undef op16
#undef op24
#undef a8
#undef x8
strcat(s, t);
strcat(s, " ");
sprintf(t, "A:%0.4x X:%0.4x Y:%0.4x S:%0.4x D:%0.4x DB:%0.2x ",
regs.a.w, regs.x.w, regs.y.w, regs.s.w, regs.d.w, regs.db);
strcat(s, t);
if(regs.e) {
sprintf(t, "%c%c%c%c%c%c%c%c",
(regs.p.n)?'N':'n', (regs.p.v)?'V':'v',
(regs.p.m)?'1':'0', (regs.p.x)?'B':'b',
(regs.p.d)?'D':'d', (regs.p.i)?'I':'i',
(regs.p.z)?'Z':'z', (regs.p.c)?'C':'c');
(regs.p.n) ? 'N' : 'n', (regs.p.v) ? 'V' : 'v',
(regs.p.m) ? '1' : '0', (regs.p.x) ? 'B' : 'b',
(regs.p.d) ? 'D' : 'd', (regs.p.i) ? 'I' : 'i',
(regs.p.z) ? 'Z' : 'z', (regs.p.c) ? 'C' : 'c');
} else {
sprintf(t, "%c%c%c%c%c%c%c%c",
(regs.p.n)?'N':'n', (regs.p.v)?'V':'v',
(regs.p.m)?'M':'m', (regs.p.x)?'X':'x',
(regs.p.d)?'D':'d', (regs.p.i)?'I':'i',
(regs.p.z)?'Z':'z', (regs.p.c)?'C':'c');
(regs.p.n) ? 'N' : 'n', (regs.p.v) ? 'V' : 'v',
(regs.p.m) ? 'M' : 'm', (regs.p.x) ? 'X' : 'x',
(regs.p.d) ? 'D' : 'd', (regs.p.i) ? 'I' : 'i',
(regs.p.z) ? 'Z' : 'z', (regs.p.c) ? 'C' : 'c');
}
strcat(s, t);
strcat(s, " ");
sprintf(t, "V:%3d H:%4d", vcounter(), hclock());
strcat(s, t);
}
/*
opcode_length() retrieves the length of the next opcode
to be executed. It is used by the debugger to step over,
disable, and proceed cpu opcodes.
5 and 6 are special cases, 5 is used for #consts based on
the A register size, 6 for the X/Y register size. the
rest are literal sizes. There's no need to test for
emulation mode, as regs.p.m/regs.p.x should *always* be
set in emulation mode.
*/
/*****
* opcode_length() retrieves the length of the next opcode
* to be executed. It is used by the debugger to step over,
* disable and proceed cpu opcodes.
*
* 5 and 6 are special cases, 5 is used for #consts based on
* the A register size, 6 for the X/Y register size. the
* rest are literal sizes. There's no need to test for
* emulation mode, as regs.p.m/regs.p.x should *always* be
* set in emulation mode.
*****/
uint8 CPU::opcode_length() {
uint8 op, len;
static uint8 op_len_tbl[256] = {
//0,1,2,3, 4,5,6,7, 8,9,a,b, c,d,e,f
2,2,2,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x0n
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0x1n
3,2,4,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x2n
@@ -457,9 +467,9 @@ static uint8 op_len_tbl[256] = {
return 0;
}
op = r_mem->read(regs.pc.d);
op = dreadb(regs.pc.d);
len = op_len_tbl[op];
if(len == 5)return (regs.p.m)?2:3;
if(len == 6)return (regs.p.x)?2:3;
if(len == 5)return (regs.e || regs.p.m) ? 2 : 3;
if(len == 6)return (regs.e || regs.p.x) ? 2 : 3;
return len;
}
+3
View File
@@ -0,0 +1,3 @@
cl /nologo /O2 scpugen.cpp
@pause
@del *.obj
+1
View File
@@ -0,0 +1 @@
@del *.exe
+70
View File
@@ -0,0 +1,70 @@
#include "opfn.cpp"
void sCPU::main() {
for(;;) {
if(event.irq) {
event.irq = false;
if(status.nmi_pending == true) {
status.nmi_pending = false;
event.irq_vector = (regs.e == false) ? 0xffea : 0xfffa;
} else if(status.irq_pending == true) {
status.irq_pending = false;
event.irq_vector = (regs.e == false) ? 0xffee : 0xfffe;
}
op_irq();
}
tracer.trace_cpuop(); //traces CPU opcode (only if tracer is enabled)
status.in_opcode = true;
switch(op_readpc()) {
#include "op_read.cpp"
#include "op_write.cpp"
#include "op_rmw.cpp"
#include "op_pc.cpp"
#include "op_misc.cpp"
}
status.in_opcode = false;
#ifdef FAVOR_SPEED
co_return();
#endif
}
}
void sCPU::op_irq() {
op_read(regs.pc.d);
op_io();
if(!regs.e)op_writestack(regs.pc.b);
op_writestack(regs.pc.h);
op_writestack(regs.pc.l);
op_writestack(regs.e ? (regs.p & ~0x10) : regs.p);
rd.l = op_read(event.irq_vector + 0);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
rd.h = op_read(event.irq_vector + 1);
regs.pc.w = rd.w;
}
//
alwaysinline void sCPU::op_io_cond2() {
if(regs.d.l != 0x00) {
op_io();
}
}
alwaysinline void sCPU::op_io_cond4(uint16 x, uint16 y) {
if(!regs.p.x || (x & 0xff00) != (y & 0xff00)) {
op_io();
}
}
alwaysinline void sCPU::op_io_cond6(uint16 addr) {
if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) {
op_io();
}
}
+58
View File
@@ -0,0 +1,58 @@
//void (sCPU::*optbl[256])();
CPUReg24 aa, rd;
uint8 dp, sp;
inline void main();
inline void op_irq();
inline bool in_opcode() { return status.in_opcode; }
//op_read
void op_adc_b();
void op_adc_w();
void op_and_b();
void op_and_w();
void op_bit_b();
void op_bit_w();
void op_cmp_b();
void op_cmp_w();
void op_cpx_b();
void op_cpx_w();
void op_cpy_b();
void op_cpy_w();
void op_eor_b();
void op_eor_w();
void op_lda_b();
void op_lda_w();
void op_ldx_b();
void op_ldx_w();
void op_ldy_b();
void op_ldy_w();
void op_ora_b();
void op_ora_w();
void op_sbc_b();
void op_sbc_w();
//op_rmw
void op_inc_b();
void op_inc_w();
void op_dec_b();
void op_dec_w();
void op_asl_b();
void op_asl_w();
void op_lsr_b();
void op_lsr_w();
void op_rol_b();
void op_rol_w();
void op_ror_b();
void op_ror_w();
void op_trb_b();
void op_trb_w();
void op_tsb_b();
void op_tsb_w();
void op_io_cond2();
void op_io_cond4(uint16 x, uint16 y);
void op_io_cond6(uint16 addr);
//#include "op.h"
+282
View File
@@ -0,0 +1,282 @@
nop(0xea) {
1:last_cycle();
op_io();
}
wdm(0x42) {
1:last_cycle();
op_readpc();
}
xba(0xeb) {
1:op_io();
2:last_cycle();
op_io();
regs.a.l ^= regs.a.h;
regs.a.h ^= regs.a.l;
regs.a.l ^= regs.a.h;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
mvn(0x54, ++),
mvp(0x44, --) {
1:dp = op_readpc();
2:sp = op_readpc();
3:regs.db = dp;
rd.l = op_readlong((sp << 16) | regs.x.w);
4:op_writelong((dp << 16) | regs.y.w, rd.l);
5:op_io();
if(regs.idx_8b) {
regs.x.l $1; regs.y.l $1;
} else {
regs.x.w $1; regs.y.w $1;
}
6:last_cycle();
op_io();
if(regs.a.w--)regs.pc.w -= 3;
}
brk(0x00, 0xfffe, 0xffff, 0xffe6, 0xffe7),
cop(0x02, 0xfff4, 0xfff5, 0xffe4, 0xffe5) {
1:op_readpc();
2:if(!regs.e)op_writestack(regs.pc.b);
3:op_writestack(regs.pc.h);
4:op_writestack(regs.pc.l);
5:op_writestack(regs.p);
6:rd.l = op_readlong((regs.e) ? $1 : $3);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
7:last_cycle();
rd.h = op_readlong((regs.e) ? $2 : $4);
regs.pc.w = rd.w;
}
stp(0xdb) {
1:op_io();
2:last_cycle();
while(1) {
op_io();
co_return();
}
}
wai(0xcb) {
1:op_io();
event.wai = true;
2:last_cycle();
op_io();
3:while(event.wai) {
last_cycle();
op_io();
co_return();
}
}
xce(0xfb) {
1:last_cycle();
op_io();
bool c = regs.p.c;
regs.p.c = regs.e;
regs.e = c;
if(regs.e)regs.s.h = 0x01;
regs.acc_8b = (regs.e || regs.p.m);
regs.idx_8b = (regs.e || regs.p.x);
if(regs.idx_8b) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
}
clc(0x18, regs.p.c = 0),
cld(0xd8, regs.p.d = 0),
cli(0x58, regs.p.i = 0),
clv(0xb8, regs.p.v = 0),
sec(0x38, regs.p.c = 1),
sed(0xf8, regs.p.d = 1),
sei(0x78, regs.p.i = 1) {
1:last_cycle();
op_io();
$1;
}
rep(0xc2, &=~),
sep(0xe2, |=) {
1:rd.l = op_readpc();
2:last_cycle();
op_io();
regs.p $1 rd.l;
regs.acc_8b = (regs.e || regs.p.m);
regs.idx_8b = (regs.e || regs.p.x);
if(regs.idx_8b) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
}
tax(0xaa, regs.idx_8b, x, a),
tay(0xa8, regs.idx_8b, y, a),
txa(0x8a, regs.acc_8b, a, x),
txy(0x9b, regs.idx_8b, y, x),
tya(0x98, regs.acc_8b, a, y),
tyx(0xbb, regs.idx_8b, x, y) {
1:last_cycle();
op_io();
if($1) {
regs.$2.l = regs.$3.l;
regs.p.n = bool(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0);
} else {
regs.$2.w = regs.$3.w;
regs.p.n = bool(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0);
}
}
tcd(0x5b) {
1:last_cycle();
op_io();
regs.d.w = regs.a.w;
regs.p.n = bool(regs.d.w & 0x8000);
regs.p.z = (regs.d.w == 0);
}
tcs(0x1b) {
1:last_cycle();
op_io();
regs.s.w = regs.a.w;
if(regs.e)regs.s.h = 0x01;
}
tdc(0x7b) {
1:last_cycle();
op_io();
regs.a.w = regs.d.w;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
tsc(0x3b) {
1:last_cycle();
op_io();
regs.a.w = regs.s.w;
if(regs.e) {
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
tsx(0xba) {
1:last_cycle();
op_io();
if(regs.idx_8b) {
regs.x.l = regs.s.l;
regs.p.n = bool(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
} else {
regs.x.w = regs.s.w;
regs.p.n = bool(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
}
txs(0x9a) {
1:last_cycle();
op_io();
if(regs.e) {
regs.s.l = regs.x.l;
} else {
regs.s.w = regs.x.w;
}
}
pha(0x48, regs.acc_8b, a),
phx(0xda, regs.idx_8b, x),
phy(0x5a, regs.idx_8b, y),
phd(0x0b, 0, d) {
1:op_io();
2:if(!$1)op_writestack(regs.$2.h);
3:last_cycle();
op_writestack(regs.$2.l);
}
phb(0x8b, regs.db),
phk(0x4b, regs.pc.b),
php(0x08, regs.p) {
1:op_io();
2:last_cycle();
op_writestack($1);
}
pla(0x68, regs.acc_8b, a),
plx(0xfa, regs.idx_8b, x),
ply(0x7a, regs.idx_8b, y),
pld(0x2b, 0, d) {
1:op_io();
2:op_io();
3:if($1)last_cycle();
regs.$2.l = op_readstack();
if($1) {
regs.p.n = bool(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0);
end;
}
4:last_cycle();
regs.$2.h = op_readstack();
regs.p.n = bool(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0);
}
plb(0xab) {
1:op_io();
2:op_io();
3:last_cycle();
regs.db = op_readstack();
regs.p.n = bool(regs.db & 0x80);
regs.p.z = (regs.db == 0);
}
plp(0x28) {
1:op_io();
2:op_io();
3:last_cycle();
regs.p = op_readstack();
regs.acc_8b = (regs.e || regs.p.m);
regs.idx_8b = (regs.e || regs.p.x);
if(regs.idx_8b) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
}
pea(0xf4) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_writestack(aa.h);
4:last_cycle();
op_writestack(aa.l);
}
pei(0xd4) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:op_writestack(aa.h);
6:last_cycle();
op_writestack(aa.l);
}
per(0x62) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io();
rd.w = regs.pc.d + (int16)aa.w;
4:op_writestack(rd.h);
5:last_cycle();
op_writestack(rd.l);
}
+540
View File
@@ -0,0 +1,540 @@
//nop
case 0xea: {
last_cycle();
op_io();
} break;
//wdm
case 0x42: {
last_cycle();
op_readpc();
} break;
//xba
case 0xeb: {
op_io();
last_cycle();
op_io();
regs.a.l ^= regs.a.h;
regs.a.h ^= regs.a.l;
regs.a.l ^= regs.a.h;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} break;
//mvn
case 0x54: {
dp = op_readpc();
sp = op_readpc();
regs.db = dp;
rd.l = op_readlong((sp << 16) | regs.x.w);
op_writelong((dp << 16) | regs.y.w, rd.l);
op_io();
if(regs.idx_8b) {
regs.x.l ++; regs.y.l ++;
} else {
regs.x.w ++; regs.y.w ++;
}
last_cycle();
op_io();
if(regs.a.w--)regs.pc.w -= 3;
} break;
//mvp
case 0x44: {
dp = op_readpc();
sp = op_readpc();
regs.db = dp;
rd.l = op_readlong((sp << 16) | regs.x.w);
op_writelong((dp << 16) | regs.y.w, rd.l);
op_io();
if(regs.idx_8b) {
regs.x.l --; regs.y.l --;
} else {
regs.x.w --; regs.y.w --;
}
last_cycle();
op_io();
if(regs.a.w--)regs.pc.w -= 3;
} break;
//brk
case 0x00: {
op_readpc();
if(!regs.e)op_writestack(regs.pc.b);
op_writestack(regs.pc.h);
op_writestack(regs.pc.l);
op_writestack(regs.p);
rd.l = op_readlong((regs.e) ? 0xfffe : 0xffe6);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
last_cycle();
rd.h = op_readlong((regs.e) ? 0xffff : 0xffe7);
regs.pc.w = rd.w;
} break;
//cop
case 0x02: {
op_readpc();
if(!regs.e)op_writestack(regs.pc.b);
op_writestack(regs.pc.h);
op_writestack(regs.pc.l);
op_writestack(regs.p);
rd.l = op_readlong((regs.e) ? 0xfff4 : 0xffe4);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
last_cycle();
rd.h = op_readlong((regs.e) ? 0xfff5 : 0xffe5);
regs.pc.w = rd.w;
} break;
//stp
case 0xdb: {
op_io();
last_cycle();
while(1) {
op_io();
co_return();
}
} break;
//wai
case 0xcb: {
op_io();
event.wai = true;
last_cycle();
op_io();
while(event.wai) {
last_cycle();
op_io();
co_return();
}
} break;
//xce
case 0xfb: {
last_cycle();
op_io();
bool c = regs.p.c;
regs.p.c = regs.e;
regs.e = c;
if(regs.e)regs.s.h = 0x01;
regs.acc_8b = (regs.e || regs.p.m);
regs.idx_8b = (regs.e || regs.p.x);
if(regs.idx_8b) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
} break;
//clc
case 0x18: {
last_cycle();
op_io();
regs.p.c = 0;
} break;
//cld
case 0xd8: {
last_cycle();
op_io();
regs.p.d = 0;
} break;
//cli
case 0x58: {
last_cycle();
op_io();
regs.p.i = 0;
} break;
//clv
case 0xb8: {
last_cycle();
op_io();
regs.p.v = 0;
} break;
//sec
case 0x38: {
last_cycle();
op_io();
regs.p.c = 1;
} break;
//sed
case 0xf8: {
last_cycle();
op_io();
regs.p.d = 1;
} break;
//sei
case 0x78: {
last_cycle();
op_io();
regs.p.i = 1;
} break;
//rep
case 0xc2: {
rd.l = op_readpc();
last_cycle();
op_io();
regs.p &=~ rd.l;
regs.acc_8b = (regs.e || regs.p.m);
regs.idx_8b = (regs.e || regs.p.x);
if(regs.idx_8b) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
} break;
//sep
case 0xe2: {
rd.l = op_readpc();
last_cycle();
op_io();
regs.p |= rd.l;
regs.acc_8b = (regs.e || regs.p.m);
regs.idx_8b = (regs.e || regs.p.x);
if(regs.idx_8b) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
} break;
//tax
case 0xaa: {
last_cycle();
op_io();
if(regs.idx_8b) {
regs.x.l = regs.a.l;
regs.p.n = bool(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
} else {
regs.x.w = regs.a.w;
regs.p.n = bool(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
} break;
//tay
case 0xa8: {
last_cycle();
op_io();
if(regs.idx_8b) {
regs.y.l = regs.a.l;
regs.p.n = bool(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
} else {
regs.y.w = regs.a.w;
regs.p.n = bool(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
}
} break;
//txa
case 0x8a: {
last_cycle();
op_io();
if(regs.acc_8b) {
regs.a.l = regs.x.l;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.a.w = regs.x.w;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//txy
case 0x9b: {
last_cycle();
op_io();
if(regs.idx_8b) {
regs.y.l = regs.x.l;
regs.p.n = bool(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
} else {
regs.y.w = regs.x.w;
regs.p.n = bool(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
}
} break;
//tya
case 0x98: {
last_cycle();
op_io();
if(regs.acc_8b) {
regs.a.l = regs.y.l;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.a.w = regs.y.w;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//tyx
case 0xbb: {
last_cycle();
op_io();
if(regs.idx_8b) {
regs.x.l = regs.y.l;
regs.p.n = bool(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
} else {
regs.x.w = regs.y.w;
regs.p.n = bool(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
} break;
//tcd
case 0x5b: {
last_cycle();
op_io();
regs.d.w = regs.a.w;
regs.p.n = bool(regs.d.w & 0x8000);
regs.p.z = (regs.d.w == 0);
} break;
//tcs
case 0x1b: {
last_cycle();
op_io();
regs.s.w = regs.a.w;
if(regs.e)regs.s.h = 0x01;
} break;
//tdc
case 0x7b: {
last_cycle();
op_io();
regs.a.w = regs.d.w;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
} break;
//tsc
case 0x3b: {
last_cycle();
op_io();
regs.a.w = regs.s.w;
if(regs.e) {
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//tsx
case 0xba: {
last_cycle();
op_io();
if(regs.idx_8b) {
regs.x.l = regs.s.l;
regs.p.n = bool(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
} else {
regs.x.w = regs.s.w;
regs.p.n = bool(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
} break;
//txs
case 0x9a: {
last_cycle();
op_io();
if(regs.e) {
regs.s.l = regs.x.l;
} else {
regs.s.w = regs.x.w;
}
} break;
//pha
case 0x48: {
op_io();
if(!regs.acc_8b)op_writestack(regs.a.h);
last_cycle();
op_writestack(regs.a.l);
} break;
//phx
case 0xda: {
op_io();
if(!regs.idx_8b)op_writestack(regs.x.h);
last_cycle();
op_writestack(regs.x.l);
} break;
//phy
case 0x5a: {
op_io();
if(!regs.idx_8b)op_writestack(regs.y.h);
last_cycle();
op_writestack(regs.y.l);
} break;
//phd
case 0x0b: {
op_io();
if(!0)op_writestack(regs. d.h);
last_cycle();
op_writestack(regs. d.l);
} break;
//phb
case 0x8b: {
op_io();
last_cycle();
op_writestack(regs.db);
} break;
//phk
case 0x4b: {
op_io();
last_cycle();
op_writestack(regs.pc.b);
} break;
//php
case 0x08: {
op_io();
last_cycle();
op_writestack(regs.p);
} break;
//pla
case 0x68: {
op_io();
op_io();
if(regs.acc_8b)last_cycle();
regs.a.l = op_readstack();
if(regs.acc_8b) {
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
break;
}
last_cycle();
regs.a.h = op_readstack();
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
} break;
//plx
case 0xfa: {
op_io();
op_io();
if(regs.idx_8b)last_cycle();
regs.x.l = op_readstack();
if(regs.idx_8b) {
regs.p.n = bool(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
break;
}
last_cycle();
regs.x.h = op_readstack();
regs.p.n = bool(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
} break;
//ply
case 0x7a: {
op_io();
op_io();
if(regs.idx_8b)last_cycle();
regs.y.l = op_readstack();
if(regs.idx_8b) {
regs.p.n = bool(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
break;
}
last_cycle();
regs.y.h = op_readstack();
regs.p.n = bool(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
} break;
//pld
case 0x2b: {
op_io();
op_io();
if(0)last_cycle();
regs. d.l = op_readstack();
if(0) {
regs.p.n = bool(regs. d.l & 0x80);
regs.p.z = (regs. d.l == 0);
break;
}
last_cycle();
regs. d.h = op_readstack();
regs.p.n = bool(regs. d.w & 0x8000);
regs.p.z = (regs. d.w == 0);
} break;
//plb
case 0xab: {
op_io();
op_io();
last_cycle();
regs.db = op_readstack();
regs.p.n = bool(regs.db & 0x80);
regs.p.z = (regs.db == 0);
} break;
//plp
case 0x28: {
op_io();
op_io();
last_cycle();
regs.p = op_readstack();
regs.acc_8b = (regs.e || regs.p.m);
regs.idx_8b = (regs.e || regs.p.x);
if(regs.idx_8b) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
} break;
//pea
case 0xf4: {
aa.l = op_readpc();
aa.h = op_readpc();
op_writestack(aa.h);
last_cycle();
op_writestack(aa.l);
} break;
//pei
case 0xd4: {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1);
op_writestack(aa.h);
last_cycle();
op_writestack(aa.l);
} break;
//per
case 0x62: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.w = regs.pc.d + (int16)aa.w;
op_writestack(rd.h);
last_cycle();
op_writestack(rd.l);
} break;
+161
View File
@@ -0,0 +1,161 @@
bcc(0x90, !regs.p.c),
bcs(0xb0, regs.p.c),
bne(0xd0, !regs.p.z),
beq(0xf0, regs.p.z),
bpl(0x10, !regs.p.n),
bmi(0x30, regs.p.n),
bvc(0x50, !regs.p.v),
bvs(0x70, regs.p.v) {
1:if(!$1)last_cycle();
rd.l = op_readpc();
if($1) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
end;
}
2:op_io_cond6(aa.w);
3:last_cycle();
op_io();
}
bra(0x80) {
1:rd.l = op_readpc();
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
2:op_io_cond6(aa.w);
3:last_cycle();
op_io();
}
brl(0x82) {
1:rd.l = op_readpc();
2:rd.h = op_readpc();
3:last_cycle();
op_io();
regs.pc.w = regs.pc.d + (int16)rd.w;
}
jmp_addr(0x4c) {
1:rd.l = op_readpc();
2:last_cycle();
rd.h = op_readpc();
regs.pc.w = rd.w;
}
jmp_long(0x5c) {
1:rd.l = op_readpc();
2:rd.h = op_readpc();
3:last_cycle();
rd.b = op_readpc();
regs.pc.d = uclip<24>(rd.d);
}
jmp_iaddr(0x6c) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:rd.l = op_readaddr(aa.w);
4:last_cycle();
rd.h = op_readaddr(aa.w + 1);
regs.pc.w = rd.w;
}
jmp_iaddrx(0x7c) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io();
4:rd.l = op_readpbr(aa.w + regs.x.w);
5:last_cycle();
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
}
jmp_iladdr(0xdc) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:rd.l = op_readaddr(aa.w);
4:rd.h = op_readaddr(aa.w + 1);
5:last_cycle();
rd.b = op_readaddr(aa.w + 2);
regs.pc.d = uclip<24>(rd.d);
}
jsr_addr(0x20) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io();
4:regs.pc.w--;
op_writestack(regs.pc.h);
5:last_cycle();
op_writestack(regs.pc.l);
regs.pc.w = aa.w;
}
jsr_long(0x22) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_writestack(regs.pc.b);
4:op_io();
5:aa.b = op_readpc();
6:regs.pc.w--;
op_writestack(regs.pc.h);
7:last_cycle();
op_writestack(regs.pc.l);
regs.pc.d = uclip<24>(aa.d);
}
jsr_iaddrx(0xfc) {
1:aa.l = op_readpc();
2:op_writestack(regs.pc.h);
3:op_writestack(regs.pc.l);
4:aa.h = op_readpc();
5:op_io();
6:rd.l = op_readpbr(aa.w + regs.x.w);
7:last_cycle();
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
}
rti(0x40) {
1:op_io();
2:op_io();
3:regs.p = op_readstack();
regs.acc_8b = (regs.e || regs.p.m);
regs.idx_8b = (regs.e || regs.p.x);
if(regs.idx_8b) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
4:rd.l = op_readstack();
5:if(regs.e)last_cycle();
rd.h = op_readstack();
if(regs.e) {
regs.pc.w = rd.w;
end;
}
6:last_cycle();
rd.b = op_readstack();
regs.pc.d = uclip<24>(rd.d);
}
rts(0x60) {
1:op_io();
2:op_io();
3:rd.l = op_readstack();
4:rd.h = op_readstack();
5:last_cycle();
op_io();
regs.pc.w = rd.w;
regs.pc.w++;
}
rtl(0x6b) {
1:op_io();
2:op_io();
3:rd.l = op_readstack();
4:rd.h = op_readstack();
5:last_cycle();
rd.b = op_readstack();
regs.pc.d = uclip<24>(rd.d);
regs.pc.w++;
}
+274
View File
@@ -0,0 +1,274 @@
//bcc
case 0x90: {
if(!!regs.p.c)last_cycle();
rd.l = op_readpc();
if(!regs.p.c) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
break;
}
op_io_cond6(aa.w);
last_cycle();
op_io();
} break;
//bcs
case 0xb0: {
if(!regs.p.c)last_cycle();
rd.l = op_readpc();
if(regs.p.c) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
break;
}
op_io_cond6(aa.w);
last_cycle();
op_io();
} break;
//bne
case 0xd0: {
if(!!regs.p.z)last_cycle();
rd.l = op_readpc();
if(!regs.p.z) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
break;
}
op_io_cond6(aa.w);
last_cycle();
op_io();
} break;
//beq
case 0xf0: {
if(!regs.p.z)last_cycle();
rd.l = op_readpc();
if(regs.p.z) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
break;
}
op_io_cond6(aa.w);
last_cycle();
op_io();
} break;
//bpl
case 0x10: {
if(!!regs.p.n)last_cycle();
rd.l = op_readpc();
if(!regs.p.n) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
break;
}
op_io_cond6(aa.w);
last_cycle();
op_io();
} break;
//bmi
case 0x30: {
if(!regs.p.n)last_cycle();
rd.l = op_readpc();
if(regs.p.n) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
break;
}
op_io_cond6(aa.w);
last_cycle();
op_io();
} break;
//bvc
case 0x50: {
if(!!regs.p.v)last_cycle();
rd.l = op_readpc();
if(!regs.p.v) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
break;
}
op_io_cond6(aa.w);
last_cycle();
op_io();
} break;
//bvs
case 0x70: {
if(!regs.p.v)last_cycle();
rd.l = op_readpc();
if(regs.p.v) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
break;
}
op_io_cond6(aa.w);
last_cycle();
op_io();
} break;
//bra
case 0x80: {
rd.l = op_readpc();
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
op_io_cond6(aa.w);
last_cycle();
op_io();
} break;
//brl
case 0x82: {
rd.l = op_readpc();
rd.h = op_readpc();
last_cycle();
op_io();
regs.pc.w = regs.pc.d + (int16)rd.w;
} break;
//jmp_addr
case 0x4c: {
rd.l = op_readpc();
last_cycle();
rd.h = op_readpc();
regs.pc.w = rd.w;
} break;
//jmp_long
case 0x5c: {
rd.l = op_readpc();
rd.h = op_readpc();
last_cycle();
rd.b = op_readpc();
regs.pc.d = uclip<24>(rd.d);
} break;
//jmp_iaddr
case 0x6c: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readaddr(aa.w);
last_cycle();
rd.h = op_readaddr(aa.w + 1);
regs.pc.w = rd.w;
} break;
//jmp_iaddrx
case 0x7c: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readpbr(aa.w + regs.x.w);
last_cycle();
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
} break;
//jmp_iladdr
case 0xdc: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readaddr(aa.w);
rd.h = op_readaddr(aa.w + 1);
last_cycle();
rd.b = op_readaddr(aa.w + 2);
regs.pc.d = uclip<24>(rd.d);
} break;
//jsr_addr
case 0x20: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
regs.pc.w--;
op_writestack(regs.pc.h);
last_cycle();
op_writestack(regs.pc.l);
regs.pc.w = aa.w;
} break;
//jsr_long
case 0x22: {
aa.l = op_readpc();
aa.h = op_readpc();
op_writestack(regs.pc.b);
op_io();
aa.b = op_readpc();
regs.pc.w--;
op_writestack(regs.pc.h);
last_cycle();
op_writestack(regs.pc.l);
regs.pc.d = uclip<24>(aa.d);
} break;
//jsr_iaddrx
case 0xfc: {
aa.l = op_readpc();
op_writestack(regs.pc.h);
op_writestack(regs.pc.l);
aa.h = op_readpc();
op_io();
rd.l = op_readpbr(aa.w + regs.x.w);
last_cycle();
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
} break;
//rti
case 0x40: {
op_io();
op_io();
regs.p = op_readstack();
regs.acc_8b = (regs.e || regs.p.m);
regs.idx_8b = (regs.e || regs.p.x);
if(regs.idx_8b) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
rd.l = op_readstack();
if(regs.e)last_cycle();
rd.h = op_readstack();
if(regs.e) {
regs.pc.w = rd.w;
break;
}
last_cycle();
rd.b = op_readstack();
regs.pc.d = uclip<24>(rd.d);
} break;
//rts
case 0x60: {
op_io();
op_io();
rd.l = op_readstack();
rd.h = op_readstack();
last_cycle();
op_io();
regs.pc.w = rd.w;
regs.pc.w++;
} break;
//rtl
case 0x6b: {
op_io();
op_io();
rd.l = op_readstack();
rd.h = op_readstack();
last_cycle();
rd.b = op_readstack();
regs.pc.d = uclip<24>(rd.d);
regs.pc.w++;
} break;
+317
View File
@@ -0,0 +1,317 @@
adc_const(0x69, adc, regs.acc_8b),
and_const(0x29, and, regs.acc_8b),
cmp_const(0xc9, cmp, regs.acc_8b),
cpx_const(0xe0, cpx, regs.idx_8b),
cpy_const(0xc0, cpy, regs.idx_8b),
eor_const(0x49, eor, regs.acc_8b),
lda_const(0xa9, lda, regs.acc_8b),
ldx_const(0xa2, ldx, regs.idx_8b),
ldy_const(0xa0, ldy, regs.idx_8b),
ora_const(0x09, ora, regs.acc_8b),
sbc_const(0xe9, sbc, regs.acc_8b) {
1:if($2)last_cycle();
rd.l = op_readpc();
if($2) { op_$1_b(); end; }
2:last_cycle();
rd.h = op_readpc();
op_$1_w();
}
adc_addr(0x6d, adc, regs.acc_8b),
and_addr(0x2d, and, regs.acc_8b),
bit_addr(0x2c, bit, regs.acc_8b),
cmp_addr(0xcd, cmp, regs.acc_8b),
cpx_addr(0xec, cpx, regs.idx_8b),
cpy_addr(0xcc, cpy, regs.idx_8b),
eor_addr(0x4d, eor, regs.acc_8b),
lda_addr(0xad, lda, regs.acc_8b),
ldx_addr(0xae, ldx, regs.idx_8b),
ldy_addr(0xac, ldy, regs.idx_8b),
ora_addr(0x0d, ora, regs.acc_8b),
sbc_addr(0xed, sbc, regs.acc_8b) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:if($2)last_cycle();
rd.l = op_readdbr(aa.w);
if($2) { op_$1_b(); end; }
4:last_cycle();
rd.h = op_readdbr(aa.w + 1);
op_$1_w();
}
adc_addrx(0x7d, adc, regs.acc_8b),
and_addrx(0x3d, and, regs.acc_8b),
bit_addrx(0x3c, bit, regs.acc_8b),
cmp_addrx(0xdd, cmp, regs.acc_8b),
eor_addrx(0x5d, eor, regs.acc_8b),
lda_addrx(0xbd, lda, regs.acc_8b),
ldy_addrx(0xbc, ldy, regs.idx_8b),
ora_addrx(0x1d, ora, regs.acc_8b),
sbc_addrx(0xfd, sbc, regs.acc_8b) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io_cond4(aa.w, aa.w + regs.x.w);
4:if($2)last_cycle();
rd.l = op_readdbr(aa.w + regs.x.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_$1_w();
}
adc_addry(0x79, adc, regs.acc_8b),
and_addry(0x39, and, regs.acc_8b),
cmp_addry(0xd9, cmp, regs.acc_8b),
eor_addry(0x59, eor, regs.acc_8b),
lda_addry(0xb9, lda, regs.acc_8b),
ldx_addry(0xbe, ldx, regs.idx_8b),
ora_addry(0x19, ora, regs.acc_8b),
sbc_addry(0xf9, sbc, regs.acc_8b) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io_cond4(aa.w, aa.w + regs.y.w);
4:if($2)last_cycle();
rd.l = op_readdbr(aa.w + regs.y.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_readdbr(aa.w + regs.y.w + 1);
op_$1_w();
}
adc_long(0x6f, adc, regs.acc_8b),
and_long(0x2f, and, regs.acc_8b),
cmp_long(0xcf, cmp, regs.acc_8b),
eor_long(0x4f, eor, regs.acc_8b),
lda_long(0xaf, lda, regs.acc_8b),
ora_long(0x0f, ora, regs.acc_8b),
sbc_long(0xef, sbc, regs.acc_8b) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if($2)last_cycle();
rd.l = op_readlong(aa.d);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_readlong(aa.d + 1);
op_$1_w();
}
adc_longx(0x7f, adc, regs.acc_8b),
and_longx(0x3f, and, regs.acc_8b),
cmp_longx(0xdf, cmp, regs.acc_8b),
eor_longx(0x5f, eor, regs.acc_8b),
lda_longx(0xbf, lda, regs.acc_8b),
ora_longx(0x1f, ora, regs.acc_8b),
sbc_longx(0xff, sbc, regs.acc_8b) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if($2)last_cycle();
rd.l = op_readlong(aa.d + regs.x.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_readlong(aa.d + regs.x.w + 1);
op_$1_w();
}
adc_dp(0x65, adc, regs.acc_8b),
and_dp(0x25, and, regs.acc_8b),
bit_dp(0x24, bit, regs.acc_8b),
cmp_dp(0xc5, cmp, regs.acc_8b),
cpx_dp(0xe4, cpx, regs.idx_8b),
cpy_dp(0xc4, cpy, regs.idx_8b),
eor_dp(0x45, eor, regs.acc_8b),
lda_dp(0xa5, lda, regs.acc_8b),
ldx_dp(0xa6, ldx, regs.idx_8b),
ldy_dp(0xa4, ldy, regs.idx_8b),
ora_dp(0x05, ora, regs.acc_8b),
sbc_dp(0xe5, sbc, regs.acc_8b) {
1:dp = op_readpc();
2:op_io_cond2();
3:if($2)last_cycle();
rd.l = op_readdp(dp);
if($2) { op_$1_b(); end; }
4:last_cycle();
rd.h = op_readdp(dp + 1);
op_$1_w();
}
adc_dpx(0x75, adc, regs.acc_8b),
and_dpx(0x35, and, regs.acc_8b),
bit_dpx(0x34, bit, regs.acc_8b),
cmp_dpx(0xd5, cmp, regs.acc_8b),
eor_dpx(0x55, eor, regs.acc_8b),
lda_dpx(0xb5, lda, regs.acc_8b),
ldy_dpx(0xb4, ldy, regs.idx_8b),
ora_dpx(0x15, ora, regs.acc_8b),
sbc_dpx(0xf5, sbc, regs.acc_8b) {
1:dp = op_readpc();
2:op_io_cond2();
3:op_io();
4:if($2)last_cycle();
rd.l = op_readdp(dp + regs.x.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_readdp(dp + regs.x.w + 1);
op_$1_w();
}
ldx_dpy(0xb6, ldx, regs.idx_8b) {
1:dp = op_readpc();
2:op_io_cond2();
3:op_io();
4:if($2)last_cycle();
rd.l = op_readdp(dp + regs.y.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_readdp(dp + regs.y.w + 1);
op_$1_w();
}
adc_idp(0x72, adc, regs.acc_8b),
and_idp(0x32, and, regs.acc_8b),
cmp_idp(0xd2, cmp, regs.acc_8b),
eor_idp(0x52, eor, regs.acc_8b),
lda_idp(0xb2, lda, regs.acc_8b),
ora_idp(0x12, ora, regs.acc_8b),
sbc_idp(0xf2, sbc, regs.acc_8b) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:if($2)last_cycle();
rd.l = op_readdbr(aa.w);
if($2) { op_$1_b(); end; }
6:last_cycle();
rd.h = op_readdbr(aa.w + 1);
op_$1_w();
}
adc_idpx(0x61, adc, regs.acc_8b),
and_idpx(0x21, and, regs.acc_8b),
cmp_idpx(0xc1, cmp, regs.acc_8b),
eor_idpx(0x41, eor, regs.acc_8b),
lda_idpx(0xa1, lda, regs.acc_8b),
ora_idpx(0x01, ora, regs.acc_8b),
sbc_idpx(0xe1, sbc, regs.acc_8b) {
1:dp = op_readpc();
2:op_io_cond2();
3:op_io();
4:aa.l = op_readdp(dp + regs.x.w);
5:aa.h = op_readdp(dp + regs.x.w + 1);
6:if($2)last_cycle();
rd.l = op_readdbr(aa.w);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_readdbr(aa.w + 1);
op_$1_w();
}
adc_idpy(0x71, adc, regs.acc_8b),
and_idpy(0x31, and, regs.acc_8b),
cmp_idpy(0xd1, cmp, regs.acc_8b),
eor_idpy(0x51, eor, regs.acc_8b),
lda_idpy(0xb1, lda, regs.acc_8b),
ora_idpy(0x11, ora, regs.acc_8b),
sbc_idpy(0xf1, sbc, regs.acc_8b) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:op_io_cond4(aa.w, aa.w + regs.y.w);
6:if($2)last_cycle();
rd.l = op_readdbr(aa.w + regs.y.w);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_readdbr(aa.w + regs.y.w + 1);
op_$1_w();
}
adc_ildp(0x67, adc, regs.acc_8b),
and_ildp(0x27, and, regs.acc_8b),
cmp_ildp(0xc7, cmp, regs.acc_8b),
eor_ildp(0x47, eor, regs.acc_8b),
lda_ildp(0xa7, lda, regs.acc_8b),
ora_ildp(0x07, ora, regs.acc_8b),
sbc_ildp(0xe7, sbc, regs.acc_8b) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if($2)last_cycle();
rd.l = op_readlong(aa.d);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_readlong(aa.d + 1);
op_$1_w();
}
adc_ildpy(0x77, adc, regs.acc_8b),
and_ildpy(0x37, and, regs.acc_8b),
cmp_ildpy(0xd7, cmp, regs.acc_8b),
eor_ildpy(0x57, eor, regs.acc_8b),
lda_ildpy(0xb7, lda, regs.acc_8b),
ora_ildpy(0x17, ora, regs.acc_8b),
sbc_ildpy(0xf7, sbc, regs.acc_8b) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if($2)last_cycle();
rd.l = op_readlong(aa.d + regs.y.w);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_readlong(aa.d + regs.y.w + 1);
op_$1_w();
}
adc_sr(0x63, adc, regs.acc_8b),
and_sr(0x23, and, regs.acc_8b),
cmp_sr(0xc3, cmp, regs.acc_8b),
eor_sr(0x43, eor, regs.acc_8b),
lda_sr(0xa3, lda, regs.acc_8b),
ora_sr(0x03, ora, regs.acc_8b),
sbc_sr(0xe3, sbc, regs.acc_8b) {
1:sp = op_readpc();
2:op_io();
3:if($2)last_cycle();
rd.l = op_readsp(sp);
if($2) { op_$1_b(); end; }
4:last_cycle();
rd.h = op_readsp(sp + 1);
op_$1_w();
}
adc_isry(0x73, adc),
and_isry(0x33, and),
cmp_isry(0xd3, cmp),
eor_isry(0x53, eor),
lda_isry(0xb3, lda),
ora_isry(0x13, ora),
sbc_isry(0xf3, sbc) {
1:sp = op_readpc();
2:op_io();
3:aa.l = op_readsp(sp);
4:aa.h = op_readsp(sp + 1);
5:op_io();
6:if(regs.acc_8b)last_cycle();
rd.l = op_readdbr(aa.w + regs.y.w);
if(regs.acc_8b) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_readdbr(aa.w + regs.y.w + 1);
op_$1_w();
}
bit_const(0x89) {
1:if(regs.acc_8b)last_cycle();
rd.l = op_readpc();
if(regs.acc_8b) {
regs.p.z = ((rd.l & regs.a.l) == 0);
end;
}
2:last_cycle();
rd.h = op_readpc();
regs.p.z = ((rd.w & regs.a.w) == 0);
}
File diff suppressed because it is too large. Load diff
+181
View File
@@ -0,0 +1,181 @@
inc(0x1a, regs.acc_8b, a),
inx(0xe8, regs.idx_8b, x),
iny(0xc8, regs.idx_8b, y) {
1:last_cycle();
op_io();
if($1) {
regs.$2.l++;
regs.p.n = bool(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0);
} else {
regs.$2.w++;
regs.p.n = bool(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0);
}
}
dec(0x3a, regs.acc_8b, a),
dex(0xca, regs.idx_8b, x),
dey(0x88, regs.idx_8b, y) {
1:last_cycle();
op_io();
if($1) {
regs.$2.l--;
regs.p.n = bool(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0);
} else {
regs.$2.w--;
regs.p.n = bool(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0);
}
}
asl(0x0a) {
1:last_cycle();
op_io();
if(regs.acc_8b) {
regs.p.c = bool(regs.a.l & 0x80);
regs.a.l <<= 1;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = bool(regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
lsr(0x4a) {
1:last_cycle();
op_io();
if(regs.acc_8b) {
regs.p.c = regs.a.l & 1;
regs.a.l >>= 1;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = regs.a.w & 1;
regs.a.w >>= 1;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
rol(0x2a) {
1:last_cycle();
op_io();
uint16 c = regs.p.c;
if(regs.acc_8b) {
regs.p.c = bool(regs.a.l & 0x80);
regs.a.l <<= 1;
regs.a.l |= c;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = bool(regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.a.w |= c;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
ror(0x6a) {
1:last_cycle();
op_io();
uint16 c;
if(regs.acc_8b) {
c = (regs.p.c)?0x80:0;
regs.p.c = regs.a.l & 1;
regs.a.l >>= 1;
regs.a.l |= c;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
c = (regs.p.c)?0x8000:0;
regs.p.c = regs.a.w & 1;
regs.a.w >>= 1;
regs.a.w |= c;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
inc_addr(0xee, inc),
dec_addr(0xce, dec),
asl_addr(0x0e, asl),
lsr_addr(0x4e, lsr),
rol_addr(0x2e, rol),
ror_addr(0x6e, ror),
trb_addr(0x1c, trb),
tsb_addr(0x0c, tsb) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:rd.l = op_readdbr(aa.w);
4:if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
5:op_io();
if(regs.acc_8b) { op_$1_b(); }
else { op_$1_w();
6:op_writedbr(aa.w + 1, rd.h); }
7:last_cycle();
op_writedbr(aa.w, rd.l);
}
inc_addrx(0xfe, inc),
dec_addrx(0xde, dec),
asl_addrx(0x1e, asl),
lsr_addrx(0x5e, lsr),
rol_addrx(0x3e, rol),
ror_addrx(0x7e, ror) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io();
4:rd.l = op_readdbr(aa.w + regs.x.w);
5:if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
6:op_io();
if(regs.acc_8b) { op_$1_b(); }
else { op_$1_w();
7:op_writedbr(aa.w + regs.x.w + 1, rd.h); }
8:last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
}
inc_dp(0xe6, inc),
dec_dp(0xc6, dec),
asl_dp(0x06, asl),
lsr_dp(0x46, lsr),
rol_dp(0x26, rol),
ror_dp(0x66, ror),
trb_dp(0x14, trb),
tsb_dp(0x04, tsb) {
1:dp = op_readpc();
2:op_io_cond2();
3:rd.l = op_readdp(dp);
4:if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
5:op_io();
if(regs.acc_8b) { op_$1_b(); }
else { op_$1_w();
6:op_writedp(dp + 1, rd.h); }
7:last_cycle();
op_writedp(dp, rd.l);
}
inc_dpx(0xf6, inc),
dec_dpx(0xd6, dec),
asl_dpx(0x16, asl),
lsr_dpx(0x56, lsr),
rol_dpx(0x36, rol),
ror_dpx(0x76, ror) {
1:dp = op_readpc();
2:op_io_cond2();
3:op_io();
4:rd.l = op_readdp(dp + regs.x.w);
5:if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
6:op_io();
if(regs.acc_8b) { op_$1_b(); }
else { op_$1_w();
7:op_writedp(dp + regs.x.w + 1, rd.h); }
8:last_cycle();
op_writedp(dp + regs.x.w, rd.l);
}
+570
View File
@@ -0,0 +1,570 @@
//inc
case 0x1a: {
last_cycle();
op_io();
if(regs.acc_8b) {
regs.a.l++;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.a.w++;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//inx
case 0xe8: {
last_cycle();
op_io();
if(regs.idx_8b) {
regs.x.l++;
regs.p.n = bool(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
} else {
regs.x.w++;
regs.p.n = bool(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
} break;
//iny
case 0xc8: {
last_cycle();
op_io();
if(regs.idx_8b) {
regs.y.l++;
regs.p.n = bool(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
} else {
regs.y.w++;
regs.p.n = bool(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
}
} break;
//dec
case 0x3a: {
last_cycle();
op_io();
if(regs.acc_8b) {
regs.a.l--;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.a.w--;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//dex
case 0xca: {
last_cycle();
op_io();
if(regs.idx_8b) {
regs.x.l--;
regs.p.n = bool(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
} else {
regs.x.w--;
regs.p.n = bool(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
} break;
//dey
case 0x88: {
last_cycle();
op_io();
if(regs.idx_8b) {
regs.y.l--;
regs.p.n = bool(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
} else {
regs.y.w--;
regs.p.n = bool(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
}
} break;
//asl
case 0x0a: {
last_cycle();
op_io();
if(regs.acc_8b) {
regs.p.c = bool(regs.a.l & 0x80);
regs.a.l <<= 1;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = bool(regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//lsr
case 0x4a: {
last_cycle();
op_io();
if(regs.acc_8b) {
regs.p.c = regs.a.l & 1;
regs.a.l >>= 1;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = regs.a.w & 1;
regs.a.w >>= 1;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//rol
case 0x2a: {
last_cycle();
op_io();
uint16 c = regs.p.c;
if(regs.acc_8b) {
regs.p.c = bool(regs.a.l & 0x80);
regs.a.l <<= 1;
regs.a.l |= c;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = bool(regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.a.w |= c;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//ror
case 0x6a: {
last_cycle();
op_io();
uint16 c;
if(regs.acc_8b) {
c = (regs.p.c)?0x80:0;
regs.p.c = regs.a.l & 1;
regs.a.l >>= 1;
regs.a.l |= c;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
c = (regs.p.c)?0x8000:0;
regs.p.c = regs.a.w & 1;
regs.a.w >>= 1;
regs.a.w |= c;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//inc_addr
case 0xee: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.acc_8b) { op_inc_b(); }
else { op_inc_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//dec_addr
case 0xce: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.acc_8b) { op_dec_b(); }
else { op_dec_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//asl_addr
case 0x0e: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.acc_8b) { op_asl_b(); }
else { op_asl_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//lsr_addr
case 0x4e: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.acc_8b) { op_lsr_b(); }
else { op_lsr_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//rol_addr
case 0x2e: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.acc_8b) { op_rol_b(); }
else { op_rol_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//ror_addr
case 0x6e: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.acc_8b) { op_ror_b(); }
else { op_ror_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//trb_addr
case 0x1c: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.acc_8b) { op_trb_b(); }
else { op_trb_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//tsb_addr
case 0x0c: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.acc_8b) { op_tsb_b(); }
else { op_tsb_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//inc_addrx
case 0xfe: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_inc_b(); }
else { op_inc_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
} break;
//dec_addrx
case 0xde: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_dec_b(); }
else { op_dec_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
} break;
//asl_addrx
case 0x1e: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_asl_b(); }
else { op_asl_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
} break;
//lsr_addrx
case 0x5e: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_lsr_b(); }
else { op_lsr_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
} break;
//rol_addrx
case 0x3e: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_rol_b(); }
else { op_rol_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
} break;
//ror_addrx
case 0x7e: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_ror_b(); }
else { op_ror_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
} break;
//inc_dp
case 0xe6: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
op_io();
if(regs.acc_8b) { op_inc_b(); }
else { op_inc_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//dec_dp
case 0xc6: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
op_io();
if(regs.acc_8b) { op_dec_b(); }
else { op_dec_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//asl_dp
case 0x06: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
op_io();
if(regs.acc_8b) { op_asl_b(); }
else { op_asl_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//lsr_dp
case 0x46: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
op_io();
if(regs.acc_8b) { op_lsr_b(); }
else { op_lsr_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//rol_dp
case 0x26: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
op_io();
if(regs.acc_8b) { op_rol_b(); }
else { op_rol_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//ror_dp
case 0x66: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
op_io();
if(regs.acc_8b) { op_ror_b(); }
else { op_ror_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//trb_dp
case 0x14: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
op_io();
if(regs.acc_8b) { op_trb_b(); }
else { op_trb_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//tsb_dp
case 0x04: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
op_io();
if(regs.acc_8b) { op_tsb_b(); }
else { op_tsb_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//inc_dpx
case 0xf6: {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_inc_b(); }
else { op_inc_w();
op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle();
op_writedp(dp + regs.x.w, rd.l);
} break;
//dec_dpx
case 0xd6: {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_dec_b(); }
else { op_dec_w();
op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle();
op_writedp(dp + regs.x.w, rd.l);
} break;
//asl_dpx
case 0x16: {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_asl_b(); }
else { op_asl_w();
op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle();
op_writedp(dp + regs.x.w, rd.l);
} break;
//lsr_dpx
case 0x56: {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_lsr_b(); }
else { op_lsr_w();
op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle();
op_writedp(dp + regs.x.w, rd.l);
} break;
//rol_dpx
case 0x36: {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_rol_b(); }
else { op_rol_w();
op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle();
op_writedp(dp + regs.x.w, rd.l);
} break;
//ror_dpx
case 0x76: {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_ror_b(); }
else { op_ror_w();
op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle();
op_writedp(dp + regs.x.w, rd.l);
} break;
+181
View File
@@ -0,0 +1,181 @@
sta_addr(0x8d, regs.acc_8b, regs.a.w),
stx_addr(0x8e, regs.idx_8b, regs.x.w),
sty_addr(0x8c, regs.idx_8b, regs.y.w),
stz_addr(0x9c, regs.acc_8b, 0x0000) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:if($1)last_cycle();
op_writedbr(aa.w, $2);
if($1)end;
4:last_cycle();
op_writedbr(aa.w + 1, $2 >> 8);
}
sta_addrx(0x9d, regs.acc_8b, regs.a.w),
stz_addrx(0x9e, regs.acc_8b, 0x0000) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io();
4:if($1)last_cycle();
op_writedbr(aa.w + regs.x.w, $2);
if($1)end;
5:last_cycle();
op_writedbr(aa.w + regs.x.w + 1, $2 >> 8);
}
sta_addry(0x99) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io();
4:if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)end;
5:last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}
sta_long(0x8f) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if(regs.acc_8b)last_cycle();
op_writelong(aa.d, regs.a.l);
if(regs.acc_8b)end;
5:last_cycle();
op_writelong(aa.d + 1, regs.a.h);
}
sta_longx(0x9f) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if(regs.acc_8b)last_cycle();
op_writelong(aa.d + regs.x.w, regs.a.l);
if(regs.acc_8b)end;
5:last_cycle();
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
}
sta_dp(0x85, regs.acc_8b, regs.a.w),
stx_dp(0x86, regs.idx_8b, regs.x.w),
sty_dp(0x84, regs.idx_8b, regs.y.w),
stz_dp(0x64, regs.acc_8b, 0x0000) {
1:dp = op_readpc();
2:op_io_cond2();
3:if($1)last_cycle();
op_writedp(dp, $2);
if($1)end;
4:last_cycle();
op_writedp(dp + 1, $2 >> 8);
}
sta_dpx(0x95, regs.acc_8b, regs.a.w),
sty_dpx(0x94, regs.idx_8b, regs.y.w),
stz_dpx(0x74, regs.acc_8b, 0x0000) {
1:dp = op_readpc();
2:op_io_cond2();
3:op_io();
4:if($1)last_cycle();
op_writedp(dp + regs.x.w, $2);
if($1)end;
5:last_cycle();
op_writedp(dp + regs.x.w + 1, $2 >> 8);
}
stx_dpy(0x96) {
1:dp = op_readpc();
2:op_io_cond2();
3:op_io();
4:if(regs.idx_8b)last_cycle();
op_writedp(dp + regs.y.w, regs.x.l);
if(regs.idx_8b)end;
5:last_cycle();
op_writedp(dp + regs.y.w + 1, regs.x.h);
}
sta_idp(0x92) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:if(regs.acc_8b)last_cycle();
op_writedbr(aa.w, regs.a.l);
if(regs.acc_8b)end;
6:last_cycle();
op_writedbr(aa.w + 1, regs.a.h);
}
sta_ildp(0x87) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if(regs.acc_8b)last_cycle();
op_writelong(aa.d, regs.a.l);
if(regs.acc_8b)end;
7:last_cycle();
op_writelong(aa.d + 1, regs.a.h);
}
sta_idpx(0x81) {
1:dp = op_readpc();
2:op_io_cond2();
3:op_io();
4:aa.l = op_readdp(dp + regs.x.w);
5:aa.h = op_readdp(dp + regs.x.w + 1);
6:if(regs.acc_8b)last_cycle();
op_writedbr(aa.w, regs.a.l);
if(regs.acc_8b)end;
7:last_cycle();
op_writedbr(aa.w + 1, regs.a.h);
}
sta_idpy(0x91) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:op_io();
6:if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)end;
7:last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}
sta_ildpy(0x97) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if(regs.acc_8b)last_cycle();
op_writelong(aa.d + regs.y.w, regs.a.l);
if(regs.acc_8b)end;
7:last_cycle();
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
}
sta_sr(0x83) {
1:sp = op_readpc();
2:op_io();
3:if(regs.acc_8b)last_cycle();
op_writesp(sp, regs.a.l);
if(regs.acc_8b)end;
4:last_cycle();
op_writesp(sp + 1, regs.a.h);
}
sta_isry(0x93) {
1:sp = op_readpc();
2:op_io();
3:aa.l = op_readsp(sp);
4:aa.h = op_readsp(sp + 1);
5:op_io();
6:if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)end;
7:last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}
+290
View File
@@ -0,0 +1,290 @@
//sta_addr
case 0x8d: {
aa.l = op_readpc();
aa.h = op_readpc();
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w, regs.a.w);
if(regs.acc_8b)break;
last_cycle();
op_writedbr(aa.w + 1, regs.a.w >> 8);
} break;
//stx_addr
case 0x8e: {
aa.l = op_readpc();
aa.h = op_readpc();
if(regs.idx_8b)last_cycle();
op_writedbr(aa.w, regs.x.w);
if(regs.idx_8b)break;
last_cycle();
op_writedbr(aa.w + 1, regs.x.w >> 8);
} break;
//sty_addr
case 0x8c: {
aa.l = op_readpc();
aa.h = op_readpc();
if(regs.idx_8b)last_cycle();
op_writedbr(aa.w, regs.y.w);
if(regs.idx_8b)break;
last_cycle();
op_writedbr(aa.w + 1, regs.y.w >> 8);
} break;
//stz_addr
case 0x9c: {
aa.l = op_readpc();
aa.h = op_readpc();
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w, 0x0000);
if(regs.acc_8b)break;
last_cycle();
op_writedbr(aa.w + 1, 0x0000 >> 8);
} break;
//sta_addrx
case 0x9d: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.x.w, regs.a.w);
if(regs.acc_8b)break;
last_cycle();
op_writedbr(aa.w + regs.x.w + 1, regs.a.w >> 8);
} break;
//stz_addrx
case 0x9e: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.x.w, 0x0000);
if(regs.acc_8b)break;
last_cycle();
op_writedbr(aa.w + regs.x.w + 1, 0x0000 >> 8);
} break;
//sta_addry
case 0x99: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
} break;
//sta_long
case 0x8f: {
aa.l = op_readpc();
aa.h = op_readpc();
aa.b = op_readpc();
if(regs.acc_8b)last_cycle();
op_writelong(aa.d, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writelong(aa.d + 1, regs.a.h);
} break;
//sta_longx
case 0x9f: {
aa.l = op_readpc();
aa.h = op_readpc();
aa.b = op_readpc();
if(regs.acc_8b)last_cycle();
op_writelong(aa.d + regs.x.w, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
} break;
//sta_dp
case 0x85: {
dp = op_readpc();
op_io_cond2();
if(regs.acc_8b)last_cycle();
op_writedp(dp, regs.a.w);
if(regs.acc_8b)break;
last_cycle();
op_writedp(dp + 1, regs.a.w >> 8);
} break;
//stx_dp
case 0x86: {
dp = op_readpc();
op_io_cond2();
if(regs.idx_8b)last_cycle();
op_writedp(dp, regs.x.w);
if(regs.idx_8b)break;
last_cycle();
op_writedp(dp + 1, regs.x.w >> 8);
} break;
//sty_dp
case 0x84: {
dp = op_readpc();
op_io_cond2();
if(regs.idx_8b)last_cycle();
op_writedp(dp, regs.y.w);
if(regs.idx_8b)break;
last_cycle();
op_writedp(dp + 1, regs.y.w >> 8);
} break;
//stz_dp
case 0x64: {
dp = op_readpc();
op_io_cond2();
if(regs.acc_8b)last_cycle();
op_writedp(dp, 0x0000);
if(regs.acc_8b)break;
last_cycle();
op_writedp(dp + 1, 0x0000 >> 8);
} break;
//sta_dpx
case 0x95: {
dp = op_readpc();
op_io_cond2();
op_io();
if(regs.acc_8b)last_cycle();
op_writedp(dp + regs.x.w, regs.a.w);
if(regs.acc_8b)break;
last_cycle();
op_writedp(dp + regs.x.w + 1, regs.a.w >> 8);
} break;
//sty_dpx
case 0x94: {
dp = op_readpc();
op_io_cond2();
op_io();
if(regs.idx_8b)last_cycle();
op_writedp(dp + regs.x.w, regs.y.w);
if(regs.idx_8b)break;
last_cycle();
op_writedp(dp + regs.x.w + 1, regs.y.w >> 8);
} break;
//stz_dpx
case 0x74: {
dp = op_readpc();
op_io_cond2();
op_io();
if(regs.acc_8b)last_cycle();
op_writedp(dp + regs.x.w, 0x0000);
if(regs.acc_8b)break;
last_cycle();
op_writedp(dp + regs.x.w + 1, 0x0000 >> 8);
} break;
//stx_dpy
case 0x96: {
dp = op_readpc();
op_io_cond2();
op_io();
if(regs.idx_8b)last_cycle();
op_writedp(dp + regs.y.w, regs.x.l);
if(regs.idx_8b)break;
last_cycle();
op_writedp(dp + regs.y.w + 1, regs.x.h);
} break;
//sta_idp
case 0x92: {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1);
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writedbr(aa.w + 1, regs.a.h);
} break;
//sta_ildp
case 0x87: {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
if(regs.acc_8b)last_cycle();
op_writelong(aa.d, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writelong(aa.d + 1, regs.a.h);
} break;
//sta_idpx
case 0x81: {
dp = op_readpc();
op_io_cond2();
op_io();
aa.l = op_readdp(dp + regs.x.w);
aa.h = op_readdp(dp + regs.x.w + 1);
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writedbr(aa.w + 1, regs.a.h);
} break;
//sta_idpy
case 0x91: {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1);
op_io();
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
} break;
//sta_ildpy
case 0x97: {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
if(regs.acc_8b)last_cycle();
op_writelong(aa.d + regs.y.w, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
} break;
//sta_sr
case 0x83: {
sp = op_readpc();
op_io();
if(regs.acc_8b)last_cycle();
op_writesp(sp, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writesp(sp + 1, regs.a.h);
} break;
//sta_isry
case 0x93: {
sp = op_readpc();
op_io();
aa.l = op_readsp(sp);
aa.h = op_readsp(sp + 1);
op_io();
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
} break;
+377
View File
@@ -0,0 +1,377 @@
//op_read
inline void sCPU::op_adc_b() {
int32 r = regs.a.l + rd.l + regs.p.c;
if(regs.p.d) {
uint8 n0 = (regs.a.l ) & 15;
uint8 n1 = (regs.a.l >> 4) & 15;
n0 += ((rd.l) & 15) + regs.p.c;
if(n0 > 9) {
n0 -= 10;
n0 &= 15;
n1++;
}
n1 += ((rd.l >> 4) & 15);
if(n1 > 9) {
n1 -= 10;
n1 &= 15;
regs.p.c = 1;
} else {
regs.p.c = 0;
}
r = (n1 << 4) | (n0);
} else {
r = regs.a.l + rd.l + regs.p.c;
regs.p.c = (r > 0xff);
}
regs.p.n = bool(r & 0x80);
regs.p.v = bool(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
regs.p.z = ((uint8)r == 0);
regs.a.l = r;
}
inline void sCPU::op_adc_w() {
int32 r;
if(regs.p.d) {
uint8 n0 = (regs.a.w ) & 15;
uint8 n1 = (regs.a.w >> 4) & 15;
uint8 n2 = (regs.a.w >> 8) & 15;
uint8 n3 = (regs.a.w >> 12) & 15;
n0 += ((rd.w) & 15) + regs.p.c;
if(n0 > 9) {
n0 -= 10;
n0 &= 15;
n1++;
}
n1 += ((rd.w >> 4) & 15);
if(n1 > 9) {
n1 -= 10;
n1 &= 15;
n2++;
}
n2 += ((rd.w >> 8) & 15);
if(n2 > 9) {
n2 -= 10;
n2 &= 15;
n3++;
}
n3 += ((rd.w >> 12) & 15);
if(n3 > 9) {
n3 -= 10;
n3 &= 15;
regs.p.c = 1;
} else {
regs.p.c = 0;
}
r = (n3 << 12) | (n2 << 8) | (n1 << 4) | (n0);
} else {
r = regs.a.w + rd.w + regs.p.c;
regs.p.c = (r > 0xffff);
}
regs.p.n = bool(r & 0x8000);
regs.p.v = bool(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.a.w = r;
}
inline void sCPU::op_and_b() {
regs.a.l &= rd.l;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
inline void sCPU::op_and_w() {
regs.a.w &= rd.w;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
inline void sCPU::op_bit_b() {
regs.p.n = bool(rd.l & 0x80);
regs.p.v = bool(rd.l & 0x40);
regs.p.z = ((rd.l & regs.a.l) == 0);
}
inline void sCPU::op_bit_w() {
regs.p.n = bool(rd.w & 0x8000);
regs.p.v = bool(rd.w & 0x4000);
regs.p.z = ((rd.w & regs.a.w) == 0);
}
inline void sCPU::op_cmp_b() {
int32 r = regs.a.l - rd.l;
regs.p.n = bool(r & 0x80);
regs.p.z = ((uint8)r == 0);
regs.p.c = (r >= 0);
}
inline void sCPU::op_cmp_w() {
int32 r = regs.a.w - rd.w;
regs.p.n = bool(r & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.p.c = (r >= 0);
}
inline void sCPU::op_cpx_b() {
int32 r = regs.x.l - rd.l;
regs.p.n = bool(r & 0x80);
regs.p.z = ((uint8)r == 0);
regs.p.c = (r >= 0);
}
inline void sCPU::op_cpx_w() {
int32 r = regs.x.w - rd.w;
regs.p.n = bool(r & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.p.c = (r >= 0);
}
inline void sCPU::op_cpy_b() {
int32 r = regs.y.l - rd.l;
regs.p.n = bool(r & 0x80);
regs.p.z = ((uint8)r == 0);
regs.p.c = (r >= 0);
}
inline void sCPU::op_cpy_w() {
int32 r = regs.y.w - rd.w;
regs.p.n = bool(r & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.p.c = (r >= 0);
}
inline void sCPU::op_eor_b() {
regs.a.l ^= rd.l;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
inline void sCPU::op_eor_w() {
regs.a.w ^= rd.w;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
inline void sCPU::op_lda_b() {
regs.a.l = rd.l;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
inline void sCPU::op_lda_w() {
regs.a.w = rd.w;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
inline void sCPU::op_ldx_b() {
regs.x.l = rd.l;
regs.p.n = bool(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
}
inline void sCPU::op_ldx_w() {
regs.x.w = rd.w;
regs.p.n = bool(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
inline void sCPU::op_ldy_b() {
regs.y.l = rd.l;
regs.p.n = bool(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
}
inline void sCPU::op_ldy_w() {
regs.y.w = rd.w;
regs.p.n = bool(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
}
inline void sCPU::op_ora_b() {
regs.a.l |= rd.l;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
inline void sCPU::op_ora_w() {
regs.a.w |= rd.w;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
inline void sCPU::op_sbc_b() {
int32 r;
if(regs.p.d) {
uint8 n0 = (regs.a.l ) & 15;
uint8 n1 = (regs.a.l >> 4) & 15;
n0 -= ((rd.l ) & 15) + !regs.p.c;
n1 -= ((rd.l >> 4) & 15);
if(n0 > 9) {
n0 += 10;
n1--;
}
if(n1 > 9) {
n1 += 10;
regs.p.c = 0;
} else {
regs.p.c = 1;
}
r = (n1 << 4) | (n0);
} else {
r = regs.a.l - rd.l - !regs.p.c;
regs.p.c = (r >= 0);
}
regs.p.n = bool(r & 0x80);
regs.p.v = bool((regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
regs.p.z = ((uint8)r == 0);
regs.a.l = r;
}
inline void sCPU::op_sbc_w() {
int32 r;
if(regs.p.d) {
uint8 n0 = (regs.a.w ) & 15;
uint8 n1 = (regs.a.w >> 4) & 15;
uint8 n2 = (regs.a.w >> 8) & 15;
uint8 n3 = (regs.a.w >> 12) & 15;
n0 -= ((rd.w ) & 15) + !regs.p.c;
n1 -= ((rd.w >> 4) & 15);
n2 -= ((rd.w >> 8) & 15);
n3 -= ((rd.w >> 12) & 15);
if(n0 > 9) {
n0 += 10;
n1--;
}
if(n1 > 9) {
n1 += 10;
n2--;
}
if(n2 > 9) {
n2 += 10;
n3--;
}
if(n3 > 9) {
n3 += 10;
regs.p.c = 0;
} else {
regs.p.c = 1;
}
r = (n3 << 12) | (n2 << 8) | (n1 << 4) | (n0);
} else {
r = regs.a.w - rd.w - !regs.p.c;
regs.p.c = (r >= 0);
}
regs.p.n = bool(r & 0x8000);
regs.p.v = bool((regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.a.w = r;
}
//op_rmw
inline void sCPU::op_inc_b() {
rd.l++;
regs.p.n = bool(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void sCPU::op_inc_w() {
rd.w++;
regs.p.n = bool(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void sCPU::op_dec_b() {
rd.l--;
regs.p.n = bool(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void sCPU::op_dec_w() {
rd.w--;
regs.p.n = bool(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void sCPU::op_asl_b() {
regs.p.c = bool(rd.l & 0x80);
rd.l <<= 1;
regs.p.n = bool(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void sCPU::op_asl_w() {
regs.p.c = bool(rd.w & 0x8000);
rd.w <<= 1;
regs.p.n = bool(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void sCPU::op_lsr_b() {
regs.p.c = rd.l & 1;
rd.l >>= 1;
regs.p.n = bool(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void sCPU::op_lsr_w() {
regs.p.c = rd.w & 1;
rd.w >>= 1;
regs.p.n = bool(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void sCPU::op_rol_b() {
uint16 c = regs.p.c;
regs.p.c = bool(rd.l & 0x80);
rd.l <<= 1;
rd.l |= c;
regs.p.n = bool(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void sCPU::op_rol_w() {
uint16 c = regs.p.c;
regs.p.c = bool(rd.w & 0x8000);
rd.w <<= 1;
rd.w |= c;
regs.p.n = bool(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void sCPU::op_ror_b() {
uint16 c = (regs.p.c)?0x80:0;
regs.p.c = rd.l & 1;
rd.l >>= 1;
rd.l |= c;
regs.p.n = bool(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void sCPU::op_ror_w() {
uint16 c = (regs.p.c)?0x8000:0;
regs.p.c = rd.w & 1;
rd.w >>= 1;
rd.w |= c;
regs.p.n = bool(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void sCPU::op_trb_b() {
regs.p.z = ((rd.l & regs.a.l) == 0);
rd.l &= ~regs.a.l;
}
inline void sCPU::op_trb_w() {
regs.p.z = ((rd.w & regs.a.w) == 0);
rd.w &= ~regs.a.w;
}
inline void sCPU::op_tsb_b() {
regs.p.z = ((rd.l & regs.a.l) == 0);
rd.l |= regs.a.l;
}
inline void sCPU::op_tsb_w() {
regs.p.z = ((rd.w & regs.a.w) == 0);
rd.w |= regs.a.w;
}
+18
View File
@@ -0,0 +1,18 @@
#define CLASS_NAME "sCPU"
#include "../../../lib/opgen_s.cpp"
int main() {
//fph = fopen("op.h", "wb");
//fpt = fopen("optable.cpp", "wb");
generate("op_read.cpp", "op_read.b");
generate("op_write.cpp", "op_write.b");
generate("op_rmw.cpp", "op_rmw.b");
generate("op_pc.cpp", "op_pc.b");
generate("op_misc.cpp", "op_misc.b");
//fclose(fph);
//fclose(fpt);
return 0;
}
+273
View File
@@ -0,0 +1,273 @@
/*****
* used by both DMA and HDMA
*
* DMA address bus A cannot read from or write to the following addresses :
* $[00-3f|80-bf]:43[00-7f] <DMA control registers>
* $[00-3f|80-bf]:420b <DMA enable register>
* $[00-3f|80-bf]:420c <HDMA enable register>
* WRAM<>WRAM transfers via $2180
*****/
void sCPU::dma_transfer(bool direction, uint8 bbus, uint32 abus) {
uint8 r;
if(direction == 0) { //a->b
if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300 ||
(abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c) {
r = regs.mdr;
} else {
r = r_mem->read(abus);
}
r_mem->write(0x2100 | bbus, r);
} else { //b->a
if(bbus == 0x80 && ((abus & 0x7e0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) {
//prevent WRAM->WRAM transfers
r = regs.mdr;
} else {
r = r_mem->read(0x2100 | bbus);
}
if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300 ||
(abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c)return;
r_mem->write(abus, r);
}
status.dma_clocks += 8;
add_clocks(8);
co_return();
cycle_edge();
}
/*****
* address calculation functions
*****/
uint8 sCPU::dma_bbus(uint8 i, uint8 index) {
switch(channel[i].xfermode) {
default:
case 0: return (channel[i].destaddr); break; //0
case 1: return (channel[i].destaddr + (index & 1)); break; //0,1
case 2: return (channel[i].destaddr); break; //0,0
case 3: return (channel[i].destaddr + ((index >> 1) & 1)); break; //0,0,1,1
case 4: return (channel[i].destaddr + (index & 3)); break; //0,1,2,3
case 5: return (channel[i].destaddr + (index & 1)); break; //0,1,0,1
case 6: return (channel[i].destaddr); break; //0,0 [2]
case 7: return (channel[i].destaddr + ((index >> 1) & 1)); break; //0,0,1,1 [3]
}
}
inline uint32 sCPU::dma_addr(uint8 i) {
uint32 r = (channel[i].srcbank << 16) | (channel[i].srcaddr);
if(channel[i].fixedxfer == false) {
if(channel[i].reversexfer == false) {
channel[i].srcaddr++;
} else {
channel[i].srcaddr--;
}
}
return r;
}
inline uint32 sCPU::hdma_addr(uint8 i) {
return (channel[i].srcbank << 16) | (channel[i].hdma_addr++);
}
inline uint32 sCPU::hdma_iaddr(uint8 i) {
return (channel[i].hdma_ibank << 16) | (channel[i].hdma_iaddr++);
}
/*****
* DMA functions
*****/
void sCPU::dma_transfertobusb(uint8 i, uint8 bbus) {
if(cartridge.info.sdd1 == true && sdd1->dma_active() == true) {
r_mem->write(0x2100 | bbus, sdd1->dma_read());
} else {
dma_transfer(0, bbus, dma_addr(i));
}
channel[i].xfersize--;
}
void sCPU::dma_transfertobusa(uint8 i, uint8 bbus) {
dma_transfer(1, bbus, dma_addr(i));
channel[i].xfersize--;
}
inline void sCPU::dma_write(uint8 i, uint8 index) {
//cannot use dma_transfer() directly, due to current S-DD1 implementation
if(channel[i].direction == 0) {
dma_transfertobusb(i, index);
} else {
dma_transfertobusa(i, index);
}
}
void sCPU::dma_run() {
for(int i = 0; i < 8; i++) {
if(channel[i].dma_enabled == false)continue;
status.dma_clocks += 8;
add_clocks(8);
if(cartridge.info.sdd1 == true) {
sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr),
channel[i].xfersize);
}
if(tracer.enabled() == true && tracer.cpudma_enabled() == true) {
tprintf("[DMA] channel:%d direction:%s reverse:%c fixed:%c mode:%d b_addr:$21%0.2x "
"a_addr:$%0.2x%0.4x length:$%0.4x (%5d)",
i, channel[i].direction ? "b->a" : "a->b", channel[i].reversexfer ? '1' : '0',
channel[i].fixedxfer ? '1' : '0', channel[i].xfermode, channel[i].destaddr,
channel[i].srcbank, channel[i].srcaddr,
channel[i].xfersize, channel[i].xfersize ? channel[i].xfersize : 65536);
}
uint index = 0;
do {
dma_write(i, dma_bbus(i, index++));
} while(channel[i].dma_enabled && channel[i].xfersize);
channel[i].dma_enabled = false;
}
counter_set(counter.irq_delay, 24);
}
/*****
* HDMA functions
*****/
inline bool sCPU::hdma_active(uint8 i) {
return (channel[i].hdma_enabled && !channel[i].hdma_completed);
}
inline bool sCPU::hdma_active_after(uint8 i) {
for(int n = i + 1; n < 8; n++) {
if(hdma_active(n) == true) { return true; }
}
return false;
}
inline uint8 sCPU::hdma_enabled_channels() {
uint8 r = 0;
for(int i = 0; i < 8; i++) {
if(channel[i].hdma_enabled)r++;
}
return r;
}
inline uint8 sCPU::hdma_active_channels() {
uint8 r = 0;
for(int i = 0; i < 8; i++) {
if(hdma_active(i) == true)r++;
}
return r;
}
void sCPU::hdma_update(uint8 i) {
channel[i].hdma_line_counter = r_mem->read(hdma_addr(i));
add_clocks(8);
channel[i].hdma_completed = (channel[i].hdma_line_counter == 0);
channel[i].hdma_do_transfer = !channel[i].hdma_completed;
if(channel[i].hdma_indirect) {
channel[i].hdma_iaddr = r_mem->read(hdma_addr(i)) << 8;
add_clocks(8);
if(!channel[i].hdma_completed || hdma_active_after(i)) {
channel[i].hdma_iaddr >>= 8;
channel[i].hdma_iaddr |= r_mem->read(hdma_addr(i)) << 8;
add_clocks(8);
}
}
}
void sCPU::hdma_run() {
static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
for(int i = 0; i < 8; i++) {
if(hdma_active(i) == false)continue;
channel[i].dma_enabled = false; //HDMA run during DMA will stop DMA mid-transfer
add_clocks(8);
if(channel[i].hdma_do_transfer) {
int xferlen = hdma_xferlen[channel[i].xfermode];
for(int index = 0; index < xferlen; index++) {
if(bool(config::cpu.hdma_enable) == true) {
dma_transfer(channel[i].direction, dma_bbus(i, index),
!channel[i].hdma_indirect ? hdma_addr(i) : hdma_iaddr(i));
} else {
add_clocks(8);
co_return();
cycle_edge();
}
}
}
channel[i].hdma_line_counter--;
channel[i].hdma_do_transfer = bool(channel[i].hdma_line_counter & 0x80);
if((channel[i].hdma_line_counter & 0x7f) == 0) {
hdma_update(i);
}
}
counter_set(counter.irq_delay, 24);
}
void sCPU::hdma_init_reset() {
for(int i = 0; i < 8; i++) {
channel[i].hdma_completed = false;
channel[i].hdma_do_transfer = false;
}
}
void sCPU::hdma_init() {
for(int i = 0; i < 8; i++) {
if(!channel[i].hdma_enabled)continue;
channel[i].dma_enabled = false; //HDMA init during DMA will stop DMA mid-transfer
channel[i].hdma_addr = channel[i].srcaddr;
hdma_update(i);
}
counter_set(counter.irq_delay, 24);
}
/*****
* power / reset functions
*****/
void sCPU::dma_power() {
for(int i = 0; i < 8; i++) {
channel[i].dmap = 0xff;
channel[i].direction = 1;
channel[i].hdma_indirect = true;
channel[i].reversexfer = true;
channel[i].fixedxfer = true;
channel[i].xfermode = 7;
channel[i].destaddr = 0xff;
channel[i].srcaddr = 0xffff;
channel[i].srcbank = 0xff;
channel[i].xfersize = 0xffff;
//channel[i].hdma_iaddr = 0xffff; //union with xfersize
channel[i].hdma_ibank = 0xff;
channel[i].hdma_addr = 0xffff;
channel[i].hdma_line_counter = 0xff;
channel[i].unknown = 0xff;
}
}
void sCPU::dma_reset() {
for(int i = 0; i < 8; i++) {
channel[i].dma_enabled = false;
channel[i].hdma_enabled = false;
channel[i].hdma_completed = false;
channel[i].hdma_do_transfer = false;
}
}
+70
View File
@@ -0,0 +1,70 @@
struct {
//$420b
bool dma_enabled;
//$420c
bool hdma_enabled;
//$43x0
uint8 dmap;
bool direction;
bool hdma_indirect;
bool reversexfer;
bool fixedxfer;
uint8 xfermode;
//$43x1
uint8 destaddr;
//$43x2-$43x3
uint16 srcaddr;
//$43x4
uint8 srcbank;
//$43x5-$43x6
union {
uint16 xfersize;
uint16 hdma_iaddr;
};
//$43x7
uint8 hdma_ibank;
//$43x8-$43x9
uint16 hdma_addr;
//$43xa
uint8 hdma_line_counter;
//$43xb/$43xf
uint8 unknown;
//internal variables
bool hdma_completed;
bool hdma_do_transfer;
} channel[8];
void dma_transfer(bool direction, uint8 bbus, uint32 abus);
uint8 dma_bbus(uint8 i, uint8 index);
uint32 dma_addr(uint8 i);
uint32 hdma_addr(uint8 i);
uint32 hdma_iaddr(uint8 i);
void dma_transfertobusb(uint8 i, uint8 bbus);
void dma_transfertobusa(uint8 i, uint8 bbus);
void dma_write(uint8 i, uint8 index);
void dma_run();
bool hdma_active(uint8 i);
bool hdma_active_after(uint8 i);
uint8 hdma_enabled_channels();
uint8 hdma_active_channels();
void hdma_update(uint8 i);
void hdma_run();
void hdma_init_reset();
void hdma_init();
void dma_power();
void dma_reset();
+40
View File
@@ -0,0 +1,40 @@
/*****
* These 3 functions control bus timing for the CPU.
* cpu_io is an I/O cycle, and always 6 clock cycles long.
* mem_read / mem_write indicate memory access bus cycles.
* they are either 6, 8, or 12 bus cycles long, depending
* both on location and the $420d.d0 FastROM enable bit.
*****/
void sCPU::op_io() {
status.clock_count = 6;
precycle_edge();
add_clocks(6);
//co_return();
cycle_edge();
}
uint8 sCPU::op_read(uint32 addr) {
status.clock_count = r_mem->speed(addr);
precycle_edge();
add_clocks(status.clock_count - 4);
#ifdef FAVOR_ACCURACY
co_return();
#endif
regs.mdr = r_mem->read(addr);
add_clocks(4);
cycle_edge();
return regs.mdr;
}
void sCPU::op_write(uint32 addr, uint8 data) {
status.clock_count = r_mem->speed(addr);
precycle_edge();
add_clocks(status.clock_count);
#ifdef FAVOR_ACCURACY
co_return();
#endif
regs.mdr = data;
r_mem->write(addr, regs.mdr);
cycle_edge();
}
+33
View File
@@ -0,0 +1,33 @@
/*****
* CPU<>APU communication ports
*****/
uint8 apu_port[4];
uint8 port_read (uint8 port) { return apu_port[port & 3]; }
void port_write(uint8 port, uint8 data) { apu_port[port & 3] = data; }
/*****
* core CPU bus functions
*****/
void op_io();
uint8 op_read (uint32 addr);
void op_write(uint32 addr, uint8 data);
/*****
* helper memory addressing functions used by CPU core
*****/
uint8 op_readpc () { return op_read((regs.pc.b << 16) + regs.pc.w++); }
uint8 op_readstack() { (regs.e) ? regs.s.l++ : regs.s.w++; return op_read(regs.s.w); }
uint8 op_readaddr (uint32 addr) { return op_read(addr & 0xffff); }
uint8 op_readlong (uint32 addr) { return op_read(addr & 0xffffff); }
uint8 op_readdbr (uint32 addr) { return op_read(((regs.db << 16) + addr) & 0xffffff); }
uint8 op_readpbr (uint32 addr) { return op_read((regs.pc.b << 16) + (addr & 0xffff)); }
uint8 op_readdp (uint32 addr) { return op_read((regs.d + (addr & 0xffff)) & 0xffff); }
uint8 op_readsp (uint32 addr) { return op_read((regs.s + (addr & 0xffff)) & 0xffff); }
void op_writestack(uint8 data) { op_write(regs.s.w, data); (regs.e) ? regs.s.l-- : regs.s.w--; }
void op_writeaddr (uint32 addr, uint8 data) { op_write(addr & 0xffff, data); }
void op_writelong (uint32 addr, uint8 data) { op_write(addr & 0xffffff, data); }
void op_writedbr (uint32 addr, uint8 data) { op_write(((regs.db << 16) + addr) & 0xffffff, data); }
void op_writepbr (uint32 addr, uint8 data) { op_write((regs.pc.b << 16) + (addr & 0xffff), data); }
void op_writedp (uint32 addr, uint8 data) { op_write((regs.d + (addr & 0xffff)) & 0xffff, data); }
void op_writesp (uint32 addr, uint8 data) { op_write((regs.s + (addr & 0xffff)) & 0xffff, data); }
+591
View File
@@ -0,0 +1,591 @@
uint8 sCPU::pio_status() {
return status.pio;
}
//WMDATA
uint8 sCPU::mmio_r2180() {
uint8 r = r_mem->read(0x7e0000 | status.wram_addr);
status.wram_addr = (status.wram_addr + 1) & 0x01ffff;
return r;
}
//WMDATA
void sCPU::mmio_w2180(uint8 data) {
r_mem->write(0x7e0000 | status.wram_addr, data);
status.wram_addr = (status.wram_addr + 1) & 0x01ffff;
}
//WMADDL
void sCPU::mmio_w2181(uint8 data) {
status.wram_addr = (status.wram_addr & 0xffff00) | (data);
status.wram_addr &= 0x01ffff;
}
//WMADDM
void sCPU::mmio_w2182(uint8 data) {
status.wram_addr = (status.wram_addr & 0xff00ff) | (data << 8);
status.wram_addr &= 0x01ffff;
}
//WMADDH
void sCPU::mmio_w2183(uint8 data) {
status.wram_addr = (status.wram_addr & 0x00ffff) | (data << 16);
status.wram_addr &= 0x01ffff;
}
//JOYSER0
//bit 0 is shared between JOYSER0 and JOYSER1, therefore
//strobing $4016.d0 affects both controller port latches.
//$4017 bit 0 writes are ignored.
void sCPU::mmio_w4016(uint8 data) {
status.joypad_strobe_latch = !!(data & 1);
if(status.joypad_strobe_latch == 1) {
snes->poll_input();
}
}
//JOYSER0
//7-2 = MDR
//1-0 = Joypad serial data
//
//TODO: test whether strobe latch of zero returns
//realtime or buffered status of joypadN.b
uint8 sCPU::mmio_r4016() {
uint8 r = regs.mdr & 0xfc;
r |= (uint8)snes->port_read(0);
return r;
}
//JOYSER1
//7-5 = MDR
//4-2 = Always 1 (pins are connected to GND)
//1-0 = Joypad serial data
uint8 sCPU::mmio_r4017() {
uint8 r = (regs.mdr & 0xe0) | 0x1c;
r |= (uint8)snes->port_read(1);
return r;
}
//NMITIMEN
void sCPU::mmio_w4200(uint8 data) {
status.nmi_enabled = !!(data & 0x80);
status.virq_enabled = !!(data & 0x20);
status.hirq_enabled = !!(data & 0x10);
status.auto_joypad_poll = !!(data & 0x01);
if(status.nmi_read == 0) {
if(status.nmi_line == 1 && status.nmi_enabled == 1) {
status.nmi_transition = 1;
}
status.nmi_line = !status.nmi_enabled;
}
if(status.irq_read == 0) {
if(status.irq_line == 1 && (status.virq_enabled || status.hirq_enabled)) {
status.irq_transition = 1;
}
status.irq_line = !(status.virq_enabled || status.hirq_enabled);
}
if(status.virq_enabled == true && status.hirq_enabled == false) {
status.irq_lock = false;
}
if(status.virq_enabled == false && status.hirq_enabled == false) {
status.irq_line = 1;
status.irq_read = 1;
status.irq_transition = 0;
}
update_interrupts();
counter_set(counter.irq_delay, 2);
}
//WRIO
void sCPU::mmio_w4201(uint8 data) {
if((status.pio & 0x80) && !(data & 0x80)) {
r_ppu->latch_counters();
}
status.pio = data;
}
//WRMPYA
void sCPU::mmio_w4202(uint8 data) {
status.mul_a = data;
}
//WRMPYB
void sCPU::mmio_w4203(uint8 data) {
status.mul_b = data;
status.r4216 = status.mul_a * status.mul_b;
//counter_set(counter.hw_math, 48);
}
//WRDIVL
void sCPU::mmio_w4204(uint8 data) {
status.div_a = (status.div_a & 0xff00) | (data);
}
//WRDIVH
void sCPU::mmio_w4205(uint8 data) {
status.div_a = (status.div_a & 0x00ff) | (data << 8);
}
//WRDIVB
void sCPU::mmio_w4206(uint8 data) {
status.div_b = data;
status.r4214 = (status.div_b) ? status.div_a / status.div_b : 0xffff;
status.r4216 = (status.div_b) ? status.div_a % status.div_b : status.div_a;
//counter_set(counter.hw_math, 96);
}
//HTIMEL
void sCPU::mmio_w4207(uint8 data) {
status.hirq_pos = (status.hirq_pos & ~0xff) | (data);
status.hirq_pos &= 0x01ff;
update_interrupts();
uint vpos = status.vcounter, hpos = status.hclock;
timeshift_backward(10, vpos, hpos);
if(hpos < status.hirq_trigger_pos) { status.irq_lock = false; }
}
//HTIMEH
void sCPU::mmio_w4208(uint8 data) {
status.hirq_pos = (status.hirq_pos & 0xff) | (data << 8);
status.hirq_pos &= 0x01ff;
update_interrupts();
uint vpos = status.vcounter, hpos = status.hclock;
timeshift_backward(10, vpos, hpos);
if(hpos < status.hirq_trigger_pos) { status.irq_lock = false; }
}
//VTIMEL
void sCPU::mmio_w4209(uint8 data) {
status.virq_pos = (status.virq_pos & ~0xff) | (data);
status.virq_pos &= 0x01ff;
update_interrupts();
uint vpos = status.vcounter, hpos = status.hclock;
timeshift_backward(10, vpos, hpos);
if(hpos < status.hirq_trigger_pos) { status.irq_lock = false; }
}
//VTIMEH
void sCPU::mmio_w420a(uint8 data) {
status.virq_pos = (status.virq_pos & 0xff) | (data << 8);
status.virq_pos &= 0x01ff;
update_interrupts();
uint vpos = status.vcounter, hpos = status.hclock;
timeshift_backward(10, vpos, hpos);
if(hpos < status.hirq_trigger_pos) { status.irq_lock = false; }
}
//DMAEN
void sCPU::mmio_w420b(uint8 data) {
for(int i = 0; i < 8; i++) {
channel[i].dma_enabled = !!(data & (1 << i));
}
if(data) {
status.dma_state = DMASTATE_DMASYNC;
status.dma_pending = true;
}
}
//HDMAEN
void sCPU::mmio_w420c(uint8 data) {
for(int i = 0; i < 8; i++) {
channel[i].hdma_enabled = !!(data & (1 << i));
}
}
//MEMSEL
void sCPU::mmio_w420d(uint8 data) {
r_mem->set_speed(data & 1);
}
//RDNMI
//7 = NMI acknowledge
//6-4 = MDR
//3-0 = CPU (5a22) version
uint8 sCPU::mmio_r4210() {
uint8 r = (regs.mdr & 0x70);
r |= (uint8)(!status.nmi_read) << 7;
if(!counter.nmi_fire) {
status.nmi_read = 1;
}
r |= (cpu_version & 0x0f);
return r;
}
//TIMEUP
//7 = IRQ acknowledge
//6-0 = MDR
uint8 sCPU::mmio_r4211() {
uint8 r = (regs.mdr & 0x7f);
r |= (uint8)(!status.irq_read) << 7;
if(!counter.irq_fire) {
status.irq_read = 1;
status.irq_line = 1;
status.irq_transition = 0;
}
return r;
}
//HVBJOY
//7 = VBLANK acknowledge
//6 = HBLANK acknowledge
//5-1 = MDR
//0 = JOYPAD acknowledge
uint8 sCPU::mmio_r4212() {
uint8 r = (regs.mdr & 0x3e);
uint16 vs = !overscan() ? 225 : 240;
//auto joypad polling
if(status.vcounter >= vs && status.vcounter <= (vs + 2))r |= 0x01;
//hblank
if(status.hclock <= 2 || status.hclock >= 1096)r |= 0x40;
//vblank
if(status.vcounter >= vs)r |= 0x80;
return r;
}
//RDIO
uint8 sCPU::mmio_r4213() {
return status.pio;
}
//RDDIVL
uint8 sCPU::mmio_r4214() {
if(counter.hw_math) { return 0x00; }
return status.r4214;
}
//RDDIVH
uint8 sCPU::mmio_r4215() {
if(counter.hw_math) { return 0x00; }
return status.r4214 >> 8;
}
//RDMPYL
uint8 sCPU::mmio_r4216() {
if(counter.hw_math) { return 0x00; }
return status.r4216;
}
//RDMPYH
uint8 sCPU::mmio_r4217() {
if(counter.hw_math) { return 0x00; }
return status.r4216 >> 8;
}
//TODO: handle reads during joypad polling (v=225-227)
uint8 sCPU::mmio_r4218() { return status.joy1l; } //JOY1L
uint8 sCPU::mmio_r4219() { return status.joy1h; } //JOY1H
uint8 sCPU::mmio_r421a() { return status.joy2l; } //JOY2L
uint8 sCPU::mmio_r421b() { return status.joy2h; } //JOY2H
uint8 sCPU::mmio_r421c() { return status.joy3l; } //JOY3L
uint8 sCPU::mmio_r421d() { return status.joy3h; } //JOY3H
uint8 sCPU::mmio_r421e() { return status.joy4l; } //JOY4L
uint8 sCPU::mmio_r421f() { return status.joy4h; } //JOY4H
//DMAPx
uint8 sCPU::mmio_r43x0(uint8 i) {
return channel[i].dmap;
}
//BBADx
uint8 sCPU::mmio_r43x1(uint8 i) {
return channel[i].destaddr;
}
//A1TxL
uint8 sCPU::mmio_r43x2(uint8 i) {
return channel[i].srcaddr;
}
//A1TxH
uint8 sCPU::mmio_r43x3(uint8 i) {
return channel[i].srcaddr >> 8;
}
//A1Bx
uint8 sCPU::mmio_r43x4(uint8 i) {
return channel[i].srcbank;
}
//DASxL
//union { uint16 xfersize; uint16 hdma_iaddr; };
uint8 sCPU::mmio_r43x5(uint8 i) {
return channel[i].xfersize;
}
//DASxH
//union { uint16 xfersize; uint16 hdma_iaddr; };
uint8 sCPU::mmio_r43x6(uint8 i) {
return channel[i].xfersize >> 8;
}
//DASBx
uint8 sCPU::mmio_r43x7(uint8 i) {
return channel[i].hdma_ibank;
}
//A2AxL
uint8 sCPU::mmio_r43x8(uint8 i) {
return channel[i].hdma_addr;
}
//A2AxH
uint8 sCPU::mmio_r43x9(uint8 i) {
return channel[i].hdma_addr >> 8;
}
//NTRLx
uint8 sCPU::mmio_r43xa(uint8 i) {
return channel[i].hdma_line_counter;
}
//???
uint8 sCPU::mmio_r43xb(uint8 i) {
return channel[i].unknown;
}
//DMAPx
void sCPU::mmio_w43x0(uint8 i, uint8 data) {
channel[i].dmap = data;
channel[i].direction = !!(data & 0x80);
channel[i].hdma_indirect = !!(data & 0x40);
channel[i].reversexfer = !!(data & 0x10);
channel[i].fixedxfer = !!(data & 0x08);
channel[i].xfermode = data & 7;
}
//DDBADx
void sCPU::mmio_w43x1(uint8 i, uint8 data) {
channel[i].destaddr = data;
}
//A1TxL
void sCPU::mmio_w43x2(uint8 i, uint8 data) {
channel[i].srcaddr = (channel[i].srcaddr & 0xff00) | (data);
}
//A1TxH
void sCPU::mmio_w43x3(uint8 i, uint8 data) {
channel[i].srcaddr = (channel[i].srcaddr & 0x00ff) | (data << 8);
}
//A1Bx
void sCPU::mmio_w43x4(uint8 i, uint8 data) {
channel[i].srcbank = data;
}
//DASxL
//union { uint16 xfersize; uint16 hdma_iaddr; };
void sCPU::mmio_w43x5(uint8 i, uint8 data) {
channel[i].xfersize = (channel[i].xfersize & 0xff00) | (data);
}
//DASxH
//union { uint16 xfersize; uint16 hdma_iaddr; };
void sCPU::mmio_w43x6(uint8 i, uint8 data) {
channel[i].xfersize = (channel[i].xfersize & 0x00ff) | (data << 8);
}
//DASBx
void sCPU::mmio_w43x7(uint8 i, uint8 data) {
channel[i].hdma_ibank = data;
}
//A2AxL
void sCPU::mmio_w43x8(uint8 i, uint8 data) {
channel[i].hdma_addr = (channel[i].hdma_addr & 0xff00) | (data);
}
//A2AxH
void sCPU::mmio_w43x9(uint8 i, uint8 data) {
channel[i].hdma_addr = (channel[i].hdma_addr & 0x00ff) | (data << 8);
}
//NTRLx
void sCPU::mmio_w43xa(uint8 i, uint8 data) {
channel[i].hdma_line_counter = data;
}
//???
void sCPU::mmio_w43xb(uint8 i, uint8 data) {
channel[i].unknown = data;
}
void sCPU::mmio_power() {
}
void sCPU::mmio_reset() {
//$2181-$2183
status.wram_addr = 0x000000;
//$4016-$4017
status.joypad_strobe_latch = 0;
status.joypad1_bits = ~0;
status.joypad2_bits = ~0;
//$4200
status.nmi_enabled = false;
status.hirq_enabled = false;
status.virq_enabled = false;
status.auto_joypad_poll = false;
//$4201
status.pio = 0xff;
//$4202-$4203
status.mul_a = 0xff;
status.mul_b = 0xff;
//$4204-$4206
status.div_a = 0xffff;
status.div_b = 0xff;
//$4207-$420a
status.hirq_pos = 0x01ff;
status.virq_pos = 0x01ff;
//$4214-$4217
status.r4214 = 0x0000;
status.r4216 = 0x0000;
//$4218-$421f
status.joy1l = 0x00;
status.joy1h = 0x00;
status.joy2l = 0x00;
status.joy2h = 0x00;
status.joy3l = 0x00;
status.joy3h = 0x00;
status.joy4l = 0x00;
status.joy4h = 0x00;
}
uint8 sCPU::mmio_read(uint16 addr) {
//APU
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
#ifdef FAVOR_SPEED
co_return();
#endif
return r_smp->port_read(addr & 3);
}
//DMA
if((addr & 0xff80) == 0x4300) { //$4300-$437f
uint i = (addr >> 4) & 7;
switch(addr & 0xf) {
case 0x0: return mmio_r43x0(i);
case 0x1: return mmio_r43x1(i);
case 0x2: return mmio_r43x2(i);
case 0x3: return mmio_r43x3(i);
case 0x4: return mmio_r43x4(i);
case 0x5: return mmio_r43x5(i);
case 0x6: return mmio_r43x6(i);
case 0x7: return mmio_r43x7(i);
case 0x8: return mmio_r43x8(i);
case 0x9: return mmio_r43x9(i);
case 0xa: return mmio_r43xa(i);
case 0xb: return mmio_r43xb(i);
case 0xc: return regs.mdr; //unmapped
case 0xd: return regs.mdr; //unmapped
case 0xe: return regs.mdr; //unmapped
case 0xf: return mmio_r43xb(i); //mirror of $43xb
}
}
switch(addr) {
case 0x2180: return mmio_r2180();
case 0x4016: return mmio_r4016();
case 0x4017: return mmio_r4017();
case 0x4210: return mmio_r4210();
case 0x4211: return mmio_r4211();
case 0x4212: return mmio_r4212();
case 0x4213: return mmio_r4213();
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();
case 0x421a: return mmio_r421a();
case 0x421b: return mmio_r421b();
case 0x421c: return mmio_r421c();
case 0x421d: return mmio_r421d();
case 0x421e: return mmio_r421e();
case 0x421f: return mmio_r421f();
}
return regs.mdr;
}
void sCPU::mmio_write(uint16 addr, uint8 data) {
//APU
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
#ifdef FAVOR_SPEED
co_return();
#endif
port_write(addr & 3, data);
return;
}
//DMA
if((addr & 0xff80) == 0x4300) { //$4300-$437f
uint i = (addr >> 4) & 7;
switch(addr & 0xf) {
case 0x0: mmio_w43x0(i, data); return;
case 0x1: mmio_w43x1(i, data); return;
case 0x2: mmio_w43x2(i, data); return;
case 0x3: mmio_w43x3(i, data); return;
case 0x4: mmio_w43x4(i, data); return;
case 0x5: mmio_w43x5(i, data); return;
case 0x6: mmio_w43x6(i, data); return;
case 0x7: mmio_w43x7(i, data); return;
case 0x8: mmio_w43x8(i, data); return;
case 0x9: mmio_w43x9(i, data); return;
case 0xa: mmio_w43xa(i, data); return;
case 0xb: mmio_w43xb(i, data); return;
case 0xc: return; //unmapped
case 0xd: return; //unmapped
case 0xe: return; //unmapped
case 0xf: mmio_w43xb(i, data); return; //mirror of $43xb
}
}
switch(addr) {
case 0x2180: mmio_w2180(data); return;
case 0x2181: mmio_w2181(data); return;
case 0x2182: mmio_w2182(data); return;
case 0x2183: mmio_w2183(data); return;
case 0x4016: mmio_w4016(data); return;
case 0x4017: return; //unmapped
case 0x4200: mmio_w4200(data); return;
case 0x4201: mmio_w4201(data); return;
case 0x4202: mmio_w4202(data); return;
case 0x4203: mmio_w4203(data); return;
case 0x4204: mmio_w4204(data); return;
case 0x4205: mmio_w4205(data); return;
case 0x4206: mmio_w4206(data); return;
case 0x4207: mmio_w4207(data); return;
case 0x4208: mmio_w4208(data); return;
case 0x4209: mmio_w4209(data); return;
case 0x420a: mmio_w420a(data); return;
case 0x420b: mmio_w420b(data); return;
case 0x420c: mmio_w420c(data); return;
case 0x420d: mmio_w420d(data); return;
}
}
+70
View File
@@ -0,0 +1,70 @@
void mmio_power();
void mmio_reset();
uint8 mmio_read (uint16 addr);
void mmio_write(uint16 addr, uint8 data);
uint8 pio_status();
uint8 mmio_r2180();
uint8 mmio_r4016();
uint8 mmio_r4017();
uint8 mmio_r4210();
uint8 mmio_r4211();
uint8 mmio_r4212();
uint8 mmio_r4213();
uint8 mmio_r4214();
uint8 mmio_r4215();
uint8 mmio_r4216();
uint8 mmio_r4217();
uint8 mmio_r4218();
uint8 mmio_r4219();
uint8 mmio_r421a();
uint8 mmio_r421b();
uint8 mmio_r421c();
uint8 mmio_r421d();
uint8 mmio_r421e();
uint8 mmio_r421f();
uint8 mmio_r43x0(uint8 i);
uint8 mmio_r43x1(uint8 i);
uint8 mmio_r43x2(uint8 i);
uint8 mmio_r43x3(uint8 i);
uint8 mmio_r43x4(uint8 i);
uint8 mmio_r43x5(uint8 i);
uint8 mmio_r43x6(uint8 i);
uint8 mmio_r43x7(uint8 i);
uint8 mmio_r43x8(uint8 i);
uint8 mmio_r43x9(uint8 i);
uint8 mmio_r43xa(uint8 i);
uint8 mmio_r43xb(uint8 i);
void mmio_w2180(uint8 data);
void mmio_w2181(uint8 data);
void mmio_w2182(uint8 data);
void mmio_w2183(uint8 data);
void mmio_w4016(uint8 data);
void mmio_w4200(uint8 data);
void mmio_w4201(uint8 data);
void mmio_w4202(uint8 data);
void mmio_w4203(uint8 data);
void mmio_w4204(uint8 data);
void mmio_w4205(uint8 data);
void mmio_w4206(uint8 data);
void mmio_w4207(uint8 data);
void mmio_w4208(uint8 data);
void mmio_w4209(uint8 data);
void mmio_w420a(uint8 data);
void mmio_w420b(uint8 data);
void mmio_w420c(uint8 data);
void mmio_w420d(uint8 data);
void mmio_w43x0(uint8 i, uint8 data);
void mmio_w43x1(uint8 i, uint8 data);
void mmio_w43x2(uint8 i, uint8 data);
void mmio_w43x3(uint8 i, uint8 data);
void mmio_w43x4(uint8 i, uint8 data);
void mmio_w43x5(uint8 i, uint8 data);
void mmio_w43x6(uint8 i, uint8 data);
void mmio_w43x7(uint8 i, uint8 data);
void mmio_w43x8(uint8 i, uint8 data);
void mmio_w43x9(uint8 i, uint8 data);
void mmio_w43xa(uint8 i, uint8 data);
void mmio_w43xb(uint8 i, uint8 data);
+72
View File
@@ -0,0 +1,72 @@
#include "../../base.h"
#include "core/core.cpp"
#include "dma/dma.cpp"
#include "memory/memory.cpp"
#include "mmio/mmio.cpp"
#include "timing/timing.cpp"
void scpu_entry_point() {
r_cpu->main();
}
void sCPU::run() {
co_call(thread);
}
void sCPU::power() {
status.region = bool(snes->region());
regs.a = regs.x = regs.y = 0x0000;
regs.s = 0x01ff;
mmio_power();
dma_power();
timing_power();
reset();
}
void sCPU::reset() {
if(thread)co_delete(thread);
thread = co_create(scpu_entry_point, 65536);
regs.pc.d = 0x000000;
regs.pc.l = r_mem->read(0xfffc);
regs.pc.h = r_mem->read(0xfffd);
regs.acc_8b = true;
regs.idx_8b = true;
//note: some registers are not fully reset by SNES
regs.x.h = 0x00;
regs.y.h = 0x00;
regs.s.h = 0x01;
regs.d = 0x0000;
regs.db = 0x00;
regs.p = 0x34;
regs.e = 1;
regs.mdr = 0x00;
event.wai = false;
event.irq = false;
event.irq_vector = 0xfffc; //reset vector address
mmio_reset();
dma_reset();
timing_reset();
apu_port[0] = 0x00;
apu_port[1] = 0x00;
apu_port[2] = 0x00;
apu_port[3] = 0x00;
}
sCPU::sCPU() {
//#include "core/optable.cpp"
thread = 0;
}
sCPU::~sCPU() {
if(thread)co_delete(thread);
}
+123
View File
@@ -0,0 +1,123 @@
class sCPU : public CPU {
public:
#include "core/core.h"
#include "dma/dma.h"
#include "memory/memory.h"
#include "mmio/mmio.h"
#include "timing/timing.h"
thread_t thread;
struct {
bool wai;
bool irq;
uint16 irq_vector;
} event;
struct {
bool enabled;
uint irq_delay;
uint irq_fire;
uint nmi_fire;
uint hw_math;
} counter;
enum {
DMASTATE_INACTIVE,
DMASTATE_DMASYNC,
DMASTATE_RUN,
DMASTATE_CPUSYNC,
};
struct {
//core
uint8 opcode;
bool in_opcode;
uint clock_count;
uint clocks_executed;
//timing
bool region;
uint16 region_scanlines;
uint16 vcounter, hcounter, hclock;
bool interlace, interlace_field;
bool overscan;
uint16 field_lines, line_clocks;
uint16 vblstart;
bool line_rendered;
uint16 line_render_position;
bool dram_refreshed;
uint16 dram_refresh_position;
bool hdmainit_triggered;
uint16 hdmainit_trigger_position;
bool hdma_triggered;
uint16 irq_delay;
uint16 nmi_trigger_pos;
bool nmi_read, nmi_line, nmi_transition;
bool nmi_pending;
uint16 virq_trigger_pos, hirq_trigger_pos;
bool irq_read, irq_line, irq_transition;
bool irq_lock, irq_pending;
//dma
uint dma_counter;
uint dma_clocks;
uint dma_state;
bool dma_pending;
bool hdma_pending;
bool hdmainit_pending;
//mmio
//$2181-$2183
uint32 wram_addr;
//$4016-$4017
bool joypad_strobe_latch;
uint32 joypad1_bits;
uint32 joypad2_bits;
//$4200
bool nmi_enabled;
bool hirq_enabled, virq_enabled;
bool auto_joypad_poll;
//$4201
uint8 pio;
//$4202-$4203
uint8 mul_a, mul_b;
//$4204-$4206
uint16 div_a;
uint8 div_b;
//$4207-$420a
uint16 hirq_pos, virq_pos;
//$4214-$4217
uint16 r4214;
uint16 r4216;
//$4218-$421f
uint8 joy1l, joy1h;
uint8 joy2l, joy2h;
uint8 joy3l, joy3h;
uint8 joy4l, joy4h;
} status;
void run();
void power();
void reset();
sCPU();
~sCPU();
};
+106
View File
@@ -0,0 +1,106 @@
void sCPU::update_interrupts() {
status.nmi_trigger_pos = (status.vcounter == status.vblstart) ? 2 : IRQ_TRIGGER_NEVER;
if(irq_pos_valid() == true) {
status.virq_trigger_pos = status.virq_pos;
status.hirq_trigger_pos = (status.hirq_enabled) ? ((status.hirq_pos + 1) * 4) : 0;
} else {
status.virq_trigger_pos = IRQ_TRIGGER_NEVER;
status.hirq_trigger_pos = IRQ_TRIGGER_NEVER;
}
}
alwaysinline void sCPU::nmi_tick() {
counter.nmi_fire -= 2;
if(counter.nmi_fire != 0) { return; }
if(status.nmi_enabled == true && status.nmi_line == 1) {
status.nmi_line = 0;
status.nmi_transition = 1;
}
}
alwaysinline void sCPU::irq_tick() {
counter.irq_fire -= 2;
if(counter.irq_fire != 0) { return; }
if(status.virq_enabled == true || status.hirq_enabled == true) {
status.irq_line = 0;
status.irq_transition = 1;
}
}
alwaysinline void sCPU::poll_interrupts() {
if(status.hclock == status.nmi_trigger_pos) {
status.nmi_read = 0;
counter.nmi_fire = 4;
}
if(status.hclock == 10) { status.irq_lock = false; }
if(status.hirq_trigger_pos == IRQ_TRIGGER_NEVER)return;
if(status.virq_enabled == false && status.hirq_enabled == false)return;
if(status.irq_lock == true)return;
uint vpos = status.vcounter;
uint hpos = status.hclock;
timeshift_backward(10, vpos, hpos);
bool trigger_irq = true;
if(status.virq_enabled == true && vpos != status.virq_trigger_pos)trigger_irq = false;
if(status.hirq_enabled == true && hpos != status.hirq_trigger_pos)trigger_irq = false;
if(trigger_irq == true) {
status.irq_lock = true;
status.irq_read = 0;
counter.irq_fire = 4;
}
}
bool sCPU::irq_pos_valid() {
uint vpos = status.virq_pos;
uint hpos = (status.hirq_enabled) ? status.hirq_pos : 0;
uint vlimit = region_scanlines() >> 1;
//positions that can never be latched
//vlimit = 262/NTSC, 312/PAL
//PAL results are unverified on hardware
if(vpos == 240 && hpos == 339 && interlace() == false && interlace_field() == 1)return false;
if(vpos == (vlimit - 1) && hpos == 339 && interlace() == false)return false;
if(vpos == vlimit && interlace() == false)return false;
if(vpos == vlimit && hpos == 339)return false;
if(vpos > vlimit)return false;
if(hpos > 339)return false;
return true;
}
alwaysinline bool sCPU::nmi_test() {
if(status.nmi_transition == 0)return false;
status.nmi_transition = 0;
event.wai = false;
return true;
}
alwaysinline bool sCPU::irq_test() {
if(status.irq_transition == 1)goto irq_trigger;
if(status.irq_read == 0) {
if(status.irq_line == 1 && counter.irq_fire) {
return false;
}
goto irq_trigger;
}
if(status.irq_line == 0) {
status.irq_line = 1;
goto irq_trigger;
}
return false;
irq_trigger:
status.irq_transition = 0;
event.wai = false;
return (regs.p.i) ? false : true;
}
+19
View File
@@ -0,0 +1,19 @@
void sCPU::run_auto_joypad_poll() {
uint16 joy1 = 0, joy2 = 0;
for(int i = 0; i < 16; i++) {
joy1 |= (uint16)snes->port_read(0) ? (0x8000 >> i) : 0;
joy2 |= (uint16)snes->port_read(1) ? (0x8000 >> i) : 0;
}
status.joy1l = joy1;
status.joy1h = joy1 >> 8;
status.joy2l = joy2;
status.joy2h = joy2 >> 8;
status.joy3l = 0x00;
status.joy3h = 0x00;
status.joy4l = 0x00;
status.joy4h = 0x00;
}
+26
View File
@@ -0,0 +1,26 @@
alwaysinline void sCPU::timeshift_forward(uint clocks, uint &vtime, uint &htime) {
htime += clocks;
if(htime >= status.line_clocks) {
htime -= status.line_clocks;
if(++vtime >= status.field_lines) {
vtime = 0;
}
}
}
alwaysinline void sCPU::timeshift_backward(uint clocks, uint &vtime, uint &htime) {
if(htime >= clocks) {
htime -= clocks;
} else {
htime += 1364 - clocks;
if(status.region == SNES::NTSC && status.vcounter == 241 &&
status.interlace == false && status.interlace_field == 1)htime -= 4;
if(vtime > 0) {
vtime--;
} else {
vtime = status.region_scanlines;
if(status.interlace == true && status.interlace_field == 1)vtime++;
}
}
}
+310
View File
@@ -0,0 +1,310 @@
#define ntsc_color_burst_phase_shift_scanline() \
(status.region == SNES::NTSC && status.vcounter == 240 && \
status.interlace == false && status.interlace_field == 1)
#include "timeshift.cpp"
#include "irq.cpp"
#include "joypad.cpp"
uint16 sCPU::vcounter() { return status.vcounter; }
uint16 sCPU::hclock() { return status.hclock; }
bool sCPU::interlace() { return status.interlace; }
bool sCPU::interlace_field() { return status.interlace_field; }
bool sCPU::overscan() { return status.overscan; }
uint16 sCPU::region_scanlines() { return status.region_scanlines; }
uint sCPU::dma_counter() { return (status.dma_counter + status.hclock) & 7; }
void sCPU::set_interlace(bool r) {
status.interlace = r;
update_interrupts();
}
void sCPU::set_overscan (bool r) {
status.overscan = r;
status.vblstart = (status.overscan == false) ? 225 : 240;
update_interrupts();
}
/*****
* One PPU dot = 4 CPU clocks
*
* PPU dots 323 and 327 are 6 CPU clocks long.
* This does not apply to NTSC non-interlace scanline 240 on odd fields. This is
* because the PPU skips one dot to alter the color burst phase of the video signal.
*
* Dot 323 range = { 1292, 1294, 1296 }
* Dot 327 range = { 1310, 1312, 1314 }
*****/
uint16 sCPU::hcounter() {
if(ntsc_color_burst_phase_shift_scanline() == true) {
return (status.hclock >> 2);
}
return (status.hclock - ((status.hclock > 1292) << 1) - ((status.hclock > 1310) << 1)) >> 2;
}
void sCPU::add_clocks(uint clocks) {
status.clocks_executed += clocks;
if(counter.irq_delay) {
counter.irq_delay = (counter.irq_delay > clocks) ? (counter.irq_delay - clocks) : 0;
}
if(status.hclock + clocks >= status.line_clocks) {
clocks = (status.hclock + clocks) - status.line_clocks;
while(status.hclock < status.line_clocks - 2) { tick(); }
scanline();
}
clocks >>= 1;
while(clocks--) { tick(); }
}
alwaysinline void sCPU::tick() {
status.hclock += 2;
if(counter.nmi_fire) { nmi_tick(); }
if(counter.irq_fire) { irq_tick(); }
if(status.dram_refreshed == false && status.hclock >= status.dram_refresh_position) {
status.dram_refreshed = true;
add_clocks(40);
return;
}
poll_interrupts();
}
void sCPU::scanline() {
status.hclock = 0;
status.dma_counter = (status.dma_counter + status.line_clocks) & 7;
if(++status.vcounter >= status.field_lines) {
frame();
}
status.line_clocks = (ntsc_color_burst_phase_shift_scanline() == false) ? 1364 : 1360;
//dram refresh occurs once every scanline
status.dram_refreshed = false;
if(cpu_version == 2) {
if(ntsc_color_burst_phase_shift_scanline() == false) {
if(status.dram_refresh_position == 534) {
status.dram_refresh_position = 538;
} else {
status.dram_refresh_position = 534;
}
}
}
//hdma triggers once every visible scanline
status.line_rendered = false;
status.hdma_triggered = (status.vcounter <= (!overscan() ? 224 : 239)) ? false : true;
r_ppu->scanline();
snes->scanline();
update_interrupts();
if(status.auto_joypad_poll == true && status.vcounter == (!overscan() ? 227 : 242)) {
snes->poll_input();
run_auto_joypad_poll();
}
}
void sCPU::frame() {
status.nmi_read = 1;
status.nmi_line = 1;
status.nmi_transition = 0;
status.vcounter = 0;
status.interlace_field ^= 1;
status.field_lines = (status.region_scanlines >> 1);
//interlaced even fields have one extra scanline
//(263+262=525 NTSC, 313+312=625 PAL)
if(status.interlace == true && status.interlace_field == 0)status.field_lines++;
status.hdmainit_triggered = false;
if(cpu_version == 1) {
status.hdmainit_trigger_position = 12 + 8 - dma_counter();
} else {
status.hdmainit_trigger_position = 12 + dma_counter();
}
r_ppu->frame();
snes->frame();
}
/*****
* precycle_edge()
*
* Used for DMA/HDMA bus synchronization
*****/
alwaysinline void sCPU::precycle_edge() {
if(status.dma_state == DMASTATE_CPUSYNC) {
status.dma_state = DMASTATE_INACTIVE;
uint n = status.clock_count - (status.dma_clocks % status.clock_count);
add_clocks(n ? n : status.clock_count);
}
}
/*****
* cycle_edge()
*
* Used to test for HDMA, which can trigger on the edge of every opcode cycle.
*****/
void sCPU::cycle_edge() {
if(status.line_rendered == false) {
if(status.hclock >= status.line_render_position) {
status.line_rendered = true;
r_ppu->render_scanline();
}
}
switch(status.dma_state) {
case DMASTATE_INACTIVE:
break;
case DMASTATE_DMASYNC:
status.dma_state = DMASTATE_RUN;
break;
case DMASTATE_RUN:
status.dma_state = DMASTATE_CPUSYNC;
status.dma_clocks = 8 - dma_counter() + 8;
add_clocks(status.dma_clocks);
if(status.hdmainit_pending) { hdma_init(); status.hdmainit_pending = false; }
if(status.hdma_pending) { hdma_run(); status.hdma_pending = false; }
if(status.dma_pending) { dma_run(); status.dma_pending = false; }
break;
}
if(status.hdmainit_triggered == false) {
if(status.hclock >= status.hdmainit_trigger_position || status.vcounter) {
status.hdmainit_triggered = true;
hdma_init_reset();
if(hdma_enabled_channels()) {
if(status.dma_state == DMASTATE_INACTIVE) {
status.dma_state = DMASTATE_DMASYNC;
status.hdmainit_pending = true;
} else {
hdma_init();
}
}
}
}
if(status.hdma_triggered == false) {
if(status.hclock >= 1106) {
status.hdma_triggered = true;
if(hdma_active_channels()) {
if(status.dma_state == DMASTATE_INACTIVE) {
status.dma_state = DMASTATE_DMASYNC;
status.hdma_pending = true;
} else {
hdma_run();
}
}
}
}
}
/*****
* last_cycle()
*
* Used to test for NMI/IRQ, which can trigger on the edge of every opcode.
* Test one cycle early to simulate two-stage pipeline of x816 CPU.
*
* status.irq_delay is used to simulate hardware delay before interrupts can
* trigger during certain events (immediately after DMA, writes to $4200, etc)
*****/
void sCPU::last_cycle() {
if(counter.irq_delay) { return; }
status.nmi_pending |= nmi_test();
status.irq_pending |= irq_test();
event.irq = (status.nmi_pending || status.irq_pending);
}
/*****
* clocks_executed()
*
* Return number of clocks executed since last call to this function.
* Used by class SNES to control CPU<>APU synchronization.
*****/
uint32 sCPU::clocks_executed() {
uint32 r = status.clocks_executed;
status.clocks_executed = 0;
return r;
}
void sCPU::timing_power() {
}
void sCPU::timing_reset() {
counter.enabled = false;
counter.irq_delay = 0;
counter.hw_math = 0;
counter.irq_fire = 0;
counter.nmi_fire = 0;
status.clock_count = 0;
status.clocks_executed = 0;
status.vcounter = 0;
status.hcounter = 0;
status.hclock = 0;
status.interlace = 0;
status.interlace_field = 0;
status.overscan = false;
status.region_scanlines = (status.region == SNES::NTSC) ? 525 : 625;
status.vblstart = 225;
status.field_lines = status.region_scanlines >> 1;
status.line_clocks = 1364;
status.line_rendered = false;
status.line_render_position = minmax<0, 1112>((uint16)config::ppu.render_scanline_position);
status.dram_refreshed = false;
status.dram_refresh_position = (cpu_version == 1) ? 530 : 538;
status.hdmainit_triggered = false;
status.hdmainit_trigger_position = 0;
status.hdma_triggered = false;
status.irq_delay = 0;
status.nmi_read = 1;
status.nmi_line = 1;
status.nmi_transition = 0;
status.nmi_pending = false;
status.irq_read = 1;
status.irq_line = 1;
status.irq_transition = 0;
status.irq_lock = false;
status.irq_pending = false;
update_interrupts();
status.dma_counter = 0;
status.dma_state = DMASTATE_INACTIVE;
status.dma_pending = false;
status.hdma_pending = false;
status.hdmainit_pending = false;
//initial latch values for $213c/$213d
//[x]0035 : [y]0000 (53.0 -> 212) [lda $2137]
//[x]0038 : [y]0000 (56.5 -> 226) [nop : lda $2137]
add_clocks(186);
}
#undef ntsc_color_burst_phase_shift_scanline
+47
View File
@@ -0,0 +1,47 @@
uint16 vcounter();
uint16 hcounter();
uint16 hclock();
bool interlace();
bool interlace_field();
bool overscan();
uint16 region_scanlines();
void set_interlace(bool r);
void set_overscan(bool r);
uint dma_counter();
void add_clocks(uint clocks);
void tick();
void scanline();
void frame();
void precycle_edge();
void cycle_edge();
void last_cycle();
uint32 clocks_executed();
void timing_power();
void timing_reset();
void counter_set(uint &ctr, uint clocks) {
if(clocks >= ctr) { ctr = clocks; }
}
//timeshift.cpp
void timeshift_forward (uint clocks, uint &v, uint &h);
void timeshift_backward(uint clocks, uint &v, uint &h);
//irq.cpp
enum { IRQ_TRIGGER_NEVER = 0x3fff };
void update_interrupts();
void nmi_tick();
void irq_tick();
void poll_interrupts();
bool irq_pos_valid();
bool nmi_test();
bool irq_test();
//joypad.cpp
void run_auto_joypad_poll();
Binary file not shown.

Before

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 26 KiB

File renamed without changes.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 20 KiB

+93 -139
View File
@@ -19,143 +19,132 @@ void bDSP::writew(uint16 addr, uint16 data) {
}
uint8 bDSP::read(uint8 addr) {
int i, v, n;
addr &= 127;
v = addr >> 4;
n = addr & 15;
int v = addr >> 4;
int n = addr & 15;
switch(addr) {
case 0x00:case 0x10:case 0x20:case 0x30:
case 0x40:case 0x50:case 0x60:case 0x70:
case 0x00: case 0x10: case 0x20: case 0x30:
case 0x40: case 0x50: case 0x60: case 0x70:
return voice[v].VOLL;
case 0x01:case 0x11:case 0x21:case 0x31:
case 0x41:case 0x51:case 0x61:case 0x71:
case 0x01: case 0x11: case 0x21: case 0x31:
case 0x41: case 0x51: case 0x61: case 0x71:
return voice[v].VOLR;
case 0x02:case 0x12:case 0x22:case 0x32:
case 0x42:case 0x52:case 0x62:case 0x72:
return voice[v].PITCH >> 8;
case 0x03:case 0x13:case 0x23:case 0x33:
case 0x43:case 0x53:case 0x63:case 0x73:
case 0x02: case 0x12: case 0x22: case 0x32:
case 0x42: case 0x52: case 0x62: case 0x72:
return voice[v].PITCH;
case 0x04:case 0x14:case 0x24:case 0x34:
case 0x44:case 0x54:case 0x64:case 0x74:
case 0x03: case 0x13: case 0x23: case 0x33:
case 0x43: case 0x53: case 0x63: case 0x73:
return voice[v].PITCH >> 8;
case 0x04: case 0x14: case 0x24: case 0x34:
case 0x44: case 0x54: case 0x64: case 0x74:
return voice[v].SRCN;
case 0x05:case 0x15:case 0x25:case 0x35:
case 0x45:case 0x55:case 0x65:case 0x75:
case 0x05: case 0x15: case 0x25: case 0x35:
case 0x45: case 0x55: case 0x65: case 0x75:
return voice[v].ADSR1;
case 0x06:case 0x16:case 0x26:case 0x36:
case 0x46:case 0x56:case 0x66:case 0x76:
case 0x06: case 0x16: case 0x26: case 0x36:
case 0x46: case 0x56: case 0x66: case 0x76:
return voice[v].ADSR2;
case 0x07:case 0x17:case 0x27:case 0x37:
case 0x47:case 0x57:case 0x67:case 0x77:
case 0x07: case 0x17: case 0x27: case 0x37:
case 0x47: case 0x57: case 0x67: case 0x77:
return voice[v].GAIN;
case 0x08:case 0x18:case 0x28:case 0x38:
case 0x48:case 0x58:case 0x68:case 0x78:
case 0x08: case 0x18: case 0x28: case 0x38:
case 0x48: case 0x58: case 0x68: case 0x78:
return voice[v].ENVX;
case 0x09:case 0x19:case 0x29:case 0x39:
case 0x49:case 0x59:case 0x69:case 0x79:
case 0x09: case 0x19: case 0x29: case 0x39:
case 0x49: case 0x59: case 0x69: case 0x79:
return voice[v].OUTX;
case 0x0f:case 0x1f:case 0x2f:case 0x3f:
case 0x4f:case 0x5f:case 0x6f:case 0x7f:
case 0x0f: case 0x1f: case 0x2f: case 0x3f:
case 0x4f: case 0x5f: case 0x6f: case 0x7f:
return status.FIR[v];
case 0x0c:return status.MVOLL;
case 0x1c:return status.MVOLR;
case 0x2c:return status.EVOLL;
case 0x3c:return status.EVOLR;
case 0x4c:return status.KON;
case 0x5c:return status.KOFF;
case 0x6c:return status.FLG;
case 0x7c:return status.ENDX;
case 0x0c: return status.MVOLL;
case 0x1c: return status.MVOLR;
case 0x2c: return status.EVOLL;
case 0x3c: return status.EVOLR;
case 0x4c: return status.KON;
case 0x5c: return status.KOFF;
case 0x6c: return status.FLG;
case 0x7c: return status.ENDX;
case 0x0d:return status.EFB;
case 0x2d:return status.PMON;
case 0x3d:return status.NON;
case 0x4d:return status.EON;
case 0x5d:return status.DIR;
case 0x6d:return status.ESA;
case 0x7d:return status.EDL;
case 0x0d: return status.EFB;
case 0x2d: return status.PMON;
case 0x3d: return status.NON;
case 0x4d: return status.EON;
case 0x5d: return status.DIR;
case 0x6d: return status.ESA;
case 0x7d: return status.EDL;
}
return dspram[addr];
}
void bDSP::write(uint8 addr, uint8 data) {
int i, v, n;
//0x80-0xff is a read-only mirror of 0x00-0x7f
if(addr & 0x80)return;
v = addr >> 4;
n = addr & 15;
int v = addr >> 4;
int n = addr & 15;
switch(addr) {
case 0x00:case 0x10:case 0x20:case 0x30:
case 0x40:case 0x50:case 0x60:case 0x70:
case 0x00: case 0x10: case 0x20: case 0x30:
case 0x40: case 0x50: case 0x60: case 0x70:
voice[v].VOLL = data;
break;
case 0x01:case 0x11:case 0x21:case 0x31:
case 0x41:case 0x51:case 0x61:case 0x71:
case 0x01: case 0x11: case 0x21: case 0x31:
case 0x41: case 0x51: case 0x61: case 0x71:
voice[v].VOLR = data;
break;
case 0x02:case 0x12:case 0x22:case 0x32:
case 0x42:case 0x52:case 0x62:case 0x72:
case 0x02: case 0x12: case 0x22: case 0x32:
case 0x42: case 0x52: case 0x62: case 0x72:
voice[v].PITCH &= 0xff00;
voice[v].PITCH |= data;
break;
case 0x03:case 0x13:case 0x23:case 0x33:
case 0x43:case 0x53:case 0x63:case 0x73:
case 0x03: case 0x13: case 0x23: case 0x33:
case 0x43: case 0x53: case 0x63: case 0x73:
voice[v].PITCH &= 0x00ff;
voice[v].PITCH |= data << 8;
break;
case 0x04:case 0x14:case 0x24:case 0x34:
case 0x44:case 0x54:case 0x64:case 0x74:
case 0x04: case 0x14: case 0x24: case 0x34:
case 0x44: case 0x54: case 0x64: case 0x74:
voice[v].SRCN = data;
break;
//below is anomie's code, but TRAC says writing SRCN doesn't affect anything until a
//BRR-with-end block is encountered, where it loads the loop address from the new SRCN
//anomie's code breaks MK2 sound completely...
if(voice[v].SRCN != data) {
voice[v].SRCN = data;
voice[v].brr_ptr = readw((status.DIR << 8) + (voice[v].SRCN << 2) + ((voice[v].brr_looped) ? 2 : 0));
voice[v].brr_index = 0;
}
break;
case 0x05:case 0x15:case 0x25:case 0x35:
case 0x45:case 0x55:case 0x65:case 0x75:
case 0x05: case 0x15: case 0x25: case 0x35:
case 0x45: case 0x55: case 0x65: case 0x75:
voice[v].ADSR1 = data;
voice[v].AdjustEnvelope();
break;
case 0x06:case 0x16:case 0x26:case 0x36:
case 0x46:case 0x56:case 0x66:case 0x76:
case 0x06: case 0x16: case 0x26: case 0x36:
case 0x46: case 0x56: case 0x66: case 0x76:
voice[v].ADSR2 = data;
//sustain_level = 0-7, 7 is a special case handled by ATTACK envx mode
voice[v].env_sustain = (voice[v].ADSR_sus_level() + 1) << 8;
voice[v].AdjustEnvelope();
break;
case 0x07:case 0x17:case 0x27:case 0x37:
case 0x47:case 0x57:case 0x67:case 0x77:
case 0x07: case 0x17: case 0x27: case 0x37:
case 0x47: case 0x57: case 0x67: case 0x77:
voice[v].GAIN = data;
voice[v].AdjustEnvelope();
break;
case 0x08:case 0x18:case 0x28:case 0x38:
case 0x48:case 0x58:case 0x68:case 0x78:
case 0x08: case 0x18: case 0x28: case 0x38:
case 0x48: case 0x58: case 0x68: case 0x78:
voice[v].ENVX = data;
break;
case 0x09:case 0x19:case 0x29:case 0x39:
case 0x49:case 0x59:case 0x69:case 0x79:
case 0x09: case 0x19: case 0x29: case 0x39:
case 0x49: case 0x59: case 0x69: case 0x79:
voice[v].OUTX = data;
break;
case 0x0f:case 0x1f:case 0x2f:case 0x3f:
case 0x4f:case 0x5f:case 0x6f:case 0x7f:
case 0x0f: case 0x1f: case 0x2f: case 0x3f:
case 0x4f: case 0x5f: case 0x6f: case 0x7f:
status.FIR[v] = data;
break;
case 0x0c:status.MVOLL = data;break;
case 0x1c:status.MVOLR = data;break;
case 0x2c:status.EVOLL = data;break;
case 0x3c:status.EVOLR = data;break;
case 0x0c: status.MVOLL = data; break;
case 0x1c: status.MVOLR = data; break;
case 0x2c: status.EVOLL = data; break;
case 0x3c: status.EVOLR = data; break;
case 0x4c:
status.KON = data;
@@ -179,12 +168,12 @@ int i, v, n;
status.ENDX = 0;
break;
case 0x0d:status.EFB = data;break;
case 0x2d:status.PMON = data;break;
case 0x3d:status.NON = data;break;
case 0x4d:status.EON = data;break;
case 0x5d:status.DIR = data;break;
case 0x6d:status.ESA = data;break;
case 0x0d: status.EFB = data; break;
case 0x2d: status.PMON = data; break;
case 0x3d: status.NON = data; break;
case 0x4d: status.EON = data; break;
case 0x5d: status.DIR = data; break;
case 0x6d: status.ESA = data; break;
case 0x7d:
status.EDL = data;
@@ -196,11 +185,10 @@ int i, v, n;
}
void bDSP::power() {
int v;
spcram = r_apu->get_spcram_handle();
spcram = r_smp->get_spcram_handle();
memset(dspram, 0x00, 128);
for(v=0;v<8;v++) {
for(int v = 0; v < 8; v++) {
voice[v].VOLL = 0;
voice[v].VOLR = 0;
voice[v].PITCH = 0;
@@ -230,7 +218,6 @@ int v;
}
void bDSP::reset() {
int v;
status.KON = 0x00;
status.KOFF = 0x00;
status.FLG |= 0xe0;
@@ -245,7 +232,7 @@ int v;
status.echo_index = 0;
status.fir_buffer_index = 0;
for(v=0;v<8;v++) {
for(int v = 0; v < 8; v++) {
voice[v].ENVX = 0;
voice[v].OUTX = 0;
@@ -273,28 +260,7 @@ int v;
dsp_counter = 0;
}
int32 bDSP::clamp(int32 bits, int32 x) {
int32 b = 1 << (bits - 1);
if(x > (b - 1)) {
return (b - 1);
} else if(x < -b) {
return -b;
} else {
return x;
}
}
int32 bDSP::clip(int32 bits, int32 x) {
int32 b = 1 << (bits - 1);
if(x & b) {
return x | ~(b - 1);
} else {
return x & (b - 1);
}
}
uint32 bDSP::run() {
int v, d;
uint8 pmon;
int32 sample;
int32 msamplel, msampler;
@@ -302,10 +268,8 @@ int32 esamplel, esampler;
int32 fir_samplel, fir_sampler;
pmon = status.PMON & ~status.NON & ~1;
//if(!(dsp_counter++ & 1) && status.key_flag) {
//TRAC believes KON/KOFF is polled every sample. further testing is needed
if(status.key_flag) {
for(v=0;v<8;v++) {
if(!(dsp_counter++ & 1) && status.key_flag) {
for(int v = 0; v < 8; v++) {
uint8 mask = 1 << v;
if(status.soft_reset()) {
if(voice[v].env_state != SILENCE) {
@@ -318,7 +282,6 @@ int32 fir_samplel, fir_sampler;
voice[v].AdjustEnvelope();
}
} else if(status.kon & mask) {
//new KON code
status.ENDX &= ~mask;
status.kon &= ~mask;
@@ -334,9 +297,6 @@ int32 fir_samplel, fir_sampler;
voice[v].AdjustEnvelope();
}
}
//old KON code, breaks sound effects in DL / SFA2
// status.ENDX &= ~status.kon;
// status.kon = 0;
status.key_flag = false;
}
@@ -351,7 +311,7 @@ int32 fir_samplel, fir_sampler;
msamplel = msampler = 0;
esamplel = esampler = 0;
for(v=0;v<8;v++) {
for(int v = 0; v < 8; v++) {
if(voice[v].brr_index < -1) {
voice[v].brr_index++;
voice[v].OUTX = voice[v].outx = 0;
@@ -380,11 +340,6 @@ int32 fir_samplel, fir_sampler;
if(voice[v].brr_index == 0) {
voice[v].brr_header = readb(voice[v].brr_ptr);
//moving status.ENDX bit set into == BRR_END condition per DMV27
//if(voice[v].brr_header_flags() & BRR_END) {
// status.ENDX |= (1 << v);
//}
if(voice[v].brr_header_flags() == BRR_END) {
status.ENDX |= (1 << v);
voice[v].env_state = SILENCE;
@@ -396,9 +351,9 @@ int32 fir_samplel, fir_sampler;
if(voice[v].env_state != SILENCE) {
sample = readb(voice[v].brr_ptr + 1 + (voice[v].brr_index >> 1));
if(voice[v].brr_index & 1) {
sample = clip(4, sample);
sample = sclip<4>(sample);
} else {
sample = clip(4, sample >> 4);
sample = sclip<4>(sample >> 4);
}
if(voice[v].brr_header_shift() <= 12) {
@@ -423,7 +378,7 @@ int32 fir_samplel, fir_sampler;
break;
}
S(0) = sample = clip(15, clamp(16, sample));
S(0) = sample = sclip<15>(sclamp<16>(sample));
} else {
S(0) = sample = 0;
}
@@ -431,7 +386,6 @@ int32 fir_samplel, fir_sampler;
if(++voice[v].brr_index > 15) {
voice[v].brr_index = 0;
if(voice[v].brr_header_flags() & BRR_END) {
//below condition added by DMV27
if(voice[v].brr_header_flags() & BRR_LOOP) {
status.ENDX |= (1 << v);
}
@@ -502,7 +456,7 @@ int32 fir_samplel, fir_sampler;
if(voice[v].envx >= 0x7ff) {
voice[v].envx = 0x7ff;
//attack raises to max. envx, if sustain is also set to max. envx, skip decay phase
//attack raises to max envx. if sustain is also set to max envx, skip decay phase
voice[v].env_state = ((voice[v].env_sustain == 0x800) ? SUSTAIN : DECAY);
voice[v].AdjustEnvelope();
}
@@ -521,15 +475,15 @@ int32 fir_samplel, fir_sampler;
//gaussian interpolation / noise
if(status.NON & (1 << v)) {
sample = clip(15, status.noise_sample);
sample = sclip<15>(status.noise_sample);
} else {
d = voice[v].pitch_ctr >> 4; //-256 <= sample <= -1
int32 d = voice[v].pitch_ctr >> 4; //-256 <= sample <= -1
sample = ((GaussTable[ -1-d] * S(-3)) >> 11);
sample += ((GaussTable[255-d] * S(-2)) >> 11);
sample += ((GaussTable[512+d] * S(-1)) >> 11);
sample = clip (15, sample);
sample = sclip <15>(sample);
sample += ((GaussTable[256+d] * S( 0)) >> 11);
sample = clamp(15, sample);
sample = sclamp<15>(sample);
}
#undef S
@@ -579,8 +533,8 @@ int32 fir_samplel, fir_sampler;
esamplel += (fir_samplel * status.EFB) >> 14;
esampler += (fir_sampler * status.EFB) >> 14;
esamplel = clamp(16, esamplel);
esampler = clamp(16, esampler);
esamplel = sclamp<16>(esamplel);
esampler = sclamp<16>(esampler);
writew((status.ESA << 8) + status.echo_index, esamplel);
writew((status.ESA << 8) + status.echo_index + 2, esampler);
@@ -600,11 +554,11 @@ int32 fir_samplel, fir_sampler;
msamplel += (fir_samplel * status.EVOLL) >> 14;
msampler += (fir_sampler * status.EVOLR) >> 14;
msamplel = clamp(16, msamplel);
msampler = clamp(16, msampler);
msamplel = sclamp<16>(msamplel);
msampler = sclamp<16>(msampler);
}
return (uint32)(((uint16)msamplel) | ((uint16)msampler << 16));
return uint32( uint16(msamplel) | (uint16(msampler) << 16) );
}
bDSP::bDSP() {}
+9 -14
View File
@@ -5,10 +5,7 @@ uint8 *spcram;
uint32 dsp_counter;
enum {
BRR_END = 1,
BRR_LOOP = 2
};
enum { BRR_END = 1, BRR_LOOP = 2 };
uint8 readb (uint16 addr);
uint16 readw (uint16 addr);
@@ -74,9 +71,9 @@ struct Status {
uint8 fir_buffer_index;
//functions
bool soft_reset() { return !!(FLG & 0x80); }
bool mute() { return !!(FLG & 0x40); }
bool echo_write() { return !(FLG & 0x20); }
bool soft_reset() { return bool(FLG & 0x80); }
bool mute() { return bool(FLG & 0x40); }
bool echo_write() { return !(FLG & 0x20); }
} status;
struct Voice {
@@ -116,7 +113,7 @@ struct Voice {
uint8 brr_header_filter() { return (brr_header >> 2) & 3; }
uint8 brr_header_flags() { return brr_header & 3; }
bool ADSR_enabled() { return !!(ADSR1 & 0x80); }
bool ADSR_enabled() { return bool(ADSR1 & 0x80); }
uint8 ADSR_decay() { return (ADSR1 >> 4) & 7; }
uint8 ADSR_attack() { return ADSR1 & 15; }
uint8 ADSR_sus_level() { return ADSR2 >> 5; }
@@ -147,10 +144,10 @@ struct Voice {
}
} else if(GAIN & 0x80) {
switch(GAIN & 0x60) {
case 0x00:env_mode = LINEAR_DEC; break;
case 0x20:env_mode = EXP_DEC; break;
case 0x40:env_mode = LINEAR_INC; break;
case 0x60:env_mode = BENT_INC; break;
case 0x00: env_mode = LINEAR_DEC; break;
case 0x20: env_mode = EXP_DEC; break;
case 0x40: env_mode = LINEAR_INC; break;
case 0x60: env_mode = BENT_INC; break;
}
env_rate = RateTable[GAIN & 0x1f];
} else {
@@ -161,8 +158,6 @@ struct Voice {
}
} voice[8];
int32 clamp(int32 bits, int32 x);
int32 clip (int32 bits, int32 x);
public:
uint8 read (uint8 addr);
void write(uint8 addr, uint8 data);
+24 -39
View File
@@ -7,7 +7,7 @@
#define r_mem ref(deref(mem))
#define r_cpu ref(deref(cpu))
#define r_apu ref(deref(apu))
#define r_smp ref(deref(smp))
#define r_dsp ref(deref(dsp))
#define r_ppu ref(deref(ppu))
@@ -19,10 +19,12 @@
#include "memory/bmemory/bmemory.h"
#include "cpu/cpu.h"
#include "cpu/bcpu/bcpu.h"
#include "cpu/scpu/scpu.h"
//#include "cpu/bcpu/bcpu.h"
#include "apu/apu.h"
#include "apu/bapu/bapu.h"
#include "smp/smp.h"
#include "smp/ssmp/ssmp.h"
//#include "smp/bsmp/bsmp.h"
#include "dsp/dsp.h"
#include "dsp/bdsp/bdsp.h"
@@ -35,6 +37,7 @@
#include "chip/srtc/srtc.h"
#include "chip/sdd1/sdd1.h"
#include "chip/c4/c4.h"
#include "chip/dsp1/dsp1.h"
#include "chip/dsp2/dsp2.h"
#include "chip/obc1/obc1.h"
@@ -42,50 +45,32 @@ extern MMIO mmio_unmapped;
#ifdef POLYMORPHISM
extern MemBus *deref(mem);
extern CPU *deref(cpu);
extern APU *deref(apu);
extern SMP *deref(smp);
extern DSP *deref(dsp);
extern PPU *deref(ppu);
#else
extern MEMCORE deref(mem);
extern CPUCORE deref(cpu);
extern APUCORE deref(apu);
extern SMPCORE deref(smp);
extern DSPCORE deref(dsp);
extern PPUCORE deref(ppu);
#endif
extern SNES *snes;
extern SRTC *srtc;
extern SDD1 *sdd1;
extern C4 *c4;
extern DSP2 *dsp2;
extern OBC1 *obc1;
#endif
#include "config/config.h"
#ifdef INTERFACE_MAIN
Cartridge cartridge;
Cheat cheat;
#include "config/config.cpp"
#ifdef POLYMORPHISM
MemBus *deref(mem);
CPU *deref(cpu);
APU *deref(apu);
DSP *deref(dsp);
PPU *deref(ppu);
#else
MEMCORE deref(mem);
CPUCORE deref(cpu);
APUCORE deref(apu);
DSPCORE deref(dsp);
PPUCORE deref(ppu);
#endif
SNES *snes;
SRTC *srtc;
SDD1 *sdd1;
C4 *c4;
DSP2 *dsp2;
OBC1 *obc1;
#include "config/config.cpp"
#ifdef POLYMORPHISM
MemBus *deref(mem);
CPU *deref(cpu);
APU *deref(smp);
DSP *deref(dsp);
PPU *deref(ppu);
#else
MEMCORE deref(mem);
CPUCORE deref(cpu);
SMPCORE deref(smp);
DSPCORE deref(dsp);
PPUCORE deref(ppu);
#endif
#endif
Loaded 100 of 354 files, more files were not shown because too many files have changed in this diff. Show more