Compare commits

..

22 Commits
v008 ... v018

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
byuu
a3945e5772 Update to bsnes v016 release.
- Added Direct3D renderer with options for disabling hardware filtering and scanlines
    - Screenshots can now be captured in BMP, JPEG, or PNG format
    - Added config file option to specify default ROM and SRAM paths
    - Config file is always loaded from path to bsnes executable
    - Added support for analog mode joypad input
    - Up to 32 joypads can be used at once now
    - Fixed bug regarding enabling interlace mid-frame
    - Moved PPU rendering to V=240, from V=0
    - Started on new debugger. So far only debug messages and memory editor added
    - Added joypad axis resistance option for analog input mode
    - Added config file option to set window style attributes
    - Added color adjustment settings for brightness, contrast, gamma, and scanline intensity
    - Added grayscale, sepia, and invert color settings
    - Added NTSC filter by blargg, HQ2x filter by MaxSt, and Scale2x filter
    - PPU now renders scanline 224
    - Revampled about box
    - Added Game Genie / PAR cheat code support + editor, saves codes to .cht files
    - HDMA channels are no longer disabled when starting DMA, fixes Dracula X [DMV27]
    - Fixes to OAM priority mode (not perfect), fixes Final Fantasy: Mystic Quest [DMV27]
    - Fixed ENDX sound bug, fixes voices in Earthworm Jim 2 [DMV27]
    - bsnes should now compile with MinGW [DMV27]
    - Added DSP-2 support
    - Added OBC-1 support
    - Major rewrite of SNES address bus mirroring and MMIO handlers
    - Many address mirroring corrections, fixes Dezaemon, etc
    - Blocked invalid (H)DMA transfers, fixes Kirby's Super Funhouse
    - Wrote Win32 API wrapper and ported all GUI code to use it, should help to create Linux GUI later on
    - Revampled input system, should lead to customizable GUI shortcut keys later on
    - Fixed numerous bugs with input registers. Fixes many games that previous had their intro cut off (Super Conflict, etc), and many that never accepted input (Super Double Dragon, etc)
    - Moved auto joypad strobing from V=225 to V=227
    - Killed OAM table caching and window range caching, as they were actually hindering speed
    - Rewrote input configuration screen to show currently mapped keys
    - Greatly enhanced configuration options for each video profile
    - Modified fullscreen mode to exit to windowed mode when menu is activated, use F11 to toggle fullscreen mode
    - Fixed bugs in txs, wai, brk, cop, and rti opcodes [DMV27]
    - Fixed bug with emulation-mode IRQs [DMV27]
    - Initializing DMA registers to $ff [DMV27]
    - Memory writes now update CPU MDR register (open bus) [DMV27]
    - Improved ROM header detection, fixes Chou Jikuu Yousai Macross [DMV27]
    - Reading OAM no longer updates OAM latch
    - Writing to OAM high table no longer updates OAM latch
    - Writing CGRAM now updates CGRAM latch
    - Improved pseudo-hires rendering [blargg]
    - Much, much more
2006-04-25 15:51:10 +00:00
byuu
6b6233b3af Update to bsnes v015 rc3 release.
[No changelog available]
2006-04-22 01:02:32 +00:00
byuu
9f63cb1b99 Update to bsnes v015 rc2 release.
[No changelog available]
2006-04-20 00:26:54 +00:00
byuu
49c39e0e4d Update to bsnes v015 release.
- Added GZ / ZIP / JMA archive support [Nach, NSRT team]
    - Fixed bug in APU ADDW/SUBW opcode flags, thanks to DMV27, anomymous for info
    - Mosaic support is now (mostly) hardware accurate, thanks to TRAC for info
    - Fixed a bug in SC tilemap clipping, fixes Seiken Densetsu 3
    - Emulated pseudo-hires mode, uses a fairly poor color filter to simulate TV effect, the same one that SNES9x and Super Sleuth use
    - Rewrote the ROM loading code to be more port-friendly, and improved header detection
    - Added C4 emulation -- mostly correct. Only minor bugs remain, possibly not C4 related [Nach, byuu], also uses code from zsKnight, Overload, and anomie
    - Fixed noise channel generation for DSP, fixes Dual Orb 2 opening. Thanks to DMV27 for info
    - Fixed bug with DSP VxSRCN registers, fixes horrible sound corruption in Mortal Kombat 2/3
    - Modified DSP KON register reading to act according to anomie's research, while still allowing Der Langrisser, etc. to play sounds correctly
    - Fixed a bug in CPU BCD math, fixes numbers in SimEarth, thanks to DMV27 for info
    - Rewrote the windows port from scratch
    - -- Added triple buffering support (buggy)
    - -- Added DirectInput (joypad) support, allows both keyboard and joypad to be mapped to the same SNES controller button. Only one controller supported for this release, will be improved shortly
    - -- Added pause key (mapped to Pause/Break)
    - -- bsnes no longer consumes CPU time when paused or when no ROM is loaded
    - -- Updated DirectDraw to 7, and added video mode configuration options to configuration file
    - -- Video modes can specify screen width+height, refresh rate, and render width+height
    - -- Added CTRL+[1-0] hotkeys for swapping video modes
    - -- Added +/- hotkeys for adjusting frameskipping rate
    - -- Added adjustable speed regulation. There are five modes, all can be adjusted inside the configuration file. CTRL+[+/-] will adjust the speed mode.
    - -- Added PPU options to toggle any BG / OAM layers with any priority, HDMA effects, and offset per tile effects
    - -- Added option to accept invalid button combinations (up+down, left+right) to joypad config menu
    - -- bsnes now properly clears the main window when unloading games
    - [code] Made destructors for base classes virtual, so the correct destructors will be called now
2005-12-03 21:05:52 +00:00
byuu
7dec0b2a3c Update to bsnes v014 release.
This version adds speed regulation, greatly improves PPU rendering, and increases speed by ~30% over the previous version.
Changelog:
    - Rewrote offset-per-tile mode emulation, should be correct now. Fixes Chrono Trigger, Contra III, Tetris Attack, etc.
    - Fixed a bug with HDMA occuring during interrupts. Fixes Tales of Phantasia souond test screen
    - Updated compiler to Visual Studio 2005, and enabled profile guided optimizations
    - Added conditional compilation of debugging functions (faster without them)
    - Added conditional compilation of core classes as pointers (allowing polymorphism) or objects (allowing inlining). The latter results in a speed increase
    - Small fixes to BG and OAM rendering routines
    - Corrected sprite tile bounds wrapping
    - Corrected sprite rendering in hires video modes
    - Rewrote color add/sub routines, should be correct now. Fixes Illusion of Gaia menu, etc.
    - Optimized video blitting routines, will temporarilly break mixed video mode screenshots
    - Prevented selecting menu options via return key from being recognized as keypresses by the emulator
    - Added system speed regulation (60hz/NTSC or 50hz/PAL)! Many thanks to kode54, GIGO, and Richard Bannister for their assistance
I disabled the debugger and polymorphism, and enabled profile guided optimizations for this build, to maximize speed. The debugger and polymorphism can be re-enabled via uncommenting the respective #defines in src/base.h and recompiling, or bsnes v0.013 can be used. I may start releasing two separate builds in the future... not sure yet.
2005-11-12 16:49:26 +00:00
byuu
f288280ceb Update to bsnes v013r02 release.
[No changelog available]
2005-10-25 23:25:28 +00:00
byuu
c6c5f4669c Update to bsnes v013 release.
- Greatly improved HDMA timing and accuracy with help from anomie and DMV27 -- fixes bugs in Energy Breaker and Street Fighter Alpha 2
    - Fixed a problem with color add/sub code -- fixes opening battle in Tales of Phantasia and clouds in Energy Breaker
    - Temporarily added DMV27's bugfix for the DSP KON register -- fixes sound in Der Langrisser, but this is not a hardware-accurate fix
    - Disabled VRAM writes outside of vblank -- fixes Hook, but breaks many PD ROMs and fan translations (Roto's BS Zelda hack, Gideon Zhi's Ys 4 translation, etc). I might add an option in the future to toggle this behavior, but for now these games will no longer work. Please keep in mind these games will not run properly on real SNES hardware, either.
    - Improved frameskipping code thanks to a suggestion from Richard Bannister
    - Misc. other code cleanups and improvements (notably in the color table generation code)
    - bsnes is now endian-safe and runs on Mac OS X
    - Added caching support for window clipping tables resulting in a slight speedup. Please let me know if you spot any errors as a result of this change.
2005-10-23 23:32:30 +00:00
byuu
397b9c4505 Update to bsnes v012 release.
Changelog:
    - Added S-DSP emulation
    - Added sound output support via DirectSound -- no sound buffering though, so sound is muted by default
    - Added option to record raw sound output to WAV files
    - Added multiple color adjustment filters to the video output
    - Added mode3/4 direct color support
    - Added mode7 direct color and mosaic support
    - Greatly improved mode7 rendering algorithm thanks to anomie
    - Fixed mode7 screen repitition and EXTBG effects
    - Greatly increased accuracy of NMI and IRQ timing, and emulated many newly discovered hardware quirks involving the two
    - A few speed improvements courtesy of Nach for profiling the code for me
I'm now looking for assistance with sound buffering. Specifically, I need help modifying the DirectSound code to allow the emulator to be ran between 50%-400% normal speed, while keeping the sound output relatively good. If you have experience with this and can help, please get in touch with me (setsunakun0 at hotmail dot com).
2005-10-02 00:38:34 +00:00
byuu
7e2cfb6d40 Update to bsnes v011 release.
- Fixed Mode 0 color palette index problem. Fixes ToP, DQ5, etc.
    - Improved LoROM memory mapper to support 32mbit images. Fixes Tokimeki Memorial, etc.
    - Added full S-DD1 support, SFA2 and Star Ocean are now playable. Special thanks to Andreas Naive
    - Updated BGnxOFS / Mode7 registers with anomie's latest findings
    - Added basic ROM mirroring support. Fixes copy protection issues in MMX, etc.
    - Rewrote string library to work better on gcc/linux
    - Cleaned up S-RTC/S-DD1 emulation to make way for future add-on chip emulation
    - Rewrote DMA code, now runs cycle-by-cycle
    - Rewrote HDMA code, now allows HDMA to be enabled mid-frame, fixes many games
    - Fixed a bug in Mode7 vertical screen flip mode. Fixes FF5 title screen, etc.
    - Greatly improved IRQ triggering. Fixes Der Langrisser, etc.
    - Added full support for open bus. This includes PPU1 and PPU2 open bus support
    - Modified CPU core back to cycle-based system. Slower, but improves debugger
    - Implemented temporary fix for debugger to handle new cycle-based cores
    - Modified CGRAM to ignore highest bit, since it is not used at all by the SNES, and is impossible to read on real hardware. Lowers memory usage by ~1.2mb
    - Added mostly accurate PAL timing support. This should increase compatibility by ~30% or so
    - More stuff I'm forgetting at the moment...
2005-08-26 20:38:00 +00:00
byuu
970dcea0ac Update to bsnes v010 release.
bsnes now supports SPC700 emulation (no DSP or sound support, however), and has greatly improved compatibility. It also now contains a keyboard-only joypad configuration tool.
2005-08-03 21:22:42 +00:00
byuu
402c146a53 Update to bsnes v009 release.
- Fixed non-interlaced display modes from not drawing every other frame
    - Changed OAM halve to skip every other scanline in 224-height modes
    - Updated renderer to properly support games that switch resolutions mid-frame
    - Fixed VRAM address remapping modes, fixes DQ3R, FF: MQ
    - Fixed a bug in main color window clipping affecting BGs
    - Added video color curve option, thanks to Overload for the idea + color table
    - Added vblank, FPS counter, and DDraw surface memory options to settings menu
    - Added fullscreen modes 640x480 and 1024x768 to video modes
    - Added option to toggle the menubar on and off by pressing the escape key
    - Mode3 was not rendering sprites
    - Priorities were wrong for modes 2-4, thanks to anomie for info
    - Fixed a serious bug in IRQ interrupts. May not be perfect, but helps many games
2005-06-26 11:07:38 +00:00
429 changed files with 69791 additions and 16711 deletions

View File

@@ -1,27 +0,0 @@
#[bsnes v0.007a configuration file]
#[video mode]
# 0: 256x224w
# 1: 512x448w
# 2: 960x720w
video.mode = 1
#[video memory type]
# true: video ram (VRAM)
# false: system ram (SRAM)
#
# VRAM results in the image being stretched in hardware,
# which is generally much faster, and automatically adds
# bilinear filtering (if the card supports it).
#
# However, some video cards end up taking a major speed
# loss when this option is enabled. It is also the only
# way to guarantee that the output image will not be
# filtered.
video.use_vram = true
#video.use_vram = false
#[show fps]
# true: show fps in titlebar
# false: do not show fps in titlebar
#gui.show_fps = false

Binary file not shown.

View File

@@ -1,10 +0,0 @@
bsnes Licensing Agreement:
You are free to redistribute this software, and its source code; provided
there is no charge for the software, nor any charge for the medium used to
distribute the software. You are also free to use and modify the source code
as you desire for personal use only. No publically-released derivative works
of this source code are permitted without my permission. You must also abide
by the terms of any additional source code licenses contained within my code.
At present, this only includes the mode7 renderer, which was derived from the
snes9x mode7 renderer.

View File

@@ -1,16 +1,71 @@
#include "lib/libbase.h"
#define BSNES_VERSION "0.018"
#define BSNES_TITLE "bsnes v" BSNES_VERSION
//structs
typedef struct {
uint8 *data;
uint32 size;
}lfile;
#define MEMCORE bMemBus
#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
//enable JMA support
#define JMA_SUPPORT
//snes core polymorphism
//(allow runtime cpu/smp/dsp/ppu/bus selection, ~10% speed hit)
//#define POLYMORPHISM
#if defined(PROCESSOR_X86)
#define ARCH_LSB
#elif defined(PROCESSOR_X86_64)
#define ARCH_LSB
#elif defined(PROCESSOR_G5)
#define ARCH_MSB
#else
#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"
inline uint16 read16(uint8 *addr, uint pos) {
#ifdef ARCH_LSB
return *((uint16*)(addr + pos));
#else
return (addr[pos]) | (addr[pos + 1] << 8);
#endif
}
//platform-specific global functions
void *memalloc(uint32 size, char *name = 0, ...);
void memfree(void *mem, char *name = 0, ...);
void alert(char *s, ...);
void dprintf(char *s, ...);
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"

418
src/cart/cart.cpp Normal file
View File

@@ -0,0 +1,418 @@
#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() {
info.srtc = false;
info.sdd1 = false;
info.c4 = false;
info.dsp1 = false;
info.dsp2 = false;
info.obc1 = false;
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[info.header_index + MAPPER];
uint8 rom_type = rom[info.header_index + ROM_TYPE];
if(mapper == 0x35 && rom_type == 0x55) {
info.srtc = true;
}
if(mapper == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
info.sdd1 = true;
}
if(mapper == 0x20 && rom_type == 0xf3) {
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) {
info.dsp2 = true;
}
if(mapper == 0x30 && rom_type == 0x25) {
info.obc1 = true;
}
info.cart_mmio = info.c4 | info.dsp1 | info.dsp2 | info.obc1;
if(rom[info.header_index + SRAM_SIZE] & 7) {
info.ram_size = 1024 << (rom[info.header_index + SRAM_SIZE] & 7);
} else {
info.ram_size = 0;
}
memcpy(&info.name, &rom[info.header_index + CART_NAME], 21);
info.name[21] = 0;
for(int i = 0; i < 22; i++) {
if(info.name[i] & 0x80) {
info.name[i] = '?';
}
}
}
void Cartridge::find_header() {
int32 score_lo = 0,
score_hi = 0,
score_ex = 0;
if(info.rom_size < 0x010000) {
//cart too small to be anything but lorom
info.header_index = 0x007fc0;
return;
}
if((rom[0x7fc0 + MAPPER] & ~0x10) == 0x20)score_lo++;
if((rom[0xffc0 + MAPPER] & ~0x10) == 0x21)score_hi++;
if(rom[0x7fc0 + ROM_TYPE] < 0x08)score_lo++;
if(rom[0xffc0 + ROM_TYPE] < 0x08)score_hi++;
if(rom[0x7fc0 + ROM_SIZE] < 0x10)score_lo++;
if(rom[0xffc0 + ROM_SIZE] < 0x10)score_hi++;
if(rom[0x7fc0 + SRAM_SIZE] < 0x08)score_lo++;
if(rom[0xffc0 + SRAM_SIZE] < 0x08)score_hi++;
if(rom[0x7fc0 + REGION] < 14)score_lo++;
if(rom[0xffc0 + REGION] < 14)score_hi++;
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);
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
score_lo += 8;
}
cksum = rom[0xffc0 + CKSUM] | (rom[0xffc0 + CKSUM + 1] << 8);
icksum = rom[0xffc0 + ICKSUM] | (rom[0xffc0 + ICKSUM + 1] << 8);
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
score_hi += 8;
}
if(info.rom_size < 0x401000) {
score_ex = 0;
} else {
if(rom[0x7fc0 + MAPPER] == 0x32)score_lo++;
else score_ex += 16;
}
if(score_lo >= score_hi && score_lo >= score_ex) {
info.header_index = 0x007fc0;
} else if(score_hi >= score_ex) {
info.header_index = 0x00ffc0;
} else {
info.header_index = 0x40ffc0;
}
}
void Cartridge::load_sram() {
if(info.ram_size == 0) {
sram = 0;
return;
}
FileReader ff(sram_fn);
if(!ff.ready()) {
sram = (uint8*)malloc(info.ram_size);
memset(sram, 0xff, info.ram_size);
return;
}
sram = ff.read(info.ram_size);
}
void Cartridge::save_sram() {
if(info.ram_size == 0)return;
FileWriter ff(sram_fn);
if(!ff.ready())return;
ff.write(sram, info.ram_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);
}
uint8 *base_rom = rf.read(info.rom_size + (header ? 512 : 0));
if(header) {
memcpy(rom_header, base_rom, 512);
} else {
memset(rom_header, 0x00, 512);
}
rom = (uint8*)malloc(info.rom_size);
memcpy(rom, base_rom + (header ? 512 : 0), info.rom_size);
SafeFree(base_rom);
info.crc32 = 0xffffffff;
for(int32 i = 0; i < info.rom_size; i++) {
info.crc32 = crc32_adjust(info.crc32, rom[i]);
}
info.crc32 = ~info.crc32;
}
void Cartridge::patch_rom(Reader &rf) {
UPS<ramfile, ramfile, ramfile> ups;
uint patchsize = rf.size();
uint8 *patchdata = rf.read();
fopen(ups.original, 0, file::mode_writeread);
fopen(ups.modified, 0, file::mode_writeread);
fopen(ups.patch.fp, 0, file::mode_writeread);
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);
}
}
bool Cartridge::load(const char *fn) {
if(cart_loaded == true)return false;
if(strlen(fn) < 3)return false;
dprintf("* Loading \"%s\"...", 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(ff);
} break;
#ifdef GZIP_SUPPORT
case Reader::RF_GZ: {
GZReader gf(rom_fn);
if(!gf.ready()) {
alert("Error loading image file (%s)!", rom_fn);
return false;
}
load_rom(gf);
} break;
case Reader::RF_ZIP: {
ZipReader zf(rom_fn);
load_rom(zf);
} break;
#endif
#ifdef JMA_SUPPORT
case Reader::RF_JMA: {
try {
JMAReader jf(rom_fn);
load_rom(jf);
} catch(JMA::jma_errors jma_error) {
alert("Error loading image file (%s)!", rom_fn);
return false;
}
} break;
#endif
}
//remove ROM extension
strcpy(sram_fn, fn);
for(int i = strlen(fn) - 1; i >= 0; i--) {
if(sram_fn[i] == '.') {
sram_fn[i] = 0;
break;
}
}
//add SRAM extension
strcat(sram_fn, ".");
strcat(sram_fn, config::fs.save_ext.sget());
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, save_path);
//append fs.base_path if fs.sram_path is not fully-qualified path
if(strbegin(new_fn, "./") == true) {
strltrim(new_fn, "./");
strcpy(new_fn[1], new_fn[0]);
strcpy(new_fn[0], config::fs.base_path.sget());
strcat(new_fn[0], new_fn[1]);
}
//finally, append SRAM file name
strcat(new_fn, parts[count(parts) - 1]);
strcpy(sram_fn, strptr(new_fn));
}
//load cheat file if it exists
strcpy(cheat_fn, sram_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(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();
}
load_sram();
cart_loaded = true;
r_mem->load_cart();
return true;
}
bool Cartridge::unload() {
if(cart_loaded == false)return false;
r_mem->unload_cart();
if(sram) { save_sram(); }
SafeFree(rom);
SafeFree(sram);
if(cheat.count() > 0 || fexists(cheat_fn)) {
FileWriter ff(cheat_fn);
cheat.save(ff);
cheat.clear();
}
cart_loaded = false;
return true;
}
Cartridge::Cartridge() {
load_database();
cart_loaded = false;
rom = 0;
sram = 0;
}
Cartridge::~Cartridge() {
if(cart_loaded == true) {
unload();
}
}

96
src/cart/cart.h Normal file
View File

@@ -0,0 +1,96 @@
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 rom_header[512], *rom, *sram;
enum {
//header fields
CART_NAME = 0x00,
MAPPER = 0x15,
ROM_TYPE = 0x16,
ROM_SIZE = 0x17,
SRAM_SIZE = 0x18,
REGION = 0x19,
LICENSE = 0x1a,
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;
char name[128];
char pcb[32];
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
bool cart_mmio;
bool srtc;
bool sdd1;
bool c4;
bool dsp1;
bool dsp2;
bool obc1;
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; }
bool load(const char *fn);
bool unload();
Cartridge();
~Cartridge();
};
extern Cartridge cartridge;

37
src/cart/database.cpp Normal file
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;
}

BIN
src/cart/db/cart.db Normal file

Binary file not shown.

47
src/cart/db/cartdb.txt Normal file
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
src/cart/db/cc.bat Normal file
View File

@@ -0,0 +1,3 @@
cl /nologo /O2 dbcreate.cpp
@pause
@del *.obj

1
src/cart/db/clean.bat Normal file
View File

@@ -0,0 +1 @@
@del *.exe

2
src/cart/db/create.bat Normal file
View File

@@ -0,0 +1,2 @@
dbcreate
@copy cart.db ..\..\..\cart.db

47
src/cart/db/db.h Normal file
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
src/cart/db/dbcreate.cpp Normal file
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;
}

336
src/cheat/cheat.cpp Normal file
View File

@@ -0,0 +1,336 @@
#include "../base.h"
Cheat cheat;
/*****
* string <> binary code translation routines
* decode() "7e1234:56" -> 0x7e123456
* encode() 0x7e123456 -> "7e1234:56"
*****/
bool Cheat::decode(char *str, uint32 &addr, uint8 &data, uint8 &type) {
stringarray t, part;
strcpy(t, str);
strlower(t);
if(strlen(t) == 8 || (strlen(t) == 9 && strptr(t)[6] == ':')) {
type = CT_PRO_ACTION_REPLAY;
replace(t, ":", "");
uint32 r = strhex(t);
addr = r >> 8;
data = r & 0xff;
return true;
} else if(strlen(t) == 9 && strptr(t)[4] == '-') {
type = CT_GAME_GENIE;
replace(t, "-", "");
strtr(t, "df4709156bc8a23e", "0123456789abcdef");
uint32 r = strhex(t);
//8421 8421 8421 8421 8421 8421
//abcd efgh ijkl mnop qrst uvwx
//ijkl qrst opab cduv wxef ghmn
addr = (!!(r & 0x002000) << 23) | (!!(r & 0x001000) << 22) |
(!!(r & 0x000800) << 21) | (!!(r & 0x000400) << 20) |
(!!(r & 0x000020) << 19) | (!!(r & 0x000010) << 18) |
(!!(r & 0x000008) << 17) | (!!(r & 0x000004) << 16) |
(!!(r & 0x800000) << 15) | (!!(r & 0x400000) << 14) |
(!!(r & 0x200000) << 13) | (!!(r & 0x100000) << 12) |
(!!(r & 0x000002) << 11) | (!!(r & 0x000001) << 10) |
(!!(r & 0x008000) << 9) | (!!(r & 0x004000) << 8) |
(!!(r & 0x080000) << 7) | (!!(r & 0x040000) << 6) |
(!!(r & 0x020000) << 5) | (!!(r & 0x010000) << 4) |
(!!(r & 0x000200) << 3) | (!!(r & 0x000100) << 2) |
(!!(r & 0x000080) << 1) | (!!(r & 0x000040) << 0);
data = r >> 24;
return true;
}
return false;
}
bool Cheat::encode(char *str, uint32 addr, uint8 data, uint8 type) {
if(type == CT_PRO_ACTION_REPLAY) {
sprintf(str, "%0.6x:%0.2x", addr, data);
return true;
} else if(type == CT_GAME_GENIE) {
uint32 r = addr;
addr = (!!(r & 0x008000) << 23) | (!!(r & 0x004000) << 22) |
(!!(r & 0x002000) << 21) | (!!(r & 0x001000) << 20) |
(!!(r & 0x000080) << 19) | (!!(r & 0x000040) << 18) |
(!!(r & 0x000020) << 17) | (!!(r & 0x000010) << 16) |
(!!(r & 0x000200) << 15) | (!!(r & 0x000100) << 14) |
(!!(r & 0x800000) << 13) | (!!(r & 0x400000) << 12) |
(!!(r & 0x200000) << 11) | (!!(r & 0x100000) << 10) |
(!!(r & 0x000008) << 9) | (!!(r & 0x000004) << 8) |
(!!(r & 0x000002) << 7) | (!!(r & 0x000001) << 6) |
(!!(r & 0x080000) << 5) | (!!(r & 0x040000) << 4) |
(!!(r & 0x020000) << 3) | (!!(r & 0x010000) << 2) |
(!!(r & 0x000800) << 1) | (!!(r & 0x000400) << 0);
sprintf(str, "%0.2x%0.2x-%0.4x", data, addr >> 16, addr & 0xffff);
strtr(str, "0123456789abcdef", "df4709156bc8a23e");
return true;
}
return false;
}
/*****
* address lookup table manipulation and mirroring
* mirror_address() 0x000000 -> 0x7e0000
* set() enable specified address, mirror accordingly
* clear() disable specified address, mirror accordingly
*****/
uint Cheat::mirror_address(uint addr) {
if((addr & 0x40e000) != 0x0000)return addr;
//8k WRAM mirror
//$[00-3f|80-bf]:[0000-1fff] -> $7e:[0000-1fff]
return (0x7e0000 + (addr & 0x1fff));
}
void Cheat::set(uint32 addr) {
addr = mirror_address(addr);
mask[addr >> 3] |= 1 << (addr & 7);
if((addr & 0xffe000) == 0x7e0000) {
//mirror $7e:[0000-1fff] to $[00-3f|80-bf]:[0000-1fff]
uint mirror;
for(int x = 0; x <= 0x3f; x++) {
mirror = ((0x00 + x) << 16) + (addr & 0x1fff);
mask[mirror >> 3] |= 1 << (mirror & 7);
mirror = ((0x80 + x) << 16) + (addr & 0x1fff);
mask[mirror >> 3] |= 1 << (mirror & 7);
}
}
}
void Cheat::clear(uint32 addr) {
addr = mirror_address(addr);
//is there more than one cheat code using the same address
//(and likely a different override value) that is enabled?
//if so, do not clear code lookup table entry for this address.
uint8 r;
if(read(addr, r) == true)return;
mask[addr >> 3] &= ~(1 << (addr & 7));
if((addr & 0xffe000) == 0x7e0000) {
//mirror $7e:[0000-1fff] to $[00-3f|80-bf]:[0000-1fff]
uint mirror;
for(int x = 0; x <= 0x3f; x++) {
mirror = ((0x00 + x) << 16) + (addr & 0x1fff);
mask[mirror >> 3] &= ~(1 << (mirror & 7));
mirror = ((0x80 + x) << 16) + (addr & 0x1fff);
mask[mirror >> 3] &= ~(1 << (mirror & 7));
}
}
}
/*****
* read() is used by MemBus::read() if Cheat::enabled(addr)
* returns true to look up cheat code.
* returns true if cheat code was found, false if it was not.
* when true, cheat code substitution value is stored in data.
*****/
bool Cheat::read(uint32 addr, uint8 &data) {
addr = mirror_address(addr);
for(int i = 0; i < cheat_count; i++) {
if(enabled(i) == false)continue;
if(addr == mirror_address(index[i].addr)) {
data = index[i].data;
return true;
}
}
//code not found, or code is disabled
return false;
}
/*****
* update_cheat_status() will scan to see if any codes are
* enabled. if any are, make sure the cheat system is on.
* otherwise, turn cheat system off to speed up emulation.
*****/
void Cheat::update_cheat_status() {
for(int i = 0; i < cheat_count; i++) {
if(index[i].enabled) {
cheat_enabled = true;
return;
}
}
cheat_enabled = false;
}
/*****
* cheat list manipulation routines
*****/
bool Cheat::add(bool enable, char *code, char *desc) {
if(cheat_count >= CHEAT_LIMIT)return false;
uint32 addr, len;
uint8 data, type;
if(decode(code, addr, data, type) == false)return false;
index[cheat_count].enabled = enable;
index[cheat_count].addr = addr;
index[cheat_count].data = data;
len = strlen(code);
len = len > 16 ? 16 : len;
memcpy(index[cheat_count].code, code, len);
index[cheat_count].code[len] = 0;
len = strlen(desc);
len = len > 128 ? 128 : len;
memcpy(index[cheat_count].desc, desc, len);
index[cheat_count].desc[len] = 0;
cheat_count++;
(enable) ? set(addr) : clear(addr);
update_cheat_status();
return true;
}
bool Cheat::edit(uint32 n, bool enable, char *code, char *desc) {
if(n >= cheat_count)return false;
uint32 addr, len;
uint8 data, type;
if(decode(code, addr, data, type) == false)return false;
//disable current code and clear from code lookup table
index[n].enabled = false;
clear(index[n].addr);
//update code and enable in code lookup table
index[n].enabled = enable;
index[n].addr = addr;
index[n].data = data;
len = strlen(code);
len = len > 16 ? 16 : len;
memcpy(index[n].code, code, len);
index[n].code[len] = 0;
len = strlen(desc);
len = len > 128 ? 128 : len;
memcpy(index[n].desc, desc, len);
index[n].desc[len] = 0;
set(addr);
update_cheat_status();
return true;
}
bool Cheat::remove(uint32 n) {
if(n >= cheat_count)return false;
for(int i = n; i < cheat_count; i++) {
index[i].enabled = index[i + 1].enabled;
index[i].addr = index[i + 1].addr;
index[i].data = index[i + 1].data;
strcpy(index[i].desc, index[i + 1].desc);
}
cheat_count--;
update_cheat_status();
return true;
}
bool Cheat::get(uint32 n, bool &enable, uint32 &addr, uint8 &data, char *code, char *desc) {
if(n >= cheat_count)return false;
enable = index[n].enabled;
addr = index[n].addr;
data = index[n].data;
strcpy(code, index[n].code);
strcpy(desc, index[n].desc);
return true;
}
/*****
* code status modifier routines
*****/
bool Cheat::enabled(uint32 n) {
if(n >= cheat_count)return false;
return index[n].enabled;
}
void Cheat::enable(uint32 n) {
if(n >= cheat_count)return;
index[n].enabled = true;
set(index[n].addr);
update_cheat_status();
}
void Cheat::disable(uint32 n) {
if(n >= cheat_count)return;
index[n].enabled = false;
clear(index[n].addr);
update_cheat_status();
}
/*****
* cheat file manipulation routines
*****/
bool Cheat::load(Reader &rf) {
if(!rf.ready())return false;
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");
split(line, "\n", data);
for(int i = 0; i < ::count(line); i++) {
stringarray part;
uint8 en = *(strptr(line[i]));
if(en == '+') {
strltrim(line[i], "+");
} else if(en == '-') {
strltrim(line[i], "-");
} else {
continue;
}
qreplace(line[i], " ", "");
qsplit(part, ",", line[i]);
if(::count(part) != 2)continue;
strunquote(part[1]);
add(en == '+', strptr(part[0]), strptr(part[1]));
}
return true;
}
bool Cheat::save(Writer &wf) {
if(!wf.ready())return false;
string data;
char t[4096];
strcpy(data, "");
for(int i = 0; i < cheat_count; i++) {
sprintf(t, "%c%s, \"%s\"\r\n", index[i].enabled ? '+' : '-', index[i].code, index[i].desc);
strcat(data, t);
}
wf.write((uint8*)strptr(data), strlen(data));
return true;
}
/*****
* initialization routines
*****/
void Cheat::clear() {
cheat_enabled = false;
cheat_count = 0;
memset(mask, 0, 0x200000);
for(int i = 0; i < CHEAT_LIMIT + 1; i++) {
index[i].enabled = false;
index[i].addr = 0x000000;
index[i].data = 0x00;
strcpy(index[i].code, "");
strcpy(index[i].desc, "");
}
}
Cheat::Cheat() {
clear();
}

48
src/cheat/cheat.h Normal file
View File

@@ -0,0 +1,48 @@
#define CHEAT_LIMIT 1024
class Cheat {
public:
enum { CT_PRO_ACTION_REPLAY, CT_GAME_GENIE };
struct CheatIndex {
bool enabled;
uint32 addr;
uint8 data;
char code[ 16 + 1];
char desc[128 + 1];
} index[CHEAT_LIMIT + 1];
bool cheat_enabled;
uint32 cheat_count;
uint8 mask[0x200000];
inline bool enabled() { return cheat_enabled; }
inline uint count() { return cheat_count; }
inline bool exists(uint32 addr) { return bool(mask[addr >> 3] & 1 << (addr & 7)); }
bool decode(char *str, uint32 &addr, uint8 &data, uint8 &type);
bool encode(char *str, uint32 addr, uint8 data, uint8 type);
private:
uint mirror_address(uint addr);
void set(uint32 addr);
void clear(uint32 addr);
public:
bool read(uint32 addr, uint8 &data);
void update_cheat_status();
bool add(bool enable, char *code, char *desc);
bool edit(uint32 n, bool enable, char *code, char *desc);
bool get(uint32 n, bool &enable, uint32 &addr, uint8 &data, char *code, char *desc);
bool remove (uint32 n);
bool enabled(uint32 n);
void enable (uint32 n);
void disable(uint32 n);
bool load(Reader &rf);
bool save(Writer &wf);
void clear();
Cheat();
};
extern Cheat cheat;

199
src/chip/c4/c4.cpp Normal file
View File

@@ -0,0 +1,199 @@
/*
C4 emulation
Used in Rockman X2/X3 (Megaman X2/X3)
Portions (c) anomie, Overload, zsKnight, Nach, byuu
*/
#include "../../base.h"
C4 *c4;
#include "c4data.cpp"
#include "c4fn.cpp"
#include "c4oam.cpp"
#include "c4ops.cpp"
void C4::init() {}
void C4::enable() {}
uint32 C4::ldr(uint8 r) {
uint16 addr = 0x0080 + (r * 3);
return (reg[addr]) | (reg[addr + 1] << 8) | (reg[addr + 2] << 16);
}
void C4::str(uint8 r, uint32 data) {
uint16 addr = 0x0080 + (r * 3);
reg[addr ] = (data);
reg[addr + 1] = (data >> 8);
reg[addr + 2] = (data >> 16);
}
void C4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) {
int64 rx = x & 0xffffff;
int64 ry = y & 0xffffff;
if(rx & 0x800000)rx |= ~0x7fffff;
if(ry & 0x800000)ry |= ~0x7fffff;
rx *= ry;
rl = (rx) & 0xffffff;
rh = (rx >> 24) & 0xffffff;
}
uint32 C4::sin(uint32 rx) {
r0 = rx & 0x1ff;
if(r0 & 0x100)r0 ^= 0x1ff;
if(r0 & 0x080)r0 ^= 0x0ff;
if(rx & 0x100) {
return sin_table[r0 + 0x80];
} else {
return sin_table[r0];
}
}
uint32 C4::cos(uint32 rx) {
return sin(rx + 0x080);
}
void C4::immediate_reg(uint32 start) {
r0 = ldr(0);
for(uint32 i=start;i<48;i++) {
if((r0 & 0x0fff) < 0x0c00) {
ram[r0 & 0x0fff] = immediate_data[i];
}
r0++;
}
str(0, r0);
}
void C4::transfer_data() {
uint32 src;
uint16 dest, count;
src = (reg[0x40]) | (reg[0x41] << 8) | (reg[0x42] << 16);
count = (reg[0x43]) | (reg[0x44] << 8);
dest = (reg[0x45]) | (reg[0x46] << 8);
for(uint32 i=0;i<count;i++) {
write(dest++, r_mem->read(src++));
}
}
void C4::write(uint16 addr, uint8 data) {
addr &= 0x1fff;
if(addr < 0x0c00) {
//ram
ram[addr] = data;
return;
}
if(addr < 0x1f00) {
//unmapped
return;
}
//command register
reg[addr & 0xff] = data;
if(addr == 0x1f47) {
//memory transfer
transfer_data();
return;
}
if(addr == 0x1f4f) {
//c4 command
if(reg[0x4d] == 0x0e && !(data & 0xc3)) {
//c4 test command
reg[0x80] = data >> 2;
return;
}
switch(data) {
case 0x00:op00();break;
case 0x01:op01();break;
case 0x05:op05();break;
case 0x0d:op0d();break;
case 0x10:op10();break;
case 0x13:op13();break;
case 0x15:op15();break;
case 0x1f:op1f();break;
case 0x22:op22();break;
case 0x25:op25();break;
case 0x2d:op2d();break;
case 0x40:op40();break;
case 0x54:op54();break;
case 0x5c:op5c();break;
case 0x5e:op5e();break;
case 0x60:op60();break;
case 0x62:op62();break;
case 0x64:op64();break;
case 0x66:op66();break;
case 0x68:op68();break;
case 0x6a:op6a();break;
case 0x6c:op6c();break;
case 0x6e:op6e();break;
case 0x70:op70();break;
case 0x72:op72();break;
case 0x74:op74();break;
case 0x76:op76();break;
case 0x78:op78();break;
case 0x7a:op7a();break;
case 0x7c:op7c();break;
case 0x89:op89();break;
}
}
}
void C4::writeb(uint16 addr, uint8 data) {
write(addr, data);
}
void C4::writew(uint16 addr, uint16 data) {
write(addr, data);
write(addr + 1, data >> 8);
}
void C4::writel(uint16 addr, uint32 data) {
write(addr, data);
write(addr + 1, data >> 8);
write(addr + 2, data >> 16);
}
uint8 C4::read(uint16 addr) {
addr &= 0x1fff;
if(addr < 0x0c00) {
return ram[addr];
}
if(addr >= 0x1f00) {
return reg[addr & 0xff];
}
return r_cpu->regs.mdr;
}
uint8 C4::readb(uint16 addr) {
return read(addr);
}
uint16 C4::readw(uint16 addr) {
return read(addr) | (read(addr + 1) << 8);
}
uint32 C4::readl(uint16 addr) {
return read(addr) | (read(addr + 1) << 8) + (read(addr + 2) << 16);
}
void C4::power() {
reset();
}
void C4::reset() {
memset(ram, 0, 0x0c00);
memset(reg, 0, 0x0100);
}
C4::C4() {}

96
src/chip/c4/c4.h Normal file
View File

@@ -0,0 +1,96 @@
class C4 {
private:
uint8 ram[0x0c00];
uint8 reg[0x0100];
uint32 r0, r1, r2, r3, r4, r5, r6, r7,
r8, r9, r10, r11, r12, r13, r14, r15;
static const uint8 immediate_data[48];
static const uint16 wave_data[40];
static const uint32 sin_table[256];
static const int16 SinTable[512];
static const int16 CosTable[512];
int16 C4WFXVal, C4WFYVal, C4WFZVal, C4WFX2Val, C4WFY2Val, C4WFDist, C4WFScale;
int16 C41FXVal, C41FYVal, C41FAngleRes, C41FDist, C41FDistVal;
double tanval;
double c4x,c4y,c4z, c4x2,c4y2,c4z2;
void C4TransfWireFrame();
void C4TransfWireFrame2();
void C4CalcWireFrame();
void C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color);
void C4DrawWireFrame();
void C4DoScaleRotate(int row_padding);
public:
uint32 ldr(uint8 r);
void str(uint8 r, uint32 data);
void mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh);
uint32 sin(uint32 rx);
uint32 cos(uint32 rx);
void transfer_data();
void immediate_reg(uint32 num);
void op00_00();
void op00_03();
void op00_05();
void op00_07();
void op00_08();
void op00_0b();
void op00_0c();
void op00();
void op01();
void op05();
void op0d();
void op10();
void op13();
void op15();
void op1f();
void op22();
void op25();
void op2d();
void op40();
void op54();
void op5c();
void op5e();
void op60();
void op62();
void op64();
void op66();
void op68();
void op6a();
void op6c();
void op6e();
void op70();
void op72();
void op74();
void op76();
void op78();
void op7a();
void op7c();
void op89();
void init();
void enable();
void power();
void reset();
void write (uint16 addr, uint8 data);
void writeb(uint16 addr, uint8 data);
void writew(uint16 addr, uint16 data);
void writel(uint16 addr, uint32 data);
uint8 read (uint16 addr);
uint8 readb(uint16 addr);
uint16 readw(uint16 addr);
uint32 readl(uint16 addr);
C4();
};
extern C4 *c4;

183
src/chip/c4/c4data.cpp Normal file
View File

@@ -0,0 +1,183 @@
const uint8 C4::immediate_data[48] = {
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x80, 0xff, 0xff, 0x7f,
0x00, 0x80, 0x00, 0xff, 0x7f, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0xff,
0x00, 0x00, 0x01, 0xff, 0xff, 0xfe, 0x00, 0x01, 0x00, 0xff, 0xfe, 0x00
};
const uint16 C4::wave_data[40] = {
0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e,
0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020a, 0x020c, 0x020e,
0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040a, 0x040c, 0x040e,
0x0600, 0x0602, 0x0604, 0x0606, 0x0608, 0x060a, 0x060c, 0x060e,
0x0800, 0x0802, 0x0804, 0x0806, 0x0808, 0x080a, 0x080c, 0x080e
};
const uint32 C4::sin_table[256] = {
0x000000, 0x000324, 0x000648, 0x00096c, 0x000c8f, 0x000fb2, 0x0012d5, 0x0015f6,
0x001917, 0x001c37, 0x001f56, 0x002273, 0x002590, 0x0028aa, 0x002bc4, 0x002edb,
0x0031f1, 0x003505, 0x003817, 0x003b26, 0x003e33, 0x00413e, 0x004447, 0x00474d,
0x004a50, 0x004d50, 0x00504d, 0x005347, 0x00563e, 0x005931, 0x005c22, 0x005f0e,
0x0061f7, 0x0064dc, 0x0067bd, 0x006a9b, 0x006d74, 0x007049, 0x007319, 0x0075e5,
0x0078ad, 0x007b70, 0x007e2e, 0x0080e7, 0x00839c, 0x00864b, 0x0088f5, 0x008b9a,
0x008e39, 0x0090d3, 0x009368, 0x0095f6, 0x00987f, 0x009b02, 0x009d7f, 0x009ff6,
0x00a267, 0x00a4d2, 0x00a736, 0x00a994, 0x00abeb, 0x00ae3b, 0x00b085, 0x00b2c8,
0x00b504, 0x00b73a, 0x00b968, 0x00bb8f, 0x00bdae, 0x00bfc7, 0x00c1d8, 0x00c3e2,
0x00c5e4, 0x00c7de, 0x00c9d1, 0x00cbbb, 0x00cd9f, 0x00cf7a, 0x00d14d, 0x00d318,
0x00d4db, 0x00d695, 0x00d848, 0x00d9f2, 0x00db94, 0x00dd2d, 0x00debe, 0x00e046,
0x00e1c5, 0x00e33c, 0x00e4aa, 0x00e60f, 0x00e76b, 0x00e8bf, 0x00ea09, 0x00eb4b,
0x00ec83, 0x00edb2, 0x00eed8, 0x00eff5, 0x00f109, 0x00f213, 0x00f314, 0x00f40b,
0x00f4fa, 0x00f5de, 0x00f6ba, 0x00f78b, 0x00f853, 0x00f912, 0x00f9c7, 0x00fa73,
0x00fb14, 0x00fbac, 0x00fc3b, 0x00fcbf, 0x00fd3a, 0x00fdab, 0x00fe13, 0x00fe70,
0x00fec4, 0x00ff0e, 0x00ff4e, 0x00ff84, 0x00ffb1, 0x00ffd3, 0x00ffec, 0x00fffb,
0x000000, 0xfffcdb, 0xfff9b7, 0xfff693, 0xfff370, 0xfff04d, 0xffed2a, 0xffea09,
0xffe6e8, 0xffe3c8, 0xffe0a9, 0xffdd8c, 0xffda6f, 0xffd755, 0xffd43b, 0xffd124,
0xffce0e, 0xffcafa, 0xffc7e8, 0xffc4d9, 0xffc1cc, 0xffbec1, 0xffbbb8, 0xffb8b2,
0xffb5af, 0xffb2af, 0xffafb2, 0xffacb8, 0xffa9c1, 0xffa6ce, 0xffa3dd, 0xffa0f1,
0xff9e08, 0xff9b23, 0xff9842, 0xff9564, 0xff928b, 0xff8fb6, 0xff8ce6, 0xff8a1a,
0xff8752, 0xff848f, 0xff81d1, 0xff7f18, 0xff7c63, 0xff79b4, 0xff770a, 0xff7465,
0xff71c6, 0xff6f2c, 0xff6c97, 0xff6a09, 0xff6780, 0xff64fd, 0xff6280, 0xff6009,
0xff5d98, 0xff5b2d, 0xff58c9, 0xff566b, 0xff5414, 0xff51c4, 0xff4f7a, 0xff4d37,
0xff4afb, 0xff48c5, 0xff4697, 0xff4470, 0xff4251, 0xff4038, 0xff3e27, 0xff3c1e,
0xff3a1b, 0xff3821, 0xff362e, 0xff3444, 0xff3260, 0xff3085, 0xff2eb2, 0xff2ce7,
0xff2b24, 0xff296a, 0xff27b7, 0xff260d, 0xff246b, 0xff22d2, 0xff2141, 0xff1fb9,
0xff1e3a, 0xff1cc3, 0xff1b55, 0xff19f0, 0xff1894, 0xff1740, 0xff15f6, 0xff14b4,
0xff137c, 0xff124d, 0xff1127, 0xff100a, 0xff0ef6, 0xff0dec, 0xff0ceb, 0xff0bf4,
0xff0b05, 0xff0a21, 0xff0945, 0xff0874, 0xff07ac, 0xff06ed, 0xff0638, 0xff058d,
0xff04eb, 0xff0453, 0xff03c4, 0xff0340, 0xff02c5, 0xff0254, 0xff01ec, 0xff018f,
0xff013b, 0xff00f1, 0xff00b1, 0xff007b, 0xff004e, 0xff002c, 0xff0013, 0xff0004
};
const int16 C4::SinTable[512] = {
0, 402, 804, 1206, 1607, 2009, 2410, 2811,
3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997,
6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126,
9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167,
12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090,
15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869,
18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475,
20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884,
23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073,
25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020,
27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707,
28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117,
30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237,
31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057,
32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568,
32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765,
32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647,
32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214,
32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471,
31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425,
30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086,
28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466,
27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583,
25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453,
23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097,
20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537,
18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800,
15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910,
12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896,
9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786,
6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611,
3211, 2811, 2410, 2009, 1607, 1206, 804, 402,
0, -402, -804, -1206, -1607, -2009, -2410, -2811,
-3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997,
-6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126,
-9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167,
-12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090,
-15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869,
-18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475,
-20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884,
-23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073,
-25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020,
-27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707,
-28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117,
-30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237,
-31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057,
-32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568,
-32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765,
-32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647,
-32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214,
-32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471,
-31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425,
-30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086,
-28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466,
-27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583,
-25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453,
-23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097,
-20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537,
-18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800,
-15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910,
-12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896,
-9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786,
-6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611,
-3211, -2811, -2410, -2009, -1607, -1206, -804, -402
};
const int16 C4::CosTable[512] = {
32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647,
32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214,
32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471,
31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425,
30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086,
28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466,
27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583,
25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453,
23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097,
20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537,
18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800,
15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910,
12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896,
9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786,
6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611,
3211, 2811, 2410, 2009, 1607, 1206, 804, 402,
0, -402, -804, -1206, -1607, -2009, -2410, -2811,
-3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997,
-6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126,
-9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167,
-12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090,
-15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869,
-18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475,
-20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884,
-23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073,
-25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020,
-27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707,
-28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117,
-30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237,
-31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057,
-32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568,
-32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765,
-32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647,
-32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214,
-32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471,
-31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425,
-30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086,
-28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466,
-27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583,
-25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453,
-23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097,
-20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537,
-18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800,
-15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910,
-12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896,
-9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786,
-6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611,
-3211, -2811, -2410, -2009, -1607, -1206, -804, -402,
0, 402, 804, 1206, 1607, 2009, 2410, 2811,
3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997,
6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126,
9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167,
12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090,
15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869,
18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475,
20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884,
23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073,
25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020,
27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707,
28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117,
30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237,
31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057,
32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568,
32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765
};

242
src/chip/c4/c4fn.cpp Normal file
View File

@@ -0,0 +1,242 @@
#include <math.h>
#define Tan(a) (CosTable[a] ? ((((int32)SinTable[a]) << 16) / CosTable[a]) : 0x80000000)
#define sar(b, n) ((b) >> (n))
#ifdef PI
#undef PI
#endif
#define PI 3.1415926535897932384626433832795
//Wireframe Helpers
void C4::C4TransfWireFrame() {
c4x = (double)C4WFXVal;
c4y = (double)C4WFYVal;
c4z = (double)C4WFZVal - 0x95;
//Rotate X
tanval = -(double)C4WFX2Val * PI * 2 / 128;
c4y2 = c4y * ::cos(tanval) - c4z * ::sin(tanval);
c4z2 = c4y * ::sin(tanval) + c4z * ::cos(tanval);
//Rotate Y
tanval = -(double)C4WFY2Val * PI * 2 / 128;
c4x2 = c4x * ::cos(tanval) + c4z2 * ::sin(tanval);
c4z = c4x * -::sin(tanval) + c4z2 * ::cos(tanval);
//Rotate Z
tanval = -(double)C4WFDist * PI * 2 / 128;
c4x = c4x2 * ::cos(tanval) - c4y2 * ::sin(tanval);
c4y = c4x2 * ::sin(tanval) + c4y2 * ::cos(tanval);
//Scale
C4WFXVal = (int16)(c4x * C4WFScale / (0x90 * (c4z + 0x95)) * 0x95);
C4WFYVal = (int16)(c4y * C4WFScale / (0x90 * (c4z + 0x95)) * 0x95);
}
void C4::C4CalcWireFrame() {
C4WFXVal = C4WFX2Val - C4WFXVal;
C4WFYVal = C4WFY2Val - C4WFYVal;
if(abs(C4WFXVal) > abs(C4WFYVal)) {
C4WFDist = abs(C4WFXVal) + 1;
C4WFYVal = (256 * (long)C4WFYVal) / abs(C4WFXVal);
C4WFXVal = (C4WFXVal < 0) ? -256 : 256;
} else if(C4WFYVal != 0) {
C4WFDist = abs(C4WFYVal) + 1;
C4WFXVal = (256 * (long)C4WFXVal) / abs(C4WFYVal);
C4WFYVal = (C4WFYVal < 0) ? -256 : 256;
} else {
C4WFDist = 0;
}
}
void C4::C4TransfWireFrame2() {
c4x = (double)C4WFXVal;
c4y = (double)C4WFYVal;
c4z = (double)C4WFZVal;
//Rotate X
tanval = -(double)C4WFX2Val * PI * 2 / 128;
c4y2 = c4y * ::cos(tanval) - c4z * ::sin(tanval);
c4z2 = c4y * ::sin(tanval) + c4z * ::cos(tanval);
//Rotate Y
tanval = -(double)C4WFY2Val * PI * 2 / 128;
c4x2 = c4x * ::cos(tanval) + c4z2 * ::sin(tanval);
c4z = c4x * -::sin(tanval) + c4z2 * ::cos(tanval);
//Rotate Z
tanval = -(double)C4WFDist * PI * 2 / 128;
c4x = c4x2 * ::cos(tanval) - c4y2 * ::sin(tanval);
c4y = c4x2 * ::sin(tanval) + c4y2 * ::cos(tanval);
//Scale
C4WFXVal = (int16)(c4x * C4WFScale / 0x100);
C4WFYVal = (int16)(c4y * C4WFScale / 0x100);
}
void C4::C4DrawWireFrame() {
uint32 line = readl(0x1f80);
uint32 point1, point2;
int16 X1, Y1, Z1;
int16 X2, Y2, Z2;
uint8 Color;
for(int32 i = ram[0x0295]; i > 0; i--, line += 5) {
if(r_mem->read(line) == 0xff && r_mem->read(line + 1) == 0xff) {
int32 tmp = line - 5;
while(r_mem->read(tmp + 2) == 0xff && r_mem->read(tmp + 3) == 0xff && (tmp + 2) >= 0) { tmp -= 5; }
point1 = (read(0x1f82) << 16) | (r_mem->read(tmp + 2) << 8) | r_mem->read(tmp + 3);
} else {
point1 = (read(0x1f82) << 16) | (r_mem->read(line) << 8) | r_mem->read(line + 1);
}
point2 = (read(0x1f82) << 16) | (r_mem->read(line + 2) << 8) | r_mem->read(line + 3);
X1=(r_mem->read(point1 + 0) << 8) | r_mem->read(point1 + 1);
Y1=(r_mem->read(point1 + 2) << 8) | r_mem->read(point1 + 3);
Z1=(r_mem->read(point1 + 4) << 8) | r_mem->read(point1 + 5);
X2=(r_mem->read(point2 + 0) << 8) | r_mem->read(point2 + 1);
Y2=(r_mem->read(point2 + 2) << 8) | r_mem->read(point2 + 3);
Z2=(r_mem->read(point2 + 4) << 8) | r_mem->read(point2 + 5);
Color = r_mem->read(line + 4);
C4DrawLine(X1, Y1, Z1, X2, Y2, Z2, Color);
}
}
void C4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color) {
//Transform coordinates
C4WFXVal = (int16)X1;
C4WFYVal = (int16)Y1;
C4WFZVal = Z1;
C4WFScale = read(0x1f90);
C4WFX2Val = read(0x1f86);
C4WFY2Val = read(0x1f87);
C4WFDist = read(0x1f88);
C4TransfWireFrame2();
X1 = (C4WFXVal + 48) << 8;
Y1 = (C4WFYVal + 48) << 8;
C4WFXVal = (int16)X2;
C4WFYVal = (int16)Y2;
C4WFZVal = Z2;
C4TransfWireFrame2();
X2 = (C4WFXVal + 48) << 8;
Y2 = (C4WFYVal + 48) << 8;
//Get line info
C4WFXVal = (int16)(X1 >> 8);
C4WFYVal = (int16)(Y1 >> 8);
C4WFX2Val = (int16)(X2 >> 8);
C4WFY2Val = (int16)(Y2 >> 8);
C4CalcWireFrame();
X2 = (int16)C4WFXVal;
Y2 = (int16)C4WFYVal;
//Render line
for(int32 i = C4WFDist ? C4WFDist : 1; i > 0; i--) {
if(X1 > 0xff && Y1 > 0xff && X1 < 0x6000 && Y1 < 0x6000) {
uint16 addr = (((Y1 >> 8) >> 3) << 8) - (((Y1 >> 8) >> 3) << 6) + (((X1 >> 8) >> 3) << 4) + ((Y1 >> 8) & 7) * 2;
uint8 bit = 0x80 >> ((X1 >> 8) & 7);
ram[addr + 0x300] &= ~bit;
ram[addr + 0x301] &= ~bit;
if(Color & 1) { ram[addr + 0x300] |= bit; }
if(Color & 2) { ram[addr + 0x301] |= bit; }
}
X1 += X2;
Y1 += Y2;
}
}
void C4::C4DoScaleRotate(int row_padding) {
int16 A, B, C, D;
//Calculate matrix
int32 XScale = readw(0x1f8f);
int32 YScale = readw(0x1f92);
if(XScale & 0x8000)XScale = 0x7fff;
if(YScale & 0x8000)YScale = 0x7fff;
if(readw(0x1f80) == 0) { //no rotation
A = (int16)XScale;
B = 0;
C = 0;
D = (int16)YScale;
} else if(readw(0x1f80) == 128) { //90 degree rotation
A = 0;
B = (int16)(-YScale);
C = (int16)XScale;
D = 0;
} else if(readw(0x1f80) == 256) { //180 degree rotation
A = (int16)(-XScale);
B = 0;
C = 0;
D = (int16)(-YScale);
} else if(readw(0x1f80) == 384) { //270 degree rotation
A = 0;
B = (int16)YScale;
C = (int16)(-XScale);
D = 0;
} else {
A = (int16) sar(CosTable[readw(0x1f80) & 0x1ff] * XScale, 15);
B = (int16)(-sar(SinTable[readw(0x1f80) & 0x1ff] * YScale, 15));
C = (int16) sar(SinTable[readw(0x1f80) & 0x1ff] * XScale, 15);
D = (int16) sar(CosTable[readw(0x1f80) & 0x1ff] * YScale, 15);
}
//Calculate Pixel Resolution
uint8 w = read(0x1f89) & ~7;
uint8 h = read(0x1f8c) & ~7;
//Clear the output RAM
memset(ram, 0, (w + row_padding / 4) * h / 2);
int32 Cx = (int16)readw(0x1f83);
int32 Cy = (int16)readw(0x1f86);
//Calculate start position (i.e. (Ox, Oy) = (0, 0))
//The low 12 bits are fractional, so (Cx<<12) gives us the Cx we want in
//the function. We do Cx*A etc normally because the matrix parameters
//already have the fractional parts.
int32 LineX = (Cx << 12) - Cx * A - Cx * B;
int32 LineY = (Cy << 12) - Cy * C - Cy * D;
//Start loop
uint32 X, Y;
uint8 byte;
int32 outidx = 0;
uint8 bit = 0x80;
for(int32 y = 0; y < h; y++) {
X = LineX;
Y = LineY;
for(int32 x = 0; x < w; x++) {
if((X >> 12) >= w || (Y >> 12) >= h) {
byte = 0;
} else {
uint32 addr = (Y >> 12) * w + (X >> 12);
byte = read(0x600 + (addr >> 1));
if(addr & 1) { byte >>= 4; }
}
//De-bitplanify
if(byte & 1) { ram[outidx ] |= bit; }
if(byte & 2) { ram[outidx + 1] |= bit; }
if(byte & 4) { ram[outidx + 16] |= bit; }
if(byte & 8) { ram[outidx + 17] |= bit; }
bit >>= 1;
if(!bit) {
bit = 0x80;
outidx += 32;
}
X += A; //Add 1 to output x => add an A and a C
Y += C;
}
outidx += 2 + row_padding;
if(outidx & 0x10) {
outidx &= ~0x10;
} else {
outidx -= w * 4 + row_padding;
}
LineX += B; //Add 1 to output y => add a B and a D
LineY += D;
}
}

219
src/chip/c4/c4oam.cpp Normal file
View File

@@ -0,0 +1,219 @@
//Build OAM
void C4::op00_00() {
uint32 oamptr = ram[0x626] << 2;
for(int32 i = 0x1fd; i > oamptr && i >= 0; i -= 4) {
//clear oam-to-be
if(i >= 0)ram[i] = 0xe0;
}
uint16 globalx, globaly;
uint32 oamptr2;
int16 sprx, spry;
uint8 sprname, sprattr;
uint8 sprcount;
globalx = readw(0x621);
globaly = readw(0x623);
oamptr2 = 0x200 + (ram[0x626] >> 2);
if(!ram[0x620])return;
sprcount = 128 - ram[0x626];
uint8 offset = (ram[0x626] & 3) * 2;
uint32 srcptr = 0x220;
for(int i = ram[0x620]; i > 0 && sprcount > 0; i--, srcptr += 16) {
sprx = readw(srcptr) - globalx;
spry = readw(srcptr + 2) - globaly;
sprname = ram[srcptr + 5];
sprattr = ram[srcptr + 4] | ram[srcptr + 6];
uint32 spraddr = readl(srcptr + 7);
if(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);
}
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++;
}
}
}
//Scale and Rotate
void C4::op00_03() {
C4DoScaleRotate(0);
}
//Transform Lines
void C4::op00_05() {
C4WFX2Val = read(0x1f83);
C4WFY2Val = read(0x1f86);
C4WFDist = read(0x1f89);
C4WFScale = read(0x1f8c);
//Transform Vertices
uint32 ptr = 0;
for(int32 i = readw(0x1f80); i > 0; i--, ptr += 0x10) {
C4WFXVal = readw(ptr + 1);
C4WFYVal = readw(ptr + 5);
C4WFZVal = readw(ptr + 9);
C4TransfWireFrame();
//Displace
writew(ptr + 1, C4WFXVal + 0x80);
writew(ptr + 5, C4WFYVal + 0x50);
}
writew(0x600, 23);
writew(0x602, 0x60);
writew(0x605, 0x40);
writew(0x600 + 8, 23);
writew(0x602 + 8, 0x60);
writew(0x605 + 8, 0x40);
ptr = 0xb02;
uint32 ptr2 = 0;
for(int32 i = readw(0xb00); i > 0; i--, ptr += 2, ptr2 += 8) {
C4WFXVal = readw((read(ptr + 0) << 4) + 1);
C4WFYVal = readw((read(ptr + 0) << 4) + 5);
C4WFX2Val = readw((read(ptr + 1) << 4) + 1);
C4WFY2Val = readw((read(ptr + 1) << 4) + 5);
C4CalcWireFrame();
writew(ptr2 + 0x600, C4WFDist ? C4WFDist : 1);
writew(ptr2 + 0x602, C4WFXVal);
writew(ptr2 + 0x605, C4WFYVal);
}
}
//Scale and Rotate
void C4::op00_07() {
C4DoScaleRotate(64);
}
//Draw Wireframe
void C4::op00_08() {
C4DrawWireFrame();
}
//Disintegrate
void C4::op00_0b() {
uint8 width, height;
uint32 startx, starty;
uint32 srcptr;
uint32 x, y;
int32 scalex, scaley;
int32 cx, cy;
int32 i, j;
width = read(0x1f89);
height = read(0x1f8c);
cx = readw(0x1f80);
cy = readw(0x1f83);
scalex = (int16)readw(0x1f86);
scaley = (int16)readw(0x1f8f);
startx = -cx * scalex + (cx << 8);
starty = -cy * scaley + (cy << 8);
srcptr = 0x600;
for(i = 0; i < (width * height) >> 1; i++) {
write(i, 0);
}
for(y = starty, i = 0;i < height; i++, y += scaley) {
for(x = startx, j = 0;j < width; j++, x += scalex) {
if((x >> 8) < width && (y >> 8) < height && (y >> 8) * width + (x >> 8) < 0x2000) {
uint8 pixel = (j & 1) ? (ram[srcptr] >> 4) : (ram[srcptr]);
int32 index = (y >> 11) * width * 4 + (x >> 11) * 32 + ((y >> 8) & 7) * 2;
uint8 mask = 0x80 >> ((x >> 8) & 7);
if(pixel & 1)ram[index ] |= mask;
if(pixel & 2)ram[index + 1] |= mask;
if(pixel & 4)ram[index + 16] |= mask;
if(pixel & 8)ram[index + 17] |= mask;
}
if(j & 1)srcptr++;
}
}
}
//Bitplane Wave
void C4::op00_0c() {
uint32 destptr = 0;
uint32 waveptr = read(0x1f83);
uint16 mask1 = 0xc0c0;
uint16 mask2 = 0x3f3f;
for(int j = 0; j < 0x10; j++) {
do {
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
for(int i = 0; i < 40; i++) {
uint16 temp = readw(destptr + wave_data[i]) & mask2;
if(height >= 0) {
if(height < 8) {
temp |= mask1 & readw(0xa00 + height * 2);
} else {
temp |= mask1 & 0xff00;
}
}
writew(destptr + wave_data[i], temp);
height++;
}
waveptr = (waveptr + 1) & 0x7f;
mask1 = (mask1 >> 2) | (mask1 << 6);
mask2 = (mask2 >> 2) | (mask2 << 6);
} while(mask1 != 0xc0c0);
destptr += 16;
do {
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
for(int i = 0; i < 40; i++) {
uint16 temp = readw(destptr + wave_data[i]) & mask2;
if(height >= 0) {
if(height < 8) {
temp |= mask1 & readw(0xa10 + height * 2);
} else {
temp |= mask1 & 0xff00;
}
}
writew(destptr + wave_data[i], temp);
height++;
}
waveptr = (waveptr + 1) & 0x7f;
mask1 = (mask1 >> 2) | (mask1 << 6);
mask2 = (mask2 >> 2) | (mask2 << 6);
} while(mask1 != 0xc0c0);
destptr += 16;
}
}

222
src/chip/c4/c4ops.cpp Normal file
View File

@@ -0,0 +1,222 @@
//Sprite Functions
void C4::op00() {
switch(reg[0x4d]) {
case 0x00:op00_00();break;
case 0x03:op00_03();break;
case 0x05:op00_05();break;
case 0x07:op00_07();break;
case 0x08:op00_08();break;
case 0x0b:op00_0b();break;
case 0x0c:op00_0c();break;
}
}
//Draw Wireframe
void C4::op01() {
memset(ram + 0x300, 0, 2304);
C4DrawWireFrame();
}
//Propulsion
void C4::op05() {
int32 temp = 0x10000;
if(readw(0x1f83)) {
temp = sar((temp / readw(0x1f83)) * readw(0x1f81), 8);
}
writew(0x1f80, temp);
}
//Set Vector length
void C4::op0d() {
C41FXVal = readw(0x1f80);
C41FYVal = readw(0x1f83);
C41FDistVal = readw(0x1f86);
tanval = sqrt(((double)C41FYVal) * ((double)C41FYVal) + ((double)C41FXVal) * ((double)C41FXVal));
tanval = (double)C41FDistVal / tanval;
C41FYVal = (int16)(((double)C41FYVal * tanval) * 0.99);
C41FXVal = (int16)(((double)C41FXVal * tanval) * 0.98);
writew(0x1f89, C41FXVal);
writew(0x1f8c, C41FYVal);
}
//Triangle
void C4::op10() {
r0 = ldr(0);
r1 = ldr(1);
r4 = r0 & 0x1ff;
if(r1 & 0x8000)r1 |= ~0x7fff;
mul(cos(r4), r1, r5, r2);
r5 = (r5 >> 16) & 0xff;
r2 = (r2 << 8) + r5;
mul(sin(r4), r1, r5, r3);
r5 = (r5 >> 16) & 0xff;
r3 = (r3 << 8) + r5;
str(0, r0);
str(1, r1);
str(2, r2);
str(3, r3);
str(4, r4);
str(5, r5);
}
//Triangle
void C4::op13() {
r0 = ldr(0);
r1 = ldr(1);
r4 = r0 & 0x1ff;
mul(cos(r4), r1, r5, r2);
r5 = (r5 >> 8) & 0xffff;
r2 = (r2 << 16) + r5;
mul(sin(r4), r1, r5, r3);
r5 = (r5 >> 8) & 0xffff;
r3 = (r3 << 16) + r5;
str(0, r0);
str(1, r1);
str(2, r2);
str(3, r3);
str(4, r4);
str(5, r5);
}
//Pythagorean
void C4::op15() {
C41FXVal = readw(0x1f80);
C41FYVal = readw(0x1f83);
C41FDist = (int16)sqrt((double)C41FXVal * (double)C41FXVal + (double)C41FYVal * (double)C41FYVal);
writew(0x1f80, C41FDist);
}
//Calculate distance
void C4::op1f() {
C41FXVal = readw(0x1f80);
C41FYVal = readw(0x1f83);
if(!C41FXVal) {
C41FAngleRes = (C41FYVal > 0) ? 0x080 : 0x180;
} else {
tanval = ((double)C41FYVal) / ((double)C41FXVal);
C41FAngleRes = (short)(atan(tanval) / (PI * 2) * 512);
C41FAngleRes = C41FAngleRes;
if(C41FXVal < 0) {
C41FAngleRes += 0x100;
}
C41FAngleRes &= 0x1ff;
}
writew(0x1f86, C41FAngleRes);
}
//Trapezoid
void C4::op22() {
int16 angle1 = readw(0x1f8c) & 0x1ff;
int16 angle2 = readw(0x1f8f) & 0x1ff;
int32 tan1 = Tan(angle1);
int32 tan2 = Tan(angle2);
int16 y = readw(0x1f83) - readw(0x1f89);
int16 left, right;
for(int32 j = 0; j < 225; j++, y++) {
if(y >= 0) {
left = sar((int32)tan1 * y, 16) - readw(0x1f80) + readw(0x1f86);
right = sar((int32)tan2 * y, 16) - readw(0x1f80) + readw(0x1f86) + readw(0x1f93);
if(left < 0 && right < 0) {
left = 1;
right = 0;
} else if(left < 0) {
left = 0;
} else if(right < 0) {
right = 0;
}
if(left > 255 && right > 255) {
left = 255;
right = 254;
} else if(left > 255) {
left = 255;
} else if(right > 255) {
right = 255;
}
} else {
left = 1;
right = 0;
}
ram[j + 0x800] = (uint8)left;
ram[j + 0x900] = (uint8)right;
}
}
//Multiply
void C4::op25() {
r0 = ldr(0);
r1 = ldr(1);
mul(r0, r1, r0, r1);
str(0, r0);
str(1, r1);
}
//Transform Coords
void C4::op2d() {
C4WFXVal = readw(0x1f81);
C4WFYVal = readw(0x1f84);
C4WFZVal = readw(0x1f87);
C4WFX2Val = read (0x1f89);
C4WFY2Val = read (0x1f8a);
C4WFDist = read (0x1f8b);
C4WFScale = readw(0x1f90);
C4TransfWireFrame2();
writew(0x1f80, C4WFXVal);
writew(0x1f83, C4WFYVal);
}
//Sum
void C4::op40() {
r0 = 0;
for(uint32 i=0;i<0x800;i++) {
r0 += ram[i];
}
str(0, r0);
}
//Square
void C4::op54() {
r0 = ldr(0);
mul(r0, r0, r1, r2);
str(1, r1);
str(2, r2);
}
//Immediate Register
void C4::op5c() {
str(0, 0x000000);
immediate_reg(0);
}
//Immediate Register (Multiple)
void C4::op5e() { immediate_reg( 0); }
void C4::op60() { immediate_reg( 3); }
void C4::op62() { immediate_reg( 6); }
void C4::op64() { immediate_reg( 9); }
void C4::op66() { immediate_reg(12); }
void C4::op68() { immediate_reg(15); }
void C4::op6a() { immediate_reg(18); }
void C4::op6c() { immediate_reg(21); }
void C4::op6e() { immediate_reg(24); }
void C4::op70() { immediate_reg(27); }
void C4::op72() { immediate_reg(30); }
void C4::op74() { immediate_reg(33); }
void C4::op76() { immediate_reg(36); }
void C4::op78() { immediate_reg(39); }
void C4::op7a() { immediate_reg(42); }
void C4::op7c() { immediate_reg(45); }
//Immediate ROM
void C4::op89() {
str(0, 0x054336);
str(1, 0xffffff);
}

57
src/chip/dsp1/dsp1.cpp Normal file
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
src/chip/dsp1/dsp1.h Normal file
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;

1622
src/chip/dsp1/dsp1emu.cpp Normal file

File diff suppressed because it is too large Load Diff

127
src/chip/dsp1/dsp1emu.h Normal file
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

136
src/chip/dsp2/dsp2.cpp Normal file
View File

@@ -0,0 +1,136 @@
#include "../../base.h"
DSP2 *dsp2;
#include "dsp2_op.cpp"
void DSP2::init() {}
void DSP2::enable() {}
void DSP2::power() {
reset();
}
void DSP2::reset() {
status.waiting_for_command = true;
status.in_count = 0;
status.in_index = 0;
status.out_count = 0;
status.out_index = 0;
status.op05transparent = 0;
status.op05haslen = false;
status.op05len = 0;
status.op06haslen = false;
status.op06len = 0;
status.op09word1 = 0;
status.op09word2 = 0;
status.op0dhaslen = false;
status.op0doutlen = 0;
status.op0dinlen = 0;
}
uint8 DSP2::read(uint16 addr) {
uint8 r = 0xff;
if(status.out_count) {
r = status.output[status.out_index++];
status.out_index &= 511;
if(status.out_count == status.out_index) {
status.out_count = 0;
}
}
return r;
}
void DSP2::write(uint16 addr, uint8 data) {
if(status.waiting_for_command) {
status.command = data;
status.in_index = 0;
status.waiting_for_command = false;
switch(data) {
case 0x01: status.in_count = 32; break;
case 0x03: status.in_count = 1; break;
case 0x05: status.in_count = 1; break;
case 0x06: status.in_count = 1; break;
case 0x07: break;
case 0x08: break;
case 0x09: status.in_count = 4; break;
case 0x0d: status.in_count = 2; break;
case 0x0f: status.in_count = 0; break;
}
} else {
status.parameters[status.in_index++] = data;
status.in_index &= 511;
}
if(status.in_count == status.in_index) {
status.waiting_for_command = true;
status.out_index = 0;
switch(status.command) {
case 0x01: {
status.out_count = 32;
op01();
} break;
case 0x03: {
op03();
} break;
case 0x05: {
if(status.op05haslen) {
status.op05haslen = false;
status.out_count = status.op05len;
op05();
} else {
status.op05len = status.parameters[0];
status.in_index = 0;
status.in_count = status.op05len * 2;
status.op05haslen = true;
if(data)status.waiting_for_command = false;
}
} break;
case 0x06: {
if(status.op06haslen) {
status.op06haslen = false;
status.out_count = status.op06len;
op06();
} else {
status.op06len = status.parameters[0];
status.in_index = 0;
status.in_count = status.op06len;
status.op06haslen = true;
if(data)status.waiting_for_command = false;
}
} break;
case 0x07: break;
case 0x08: break;
case 0x09: {
op09();
} break;
case 0x0d: {
if(status.op0dhaslen) {
status.op0dhaslen = false;
status.out_count = status.op0doutlen;
op0d();
} else {
status.op0dinlen = status.parameters[0];
status.op0doutlen = status.parameters[1];
status.in_index = 0;
status.in_count = (status.op0dinlen + 1) >> 1;
status.op0dhaslen = true;
if(data)status.waiting_for_command = false;
}
} break;
case 0x0f: break;
}
}
}
DSP2::DSP2() {}
DSP2::~DSP2() {}

43
src/chip/dsp2/dsp2.h Normal file
View File

@@ -0,0 +1,43 @@
class DSP2 {
public:
struct {
bool waiting_for_command;
uint command;
uint in_count, in_index;
uint out_count, out_index;
uint8 parameters[512];
uint8 output[512];
uint8 op05transparent;
bool op05haslen;
int op05len;
bool op06haslen;
int op06len;
uint16 op09word1;
uint16 op09word2;
bool op0dhaslen;
int op0doutlen;
int op0dinlen;
} status;
void init();
void enable();
void power();
void reset();
void op01();
void op03();
void op05();
void op06();
void op09();
void op0d();
uint8 read (uint16 addr);
void write(uint16 addr, uint8 data);
DSP2();
~DSP2();
};
extern DSP2 *dsp2;

173
src/chip/dsp2/dsp2_op.cpp Normal file
View File

@@ -0,0 +1,173 @@
//convert bitmap to bitplane tile
void DSP2::op01() {
//op01 size is always 32 bytes input and output
//the hardware does strange things if you vary the size
unsigned char c0, c1, c2, c3;
unsigned char *p1 = status.parameters;
unsigned char *p2a = status.output;
unsigned char *p2b = status.output + 16; //halfway
//process 8 blocks of 4 bytes each
for(int j = 0; j < 8; j++) {
c0 = *p1++;
c1 = *p1++;
c2 = *p1++;
c3 = *p1++;
*p2a++ = (c0 & 0x10) << 3 |
(c0 & 0x01) << 6 |
(c1 & 0x10) << 1 |
(c1 & 0x01) << 4 |
(c2 & 0x10) >> 1 |
(c2 & 0x01) << 2 |
(c3 & 0x10) >> 3 |
(c3 & 0x01);
*p2a++ = (c0 & 0x20) << 2 |
(c0 & 0x02) << 5 |
(c1 & 0x20) |
(c1 & 0x02) << 3 |
(c2 & 0x20) >> 2 |
(c2 & 0x02) << 1 |
(c3 & 0x20) >> 4 |
(c3 & 0x02) >> 1;
*p2b++ = (c0 & 0x40) << 1 |
(c0 & 0x04) << 4 |
(c1 & 0x40) >> 1 |
(c1 & 0x04) << 2 |
(c2 & 0x40) >> 3 |
(c2 & 0x04) |
(c3 & 0x40) >> 5 |
(c3 & 0x04) >> 2;
*p2b++ = (c0 & 0x80) |
(c0 & 0x08) << 3 |
(c1 & 0x80) >> 2 |
(c1 & 0x08) << 1 |
(c2 & 0x80) >> 4 |
(c2 & 0x08) >> 1 |
(c3 & 0x80) >> 6 |
(c3 & 0x08) >> 3;
}
}
//set transparent color
void DSP2::op03() {
status.op05transparent = status.parameters[0];
}
//replace bitmap using transparent color
void DSP2::op05() {
uint8 color;
// Overlay bitmap with transparency.
// Input:
//
// Bitmap 1: i[0] <=> i[size-1]
// Bitmap 2: i[size] <=> i[2*size-1]
//
// Output:
//
// Bitmap 3: o[0] <=> o[size-1]
//
// Processing:
//
// Process all 4-bit pixels (nibbles) in the bitmap
//
// if ( BM2_pixel == transparent_color )
// pixelout = BM1_pixel
// else
// pixelout = BM2_pixel
// The max size bitmap is limited to 255 because the size parameter is a byte
// I think size=0 is an error. The behavior of the chip on size=0 is to
// return the last value written to DR if you read DR on Op05 with
// size = 0. I don't think it's worth implementing this quirk unless it's
// proven necessary.
unsigned char c1, c2;
unsigned char *p1 = status.parameters;
unsigned char *p2 = status.parameters + status.op05len;
unsigned char *p3 = status.output;
color = status.op05transparent & 0x0f;
for(int n = 0; n < status.op05len; n++) {
c1 = *p1++;
c2 = *p2++;
*p3++ = ( ((c2 >> 4) == color ) ? c1 & 0xf0 : c2 & 0xf0 ) |
( ((c2 & 0x0f) == color ) ? c1 & 0x0f : c2 & 0x0f );
}
}
//reverse bitmap
void DSP2::op06() {
// Input:
// size
// bitmap
int i, j;
for(i = 0, j = status.op06len - 1; i < status.op06len; i++, j--) {
status.output[j] = (status.parameters[i] << 4) | (status.parameters[i] >> 4);
}
}
//multiply
void DSP2::op09() {
status.out_count = 4;
status.op09word1 = status.parameters[0] | (status.parameters[1] << 8);
status.op09word2 = status.parameters[2] | (status.parameters[3] << 8);
uint32 r;
r = status.op09word1 * status.op09word2;
status.output[0] = r;
status.output[1] = r >> 8;
status.output[2] = r >> 16;
status.output[3] = r >> 24;
}
//scale bitmap
void DSP2::op0d() {
// Bit accurate hardware algorithm - uses fixed point math
// This should match the DSP2 Op0D output exactly
// I wouldn't recommend using this unless you're doing hardware debug.
// In some situations it has small visual artifacts that
// are not readily apparent on a TV screen but show up clearly
// on a monitor. Use Overload's scaling instead.
// This is for hardware verification testing.
//
// One note: the HW can do odd byte scaling but since we divide
// by two to get the count of bytes this won't work well for
// odd byte scaling (in any of the current algorithm implementations).
// So far I haven't seen Dungeon Master use it.
// If it does we can adjust the parameters and code to work with it
uint32 multiplier; // Any size int >= 32-bits
uint32 pixloc; // match size of multiplier
int i, j;
uint8 pixelarray[512];
if(status.op0dinlen <= status.op0doutlen) {
multiplier = 0x10000; // In our self defined fixed point 0x10000 == 1
} else {
multiplier = (status.op0dinlen << 17) / ((status.op0doutlen << 1) + 1);
}
pixloc = 0;
for(i = 0; i < status.op0doutlen * 2; i++) {
j = pixloc >> 16;
if(j & 1) {
pixelarray[i] = (status.parameters[j >> 1] & 0x0f);
} else {
pixelarray[i] = (status.parameters[j >> 1] & 0xf0) >> 4;
}
pixloc += multiplier;
}
for(i = 0; i < status.op0doutlen; i++) {
status.output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1];
}
}

90
src/chip/obc1/obc1.cpp Normal file
View File

@@ -0,0 +1,90 @@
#include "../../base.h"
OBC1 *obc1;
void OBC1::init() {}
void OBC1::enable() {}
void OBC1::power() {
reset();
}
void OBC1::reset() {
memset(cartridge.sram, 0xff, 0x2000);
status.baseptr = (cartridge.sram[0x1ff5] & 1) ? 0x1800 : 0x1c00;
status.address = (cartridge.sram[0x1ff6] & 0x7f);
status.shift = (cartridge.sram[0x1ff6] & 3) << 1;
}
uint8 OBC1::read(uint16 addr) {
addr &= 0x1fff;
if((addr & 0x1ff8) != 0x1ff0) {
return cartridge.sram[addr];
}
switch(addr) {
case 0x1ff0:
return cartridge.sram[status.baseptr + (status.address << 2) + 0];
case 0x1ff1:
return cartridge.sram[status.baseptr + (status.address << 2) + 1];
case 0x1ff2:
return cartridge.sram[status.baseptr + (status.address << 2) + 2];
case 0x1ff3:
return cartridge.sram[status.baseptr + (status.address << 2) + 3];
case 0x1ff4:
return cartridge.sram[status.baseptr + (status.address >> 2) + 0x200];
case 0x1ff5:
case 0x1ff6:
case 0x1ff7:
return cartridge.sram[addr];
}
//never used, blocks compiler warning
return 0x00;
}
void OBC1::write(uint16 addr, uint8 data) {
addr &= 0x1fff;
if((addr & 0x1ff8) != 0x1ff0) {
cartridge.sram[addr] = data;
return;
}
switch(addr) {
case 0x1ff0:
cartridge.sram[status.baseptr + (status.address << 2) + 0] = data;
break;
case 0x1ff1:
cartridge.sram[status.baseptr + (status.address << 2) + 1] = data;
break;
case 0x1ff2:
cartridge.sram[status.baseptr + (status.address << 2) + 2] = data;
break;
case 0x1ff3:
cartridge.sram[status.baseptr + (status.address << 2) + 3] = data;
break;
case 0x1ff4: {
uint8 temp;
temp = cartridge.sram[status.baseptr + (status.address >> 2) + 0x200];
temp = (temp & ~(3 << status.shift)) | ((data & 3) << status.shift);
cartridge.sram[status.baseptr + (status.address >> 2) + 0x200] = temp;
} break;
case 0x1ff5:
status.baseptr = (data & 1) ? 0x1800 : 0x1c00;
cartridge.sram[addr] = data;
break;
case 0x1ff6:
status.address = (data & 0x7f);
status.shift = (data & 3) << 1;
cartridge.sram[addr] = data;
break;
case 0x1ff7:
cartridge.sram[addr] = data;
break;
}
}
OBC1::OBC1() {}
OBC1::~OBC1() {}

20
src/chip/obc1/obc1.h Normal file
View File

@@ -0,0 +1,20 @@
class OBC1 {
public:
struct {
uint16 address;
uint16 baseptr;
uint16 shift;
} status;
void init();
void enable();
void power();
void reset();
uint8 read (uint16 addr);
void write(uint16 addr, uint8 data);
OBC1();
~OBC1();
};
extern OBC1 *obc1;

94
src/chip/sdd1/sdd1.cpp Normal file
View File

@@ -0,0 +1,94 @@
#include "../../base.h"
SDD1 *sdd1;
#include "sdd1emu.cpp"
void SDD1::init() {}
void SDD1::enable() {
for(int i = 0x4800; i <= 0x4807; i++) {
r_mem->set_mmio_mapper(i, this);
}
}
void SDD1::power() {
reset();
}
void SDD1::reset() {
sdd1.index[0] = 0x000000;
sdd1.index[1] = 0x100000;
sdd1.index[2] = 0x200000;
sdd1.index[3] = 0x300000;
for(int i=0;i<8;i++) {
sdd1.active[i] = false;
}
sdd1.dma_active = false;
}
uint32 SDD1::offset(uint32 addr) {
uint8 b = (addr >> 16) & 0xff;
if(b <= 0xbf)return 0;
b -= 0xc0; //b = 0x00-0x3f
b >>= 4; //b = 0-3
b &= 3; //bitmask
return sdd1.index[b] + (addr & 0x0fffff);
}
uint8 SDD1::mmio_read(uint16 addr) {
switch(addr) {
//>>20 == 0x100000 == 1mb
case 0x4804:return (sdd1.index[0] >> 20) & 7;
case 0x4805:return (sdd1.index[1] >> 20) & 7;
case 0x4806:return (sdd1.index[2] >> 20) & 7;
case 0x4807:return (sdd1.index[3] >> 20) & 7;
}
return r_cpu->regs.mdr;
}
void SDD1::mmio_write(uint16 addr, uint8 data) {
switch(addr) {
case 0x4801:
for(int i = 0; i < 8; i++) {
sdd1.active[i] = !!(data & (1 << i));
}
break;
//<<20 == 0x100000 == 1mb
case 0x4804:sdd1.index[0] = (data & 7) << 20;break;
case 0x4805:sdd1.index[1] = (data & 7) << 20;break;
case 0x4806:sdd1.index[2] = (data & 7) << 20;break;
case 0x4807:sdd1.index[3] = (data & 7) << 20;break;
}
}
void SDD1::dma_begin(uint8 channel, uint32 addr, uint16 length) {
if(sdd1.active[channel] == true) {
sdd1.active[channel] = false;
sdd1.dma_active = true;
sdd1.buffer_index = 0;
sdd1.buffer_size = length;
sdd1emu.decompress(addr, (length) ? length : 65536, sdd1.buffer);
}
}
bool SDD1::dma_active() {
return sdd1.dma_active;
}
uint8 SDD1::dma_read() {
if(--sdd1.buffer_size == 0) {
sdd1.dma_active = false;
}
//sdd1.buffer[] is 65536 bytes, and sdd1.buffer_index
//is of type uint16, so no buffer overflow is possible
return sdd1.buffer[sdd1.buffer_index++];
}
SDD1::SDD1() {}

32
src/chip/sdd1/sdd1.h Normal file
View File

@@ -0,0 +1,32 @@
#include "sdd1emu.h"
class SDD1 : public MMIO {
public:
SDD1emu sdd1emu;
struct {
uint32 index[4]; //memory mapping registers
uint8 buffer[65536]; //pointer to decompressed S-DD1 data,
//max. DMA length is 65536
uint16 buffer_index; //DMA read index into S-DD1 decompression buffer
uint16 buffer_size;
bool active[8]; //true when DMA channel should pass through S-DD1
bool dma_active;
} sdd1;
void init();
void enable();
void power();
void reset();
uint32 offset(uint32 addr);
void dma_begin(uint8 channel, uint32 addr, uint16 length);
bool dma_active();
uint8 dma_read();
uint8 mmio_read (uint16 addr);
void mmio_write(uint16 addr, uint8 data);
SDD1();
};
extern SDD1 *sdd1;

447
src/chip/sdd1/sdd1emu.cpp Normal file
View File

@@ -0,0 +1,447 @@
/************************************************************************
S-DD1'algorithm emulation code
------------------------------
Author: Andreas Naive
Date: August 2003
Last update: October 2004
This code is Public Domain. There is no copyright holded by the author.
Said this, the author wish to explicitly emphasize his inalienable moral rights
over this piece of intelectual work and the previous research that made it
possible, as recognized by most of the copyright laws around the world.
This code is provided 'as-is', with no warranty, expressed or implied.
No responsability is assumed by the author in connection with it.
The author is greatly indebted with The Dumper, without whose help and
patience providing him with real S-DD1 data the research would have never been
possible. He also wish to note that in the very beggining of his research,
Neviksti had done some steps in the right direction. By last, the author is
indirectly indebted to all the people that worked and contributed in the
S-DD1 issue in the past.
An algorithm's documentation is available as a separate document.
The implementation is obvious when the algorithm is
understood.
************************************************************************/
#define SDD1_read(__addr) (r_mem->read(__addr))
////////////////////////////////////////////////////
void SDD1_IM::prepareDecomp(uint32 in_buf) {
byte_ptr=in_buf;
bit_count=4;
}
////////////////////////////////////////////////////
uint8 SDD1_IM::getCodeword(uint8 code_len) {
uint8 codeword;
uint8 comp_count;
codeword = (SDD1_read(byte_ptr))<<bit_count;
++bit_count;
if (codeword & 0x80) {
codeword |= SDD1_read(byte_ptr+1)>>(9-bit_count);
bit_count+=code_len;
}
if (bit_count & 0x08) {
byte_ptr++;
bit_count&=0x07;
}
return codeword;
}
//////////////////////////////////////////////////////
SDD1_GCD::SDD1_GCD(SDD1_IM *associatedIM) :
IM(associatedIM)
{
}
//////////////////////////////////////////////////////
void SDD1_GCD::getRunCount(uint8 code_num, uint8 *MPScount, bool8 *LPSind) {
const uint8 run_count[] = {
0x00, 0x00, 0x01, 0x00, 0x03, 0x01, 0x02, 0x00,
0x07, 0x03, 0x05, 0x01, 0x06, 0x02, 0x04, 0x00,
0x0f, 0x07, 0x0b, 0x03, 0x0d, 0x05, 0x09, 0x01,
0x0e, 0x06, 0x0a, 0x02, 0x0c, 0x04, 0x08, 0x00,
0x1f, 0x0f, 0x17, 0x07, 0x1b, 0x0b, 0x13, 0x03,
0x1d, 0x0d, 0x15, 0x05, 0x19, 0x09, 0x11, 0x01,
0x1e, 0x0e, 0x16, 0x06, 0x1a, 0x0a, 0x12, 0x02,
0x1c, 0x0c, 0x14, 0x04, 0x18, 0x08, 0x10, 0x00,
0x3f, 0x1f, 0x2f, 0x0f, 0x37, 0x17, 0x27, 0x07,
0x3b, 0x1b, 0x2b, 0x0b, 0x33, 0x13, 0x23, 0x03,
0x3d, 0x1d, 0x2d, 0x0d, 0x35, 0x15, 0x25, 0x05,
0x39, 0x19, 0x29, 0x09, 0x31, 0x11, 0x21, 0x01,
0x3e, 0x1e, 0x2e, 0x0e, 0x36, 0x16, 0x26, 0x06,
0x3a, 0x1a, 0x2a, 0x0a, 0x32, 0x12, 0x22, 0x02,
0x3c, 0x1c, 0x2c, 0x0c, 0x34, 0x14, 0x24, 0x04,
0x38, 0x18, 0x28, 0x08, 0x30, 0x10, 0x20, 0x00,
0x7f, 0x3f, 0x5f, 0x1f, 0x6f, 0x2f, 0x4f, 0x0f,
0x77, 0x37, 0x57, 0x17, 0x67, 0x27, 0x47, 0x07,
0x7b, 0x3b, 0x5b, 0x1b, 0x6b, 0x2b, 0x4b, 0x0b,
0x73, 0x33, 0x53, 0x13, 0x63, 0x23, 0x43, 0x03,
0x7d, 0x3d, 0x5d, 0x1d, 0x6d, 0x2d, 0x4d, 0x0d,
0x75, 0x35, 0x55, 0x15, 0x65, 0x25, 0x45, 0x05,
0x79, 0x39, 0x59, 0x19, 0x69, 0x29, 0x49, 0x09,
0x71, 0x31, 0x51, 0x11, 0x61, 0x21, 0x41, 0x01,
0x7e, 0x3e, 0x5e, 0x1e, 0x6e, 0x2e, 0x4e, 0x0e,
0x76, 0x36, 0x56, 0x16, 0x66, 0x26, 0x46, 0x06,
0x7a, 0x3a, 0x5a, 0x1a, 0x6a, 0x2a, 0x4a, 0x0a,
0x72, 0x32, 0x52, 0x12, 0x62, 0x22, 0x42, 0x02,
0x7c, 0x3c, 0x5c, 0x1c, 0x6c, 0x2c, 0x4c, 0x0c,
0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04,
0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
0x70, 0x30, 0x50, 0x10, 0x60, 0x20, 0x40, 0x00,
};
uint8 codeword=IM->getCodeword(code_num);
if (codeword & 0x80) {
*LPSind=1;
*MPScount=run_count[codeword>>(code_num^0x07)];
}
else {
*MPScount=(1<<code_num);
}
}
///////////////////////////////////////////////////////
SDD1_BG::SDD1_BG(SDD1_GCD *associatedGCD, uint8 code) :
GCD(associatedGCD), code_num(code)
{
}
///////////////////////////////////////////////
void SDD1_BG::prepareDecomp(void) {
MPScount=0;
LPSind=0;
}
//////////////////////////////////////////////
uint8 SDD1_BG::getBit(bool8 *endOfRun) {
uint8 bit;
if (!(MPScount || LPSind)) GCD->getRunCount(code_num, &MPScount, &LPSind);
if (MPScount) {
bit=0;
MPScount--;
}
else {
bit=1;
LPSind=0;
}
if (MPScount || LPSind) (*endOfRun)=0;
else (*endOfRun)=1;
return bit;
}
/////////////////////////////////////////////////
SDD1_PEM::SDD1_PEM(SDD1_BG *associatedBG0, SDD1_BG *associatedBG1,
SDD1_BG *associatedBG2, SDD1_BG *associatedBG3,
SDD1_BG *associatedBG4, SDD1_BG *associatedBG5,
SDD1_BG *associatedBG6, SDD1_BG *associatedBG7) {
BG[0]=associatedBG0;
BG[1]=associatedBG1;
BG[2]=associatedBG2;
BG[3]=associatedBG3;
BG[4]=associatedBG4;
BG[5]=associatedBG5;
BG[6]=associatedBG6;
BG[7]=associatedBG7;
}
/////////////////////////////////////////////////////////
const SDD1_PEM::state SDD1_PEM::evolution_table[]={
{ 0,25,25},
{ 0, 2, 1},
{ 0, 3, 1},
{ 0, 4, 2},
{ 0, 5, 3},
{ 1, 6, 4},
{ 1, 7, 5},
{ 1, 8, 6},
{ 1, 9, 7},
{ 2,10, 8},
{ 2,11, 9},
{ 2,12,10},
{ 2,13,11},
{ 3,14,12},
{ 3,15,13},
{ 3,16,14},
{ 3,17,15},
{ 4,18,16},
{ 4,19,17},
{ 5,20,18},
{ 5,21,19},
{ 6,22,20},
{ 6,23,21},
{ 7,24,22},
{ 7,24,23},
{ 0,26, 1},
{ 1,27, 2},
{ 2,28, 4},
{ 3,29, 8},
{ 4,30,12},
{ 5,31,16},
{ 6,32,18},
{ 7,24,22}
};
//////////////////////////////////////////////////////
void SDD1_PEM::prepareDecomp(void) {
for (uint8 i=0; i<32; i++) {
contextInfo[i].status=0;
contextInfo[i].MPS=0;
}
}
/////////////////////////////////////////////////////////
uint8 SDD1_PEM::getBit(uint8 context) {
bool8 endOfRun;
uint8 bit;
SDD1_ContextInfo *pContInfo=&contextInfo[context];
uint8 currStatus = pContInfo->status;
const state *pState=&SDD1_PEM::evolution_table[currStatus];
uint8 currentMPS=pContInfo->MPS;
bit=(BG[pState->code_num])->getBit(&endOfRun);
if (endOfRun)
if (bit) {
if (!(currStatus & 0xfe)) (pContInfo->MPS)^=0x01;
(pContInfo->status)=pState->nextIfLPS;
}
else
(pContInfo->status)=pState->nextIfMPS;
return bit^currentMPS;
}
//////////////////////////////////////////////////////////////
SDD1_CM::SDD1_CM(SDD1_PEM *associatedPEM) :
PEM(associatedPEM)
{
}
//////////////////////////////////////////////////////////////
void SDD1_CM::prepareDecomp(uint32 first_byte) {
bitplanesInfo = SDD1_read(first_byte) & 0xc0;
contextBitsInfo = SDD1_read(first_byte) & 0x30;
bit_number=0;
for (int i=0; i<8; i++) prevBitplaneBits[i]=0;
switch (bitplanesInfo) {
case 0x00:
currBitplane = 1;
break;
case 0x40:
currBitplane = 7;
break;
case 0x80:
currBitplane = 3;
}
}
/////////////////////////////////////////////////////////////
uint8 SDD1_CM::getBit(void) {
uint8 currContext;
uint16 *context_bits;
switch (bitplanesInfo) {
case 0x00:
currBitplane ^= 0x01;
break;
case 0x40:
currBitplane ^= 0x01;
if (!(bit_number & 0x7f)) currBitplane = ((currBitplane+2) & 0x07);
break;
case 0x80:
currBitplane ^= 0x01;
if (!(bit_number & 0x7f)) currBitplane ^= 0x02;
break;
case 0xc0:
currBitplane = bit_number & 0x07;
}
context_bits = &prevBitplaneBits[currBitplane];
currContext=(currBitplane & 0x01)<<4;
switch (contextBitsInfo) {
case 0x00:
currContext|=((*context_bits & 0x01c0)>>5)|(*context_bits & 0x0001);
break;
case 0x10:
currContext|=((*context_bits & 0x0180)>>5)|(*context_bits & 0x0001);
break;
case 0x20:
currContext|=((*context_bits & 0x00c0)>>5)|(*context_bits & 0x0001);
break;
case 0x30:
currContext|=((*context_bits & 0x0180)>>5)|(*context_bits & 0x0003);
}
uint8 bit=PEM->getBit(currContext);
*context_bits <<= 1;
*context_bits |= bit;
bit_number++;
return bit;
}
//////////////////////////////////////////////////
SDD1_OL::SDD1_OL(SDD1_CM *associatedCM) :
CM(associatedCM)
{
}
///////////////////////////////////////////////////
void SDD1_OL::prepareDecomp(uint32 first_byte, uint16 out_len, uint8 *out_buf) {
bitplanesInfo = SDD1_read(first_byte) & 0xc0;
length=out_len;
buffer=out_buf;
}
///////////////////////////////////////////////////
void SDD1_OL::launch(void) {
uint8 i;
uint8 register1, register2;
switch (bitplanesInfo) {
case 0x00:
case 0x40:
case 0x80:
i=1;
do { //if length==0, we output 2^16 bytes
if (!i) {
*(buffer++)=register2;
i=~i;
}
else {
for (register1=register2=0, i=0x80; i; i>>=1) {
if (CM->getBit()) register1 |= i;
if (CM->getBit()) register2 |= i;
}
*(buffer++)=register1;
}
} while (--length);
break;
case 0xc0:
do {
for (register1=0, i=0x01; i; i<<=1) {
if (CM->getBit()) register1 |= i;
}
*(buffer++)=register1;
} while (--length);
}
}
///////////////////////////////////////////////////////
void SDD1emu::decompress(uint32 in_buf, uint16 out_len, uint8 *out_buf) {
IM.prepareDecomp(in_buf);
BG0.prepareDecomp();
BG1.prepareDecomp();
BG2.prepareDecomp();
BG3.prepareDecomp();
BG4.prepareDecomp();
BG5.prepareDecomp();
BG6.prepareDecomp();
BG7.prepareDecomp();
PEM.prepareDecomp();
CM.prepareDecomp(in_buf);
OL.prepareDecomp(in_buf, out_len, out_buf);
OL.launch();
}
////////////////////////////////////////////////////////////
SDD1emu::SDD1emu() :
GCD(&IM),
BG0(&GCD, 0), BG1(&GCD, 1), BG2(&GCD, 2), BG3(&GCD, 3),
BG4(&GCD, 4), BG5(&GCD, 5), BG6(&GCD, 6), BG7(&GCD, 7),
PEM(&BG0, &BG1, &BG2, &BG3, &BG4, &BG5, &BG6, &BG7),
CM(&PEM),
OL(&CM)
{
}
///////////////////////////////////////////////////////////

161
src/chip/sdd1/sdd1emu.h Normal file
View File

@@ -0,0 +1,161 @@
/************************************************************************
S-DD1'algorithm emulation code
------------------------------
Author: Andreas Naive
Date: August 2003
Last update: October 2004
This code is Public Domain. There is no copyright holded by the author.
Said this, the author wish to explicitly emphasize his inalienable moral rights
over this piece of intelectual work and the previous research that made it
possible, as recognized by most of the copyright laws around the world.
This code is provided 'as-is', with no warranty, expressed or implied.
No responsability is assumed by the author in connection with it.
The author is greatly indebted with The Dumper, without whose help and
patience providing him with real S-DD1 data the research would have never been
possible. He also wish to note that in the very beggining of his research,
Neviksti had done some steps in the right direction. By last, the author is
indirectly indebted to all the people that worked and contributed in the
S-DD1 issue in the past.
An algorithm's documentation is available as a separate document.
The implementation is obvious when the algorithm is
understood.
************************************************************************/
class SDD1_IM { //Input Manager
public:
SDD1_IM(void) {}
void prepareDecomp(uint32 in_buf);
uint8 getCodeword(const uint8 code_len);
private:
uint32 byte_ptr;
uint8 bit_count;
};
////////////////////////////////////////////////////
class SDD1_GCD { //Golomb-Code Decoder
public:
SDD1_GCD(SDD1_IM *associatedIM);
void getRunCount(uint8 code_num, uint8 *MPScount, bool8 *LPSind);
private:
SDD1_IM *const IM;
};
//////////////////////////////////////////////////////
class SDD1_BG { // Bits Generator
public:
SDD1_BG(SDD1_GCD *associatedGCD, uint8 code);
void prepareDecomp(void);
uint8 getBit(bool8 *endOfRun);
private:
const uint8 code_num;
uint8 MPScount;
bool8 LPSind;
SDD1_GCD *const GCD;
};
////////////////////////////////////////////////
class SDD1_PEM { //Probability Estimation Module
public:
SDD1_PEM(SDD1_BG *associatedBG0, SDD1_BG *associatedBG1,
SDD1_BG *associatedBG2, SDD1_BG *associatedBG3,
SDD1_BG *associatedBG4, SDD1_BG *associatedBG5,
SDD1_BG *associatedBG6, SDD1_BG *associatedBG7);
void prepareDecomp(void);
uint8 getBit(uint8 context);
private:
struct state {
uint8 code_num;
uint8 nextIfMPS;
uint8 nextIfLPS;
};
static const state evolution_table[];
struct SDD1_ContextInfo {
uint8 status;
uint8 MPS;
} contextInfo[32];
SDD1_BG * BG[8];
};
///////////////////////////////////////////////////
class SDD1_CM { //Context Model
public:
SDD1_CM(SDD1_PEM *associatedPEM);
void prepareDecomp(uint32 first_byte);
uint8 getBit(void);
private:
uint8 bitplanesInfo;
uint8 contextBitsInfo;
uint8 bit_number;
uint8 currBitplane;
uint16 prevBitplaneBits[8];
SDD1_PEM *const PEM;
};
///////////////////////////////////////////////////
class SDD1_OL { //Output Logic
public:
SDD1_OL(SDD1_CM *associatedCM);
void prepareDecomp(uint32 first_byte, uint16 out_len, uint8 *out_buf);
void launch(void);
private:
uint8 bitplanesInfo;
uint16 length;
uint8 *buffer;
SDD1_CM *const CM;
};
/////////////////////////////////////////////////////////
class SDD1emu {
public:
SDD1emu(void);
void decompress(uint32 in_buf, uint16 out_len, uint8 *out_buf);
private:
SDD1_IM IM;
SDD1_GCD GCD;
SDD1_BG BG0; SDD1_BG BG1; SDD1_BG BG2; SDD1_BG BG3;
SDD1_BG BG4; SDD1_BG BG5; SDD1_BG BG6; SDD1_BG BG7;
SDD1_PEM PEM;
SDD1_CM CM;
SDD1_OL OL;
};

191
src/chip/srtc/srtc.cpp Normal file
View File

@@ -0,0 +1,191 @@
/*
S-RTC chip emulation
Used by Hudson Soft in Dai Kaijuu Monogatari II and Far East of Eden Zero.
Currently, only the former is supported by bsnes.
Original S-RTC emulation code via John Weidman/SNES9x
Rewritten for compatibility with bsnes via byuu
The S-RTC is a real-time clock chip that was added to the above two carts
to allow the games to maintain the current time, even when the game was not
powered on. Thus allowing special events at certain times, and on certain
dates. Hudson Soft called this the PLG (Player's Life Gameplay System).
This chip is a special case to the term 'emulation' itself.
There are a few different ways to go about emulating this chip, and each
result in a different style of emulation.
The first is to simply return the current PC system time when the S-RTC is
read from. This emulates the original S-RTC in the sense that it always
returns the true current time, ignoring the speed that the SNES itself is
running at. The downside to this method is that you lose the ability to set
the time to whatever you choose inside the game itself. It will always return
the true time, regardless. This can be overcome by changing the PC system time,
which actually adds a greater degree of control over event timing, very useful
for emulation. It also has a timeshifting flaw discussed below.
The second is to run the S-RTC relative to the SNES speed. This means that
if the emulator is sped up (via fast forward key, frameskipping, etc), or
slowed down (via slowdown key, system bottlenecking, etc); the time increments
slower, thus ~60 frames on the SNES equal one second. Without this, timeshifting
will occur between the S-RTC and the real SNES.
The third and final method is to save a copy of the local system time when the
S-RTC is initially set, and compare the current system time against this value
when setting the S-RTC time. This overcomes the first methods' shortcoming of
not allowing the player to set the time in-game, however a new problem arises.
You now have to save the time when the RTC was initially set to both savestates
and to save-game data. This would require an extra file, or the breaking of
perhaps the only standard format (.srm savegame backups) in the entire SNES
emulation scene. You also give up the control of being able to override the
RTC clock at will via the PC system time outside of emulation.
The first method has another advantage over the third: Dai Kaijuu Monogatari II
only allows dates in the range of the years 1996-2199. The first method gets
around this limitation. But who knows, maybe it will break something in the
game if the date exceeds 2199... I guess we'll worry about that in two hundred
years from now.
For my implementation, I chose to go with the first method. Both for simplicity
and because I did not wish to create a new method for saving the system time
whenever the RTC is set.
*/
#include "../../base.h"
SRTC *srtc;
void SRTC::set_time() {
time_t rawtime;
tm *t;
::time(&rawtime);
t = localtime(&rawtime);
//see srtc.h for format of srtc.data[]
srtc.data[0] = t->tm_sec % 10;
srtc.data[1] = t->tm_sec / 10;
srtc.data[2] = t->tm_min % 10;
srtc.data[3] = t->tm_min / 10;
srtc.data[4] = t->tm_hour % 10;
srtc.data[5] = t->tm_hour / 10;
srtc.data[6] = t->tm_mday % 10;
srtc.data[7] = t->tm_mday / 10;
srtc.data[8] = t->tm_mon + 1;
srtc.data[9] = t->tm_year % 10;
srtc.data[10] = (t->tm_year / 10) % 10;
srtc.data[11] = 9 + (t->tm_year / 100);
srtc.data[12] = t->tm_wday;
}
void SRTC::init() {}
void SRTC::enable() {
r_mem->set_mmio_mapper(0x2800, this);
r_mem->set_mmio_mapper(0x2801, this);
}
void SRTC::power() {
memset(&srtc, 0, sizeof(srtc));
reset();
}
void SRTC::reset() {
srtc.index = -1;
srtc.mode = SRTC_READ;
}
uint8 SRTC::mmio_read(uint16 addr) {
switch(addr) {
case 0x2800: {
if(srtc.mode == SRTC_READ) {
if(srtc.index < 0) {
set_time();
srtc.index++;
return 0x0f; //send start message
} else if(srtc.index > MAX_SRTC_INDEX) {
srtc.index = -1;
return 0x0f; //send finished message
} else {
return srtc.data[srtc.index++];
}
} else {
return 0x00;
}
} break;
case 0x2801: {
} break;
}
return r_cpu->regs.mdr;
}
//Please see notes above about the implementation of the S-RTC
//Writes are stored the srtc.data[] array, but they are ignored
//as reads will refresh the data array with the current system
//time. The write method is only here for the sake of faux
//emulation of the real hardware.
void SRTC::mmio_write(uint16 addr, uint8 data) {
switch(addr) {
case 0x2800: {
} break;
case 0x2801: {
data &= 0x0f; //only the low four bits are used
if(data >= 0x0d) {
switch(data) {
case 0x0d:
srtc.mode = SRTC_READ;
srtc.index = -1;
break;
case 0x0e:
srtc.mode = SRTC_COMMAND;
break;
case 0x0f:
//unknown behaviour
break;
}
return;
}
if(srtc.mode == SRTC_WRITE) {
if(srtc.index >= 0 && srtc.index < MAX_SRTC_INDEX) {
srtc.data[srtc.index++] = data;
if(srtc.index == MAX_SRTC_INDEX) {
//all S-RTC data has been loaded by program
srtc.data[srtc.index++] = 0x00; //day_of_week
}
}
} else if(srtc.mode == SRTC_COMMAND) {
switch(data) {
case SRTC_COMMAND_CLEAR:
memset(srtc.data, 0, MAX_SRTC_INDEX + 1);
srtc.index = -1;
srtc.mode = SRTC_READY;
break;
case SRTC_COMMAND_WRITE:
srtc.index = 0;
srtc.mode = SRTC_WRITE;
break;
default:
//unknown behaviour
srtc.mode = SRTC_READY;
break;
}
} else {
if(srtc.mode == SRTC_READ) {
//ignore writes while in read mode
} else if(srtc.mode == SRTC_READY) {
//unknown behaviour
}
}
} break;
}
}
SRTC::SRTC() {}

52
src/chip/srtc/srtc.h Normal file
View File

@@ -0,0 +1,52 @@
class SRTC : public MMIO {
public:
enum { MAX_SRTC_INDEX = 0x0c };
enum {
SRTC_READ = 0,
SRTC_WRITE,
SRTC_COMMAND,
SRTC_READY
};
enum {
SRTC_COMMAND_WRITE = 0,
SRTC_COMMAND_CLEAR = 4
};
/******************************
[srtc.data structure]
Index Description Range
----- ----------- -----
0 Seconds low 0-9
1 Seconds high 0-5
2 Minutes low 0-9
3 Minutes high 0-5
4 Hour low 0-9
5 Hour high 0-2
6 Day low 0-9
7 Day high 0-3
8 Month 1-12
9 Year ones 0-9
10 Year tens 0-9
11 Year hundreds 9-11 (9=19xx, 10=20xx, 11=21xx)
12 Day of week 0-6 (0=Sunday, ...)
******************************/
struct {
int8 index;
uint8 mode;
uint8 data[MAX_SRTC_INDEX + 1];
} srtc;
void set_time();
void init();
void enable();
void power();
void reset();
uint8 mmio_read (uint16 addr);
void mmio_write(uint16 addr, uint8 data);
SRTC();
};
extern SRTC *srtc;

View File

@@ -1,201 +0,0 @@
#include "../../base.h"
void bClock::frameskip_update_status() {
if(frameskip.changed == true) {
frameskip.changed = false;
frameskip.count = frameskip.new_count;
frameskip.pos = 0;
} else {
frameskip.pos++;
frameskip.pos %= (frameskip.count + 1);
}
frameskip.notify_ppu = (frameskip.pos == 0)?true:false;
}
void bClock::dram_refresh_test() {
if(cc1.dram_refreshed == false && status.hcycles >= cc1.dram_refresh_pos) {
cc1.dram_refreshed = true;
if(status.interlace != false || status.interlace_field != 1 || status.vcounter != 240) {
if(cc1.dram_refresh_pos == 534) {
cc1.dram_refresh_pos = 538;
} else { //cc1.dram_refresh_pos == 538
cc1.dram_refresh_pos = 534;
}
}
cc1.pos += 40;
cc1.frame_pos += 40;
status.hcycles += 40;
}
}
/*
all scanlines are 1364 cycles long, except scanline 240
on non-interlace odd-frames, which is 1360 cycles long.
interlace mode has 525 scanlines: 263 on the even frame,
and 262 on the odd.
non-interlace mode has 524 scanlines: 262 scanlines on
both even and odd frames.
cycles per frame:
263 * 1364 = 358732
262 * 1364 = 357368
262 * 1364 - 4 = 357364
*/
void bClock::inc_vcounter() {
status.hcycles -= cc1.line_cycles;
status.vcounter++;
if(status.vcounter >= cc1.frame_lines) {
frameskip_update_status();
cc1.frame_pos -= cc1.frame_cycles;
status.vcounter = 0;
status.interlace_field ^= 1;
if(status.interlace == true) {
if(status.interlace_field == 0) {
cc1.frame_cycles = 263 * 1364;
cc1.frame_lines = 263;
} else {
cc1.frame_cycles = 262 * 1364;
cc1.frame_lines = 262;
}
} else {
if(status.interlace_field == 0) {
cc1.frame_cycles = 262 * 1364;
cc1.frame_lines = 262;
} else {
cc1.frame_cycles = (262 * 1364) - 4;
cc1.frame_lines = 262;
}
}
signal_frame = true;
}
if(status.interlace == false && status.interlace_field == 1 && status.vcounter == 240) {
cc1.line_cycles = 1360;
} else {
cc1.line_cycles = 1364;
}
cc1.dram_refreshed = false;
signal_scanline = true;
}
/*
all dots are 4 cycles long, except dots 322 and 326. dots 322 and 326
are 6 cycles long. this holds true for all scanlines except scanline
240 on non-interlace odd frames. the reason for this is because this
scanline is only 1360 cycles long, instead of 1364 like all other
scanlines.
this makes the effective range of hscan_pos 0-339 at all times.
dot 322 range = { 1288, 1290, 1292 }
dot 326 range = { 1306, 1308, 1310 }
*/
void bClock::sync() {
uint32 new_cycles, cycles;
new_cycles = cc1.pos - cc1.last_pos;
while(new_cycles) {
if(new_cycles > 40) {
cycles = 40;
new_cycles -= 40;
} else {
cycles = new_cycles;
new_cycles = 0;
}
status.hcycles += cycles;
cc1.frame_pos += cycles;
dram_refresh_test();
if(status.hcycles >= cc1.line_cycles) {
inc_vcounter();
}
}
if(status.interlace == false && status.interlace_field == 1 && status.vcounter == 240) {
status.hcounter = status.hcycles >> 2;
} else {
//1288 = 322 * 4, 1306 = 326 * 4 + 2
status.hcounter = (status.hcycles - ((status.hcycles > 1288) << 1) - ((status.hcycles > 1306) << 1)) >> 2;
}
cc1.last_pos = cc1.pos;
if(cc1.pos > cc1.frequency) {
cc1.pos -= cc1.frequency;
cc1.last_pos -= cc1.frequency;
}
}
void bClock::set_frameskip(uint8 fs) {
frameskip.changed = true;
frameskip.new_count = fs;
}
void bClock::power() {
reset();
}
void bClock::reset() {
//upon SNES reset, start at scanline 0 non-interlace
cc1.frame_cycles = 262 * 1364;
cc1.frame_lines = 262;
cc1.line_cycles = 1364;
/*
Initial latch values for $213c/$213d
0035:0000 (53.0 -> 212) [lda $2137]
0038:0000 (56.5 -> 226) [nop : lda $2137]
*/
cc1.pos = 188;
cc1.last_pos = 0;
cc1.frame_pos = 0;
status.vcounter = 0;
status.hcounter = 0;
status.hcycles = 0;
cc1.dram_refresh_pos = 538;
cc1.dram_refreshed = false;
cc2.pos = 0;
signal_scanline = false;
signal_frame = false;
sync();
}
void bClock::run() {
cpu->run();
if(frameskip.notify_ppu == true)ppu->run();
sync();
if(signal_frame == true) {
signal_frame = false;
cpu->frame();
if(frameskip.notify_ppu == true)ppu->frame();
}
if(signal_scanline == true) {
signal_scanline = false;
cpu->scanline();
if(frameskip.notify_ppu == true)ppu->scanline();
}
}
void bClock::add_cc1_cycles(uint32 cycles) {
cc1.pos += cycles;
}
void bClock::add_cc2_cycles(uint32 cycles) {
cc2.pos += cycles;
}
bClock::bClock() {
cc1.frequency = 21477272;
cc2.frequency = 24576000;
frameskip.changed = false;
frameskip.count = 0;
frameskip.pos = 0;
}

View File

@@ -1,37 +0,0 @@
class bClock : public Clock {
private:
struct {
bool changed, notify_ppu;
uint8 count, new_count, pos;
}frameskip;
bool signal_scanline, signal_frame;
void frameskip_update_status();
void inc_vcounter();
void dram_refresh_test();
public:
struct {
uint32 frequency;
uint32 pos, last_pos;
uint32 frame_cycles, frame_lines, frame_pos;
uint16 line_cycles;
bool dram_refreshed; //whether or not dram has been refreshed on this line
uint16 dram_refresh_pos;
}cc1;
struct {
uint32 frequency;
uint32 pos, last_pos;
}cc2;
void set_frameskip(uint8 fs);
void add_cc1_cycles(uint32 cycles);
void add_cc2_cycles(uint32 cycles);
void sync();
void run();
void power();
void reset();
bClock();
~bClock();
};

View File

@@ -1,49 +0,0 @@
#include "../base.h"
void Clock::enable_overscan(bool n) {
status.overscan = n;
}
void Clock::enable_interlace(bool n) {
status.interlace = n;
}
bool Clock::overscan() {
return status.overscan;
}
bool Clock::interlace() {
return status.interlace;
}
bool Clock::interlace_field() {
return status.interlace_field;
}
uint16 Clock::vcounter() {
return status.vcounter;
}
uint16 Clock::hcounter() {
return status.hcounter;
}
uint16 Clock::hcycles() {
return status.hcycles;
}
uint16 Clock::visible_scanlines() {
return (status.overscan)?239:224;
}
void Clock::set_frameskip(uint8 fs) {}
Clock::Clock() {
status.overscan = false;
status.interlace = false;
status.interlace_field = 0;
status.vcounter = 0;
status.hcounter = 0;
status.hcycles = 0;
}

View File

@@ -1,36 +0,0 @@
class Clock {
private:
struct {
bool overscan;
bool interlace;
bool interlace_field;
uint16 vcounter;
uint16 hcounter;
uint16 hcycles;
}status;
public:
virtual void enable_overscan(bool n);
virtual void enable_interlace(bool n);
virtual bool overscan();
virtual bool interlace();
virtual bool interlace_field();
virtual uint16 vcounter();
virtual uint16 hcounter();
virtual uint16 hcycles();
virtual uint16 visible_scanlines();
virtual void set_frameskip(uint8 fs);
virtual void add_cc1_cycles(uint32 cycles) = 0;
virtual void add_cc2_cycles(uint32 cycles) = 0;
virtual void sync() = 0;
virtual void run() = 0;
virtual void power() = 0;
virtual void reset() = 0;
Clock();
friend class bClock;
};

73
src/config/config.cpp Normal file
View File

@@ -0,0 +1,73 @@
Config config_file;
namespace config {
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)", "");
Setting FS::save_path(&config_file, "fs.save_path",
"Default path for all save RAM and cheat files (\"\" = use current directory)", "");
Setting FS::save_ext(&config_file, "fs.save_ext",
"Extension to be used for all save RAM files", "srm");
Setting SNES::gamma_ramp(&config_file, "snes.colorfilter.gamma_ramp",
"Use precalculated TV-style gamma ramp", true, Setting::TRUE_FALSE);
Setting SNES::sepia(&config_file, "snes.colorfilter.sepia",
"Convert color to sepia tone", false, Setting::TRUE_FALSE);
Setting SNES::grayscale(&config_file, "snes.colorfilter.grayscale",
"Convert color to grayscale tone", false, Setting::TRUE_FALSE);
Setting SNES::invert(&config_file, "snes.colorfilter.invert",
"Invert output image colors", false, Setting::TRUE_FALSE);
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"
"", true, Setting::TRUE_FALSE);
Setting SNES::mute(&config_file, "snes.mute", "Mutes SNES audio output when enabled",
false, 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);
Setting PPU::bg1_pri1_enable(0, "ppu.bg1_pri1_enable", "Enable BG1 Priority 1", true, Setting::TRUE_FALSE);
Setting PPU::bg2_pri0_enable(0, "ppu.bg2_pri0_enable", "Enable BG2 Priority 0", true, Setting::TRUE_FALSE);
Setting PPU::bg2_pri1_enable(0, "ppu.bg2_pri1_enable", "Enable BG2 Priority 1", true, Setting::TRUE_FALSE);
Setting PPU::bg3_pri0_enable(0, "ppu.bg3_pri0_enable", "Enable BG3 Priority 0", true, Setting::TRUE_FALSE);
Setting PPU::bg3_pri1_enable(0, "ppu.bg3_pri1_enable", "Enable BG3 Priority 1", true, Setting::TRUE_FALSE);
Setting PPU::bg4_pri0_enable(0, "ppu.bg4_pri0_enable", "Enable BG4 Priority 0", true, Setting::TRUE_FALSE);
Setting PPU::bg4_pri1_enable(0, "ppu.bg4_pri1_enable", "Enable BG4 Priority 1", true, Setting::TRUE_FALSE);
Setting PPU::oam_pri0_enable(0, "ppu.oam_pri0_enable", "Enable OAM Priority 0", true, Setting::TRUE_FALSE);
Setting PPU::oam_pri1_enable(0, "ppu.oam_pri1_enable", "Enable OAM Priority 1", true, Setting::TRUE_FALSE);
Setting PPU::oam_pri2_enable(0, "ppu.oam_pri2_enable", "Enable OAM Priority 2", true, Setting::TRUE_FALSE);
Setting PPU::oam_pri3_enable(0, "ppu.oam_pri3_enable", "Enable OAM Priority 3", true, Setting::TRUE_FALSE);
};

39
src/config/config.h Normal file
View File

@@ -0,0 +1,39 @@
extern Config config_file;
namespace config {
extern struct FS {
static Setting base_path, rom_path, save_path;
static Setting save_ext;
} fs;
extern struct SNES {
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;
static Setting bg2_pri0_enable, bg2_pri1_enable;
static Setting bg3_pri0_enable, bg3_pri1_enable;
static Setting bg4_pri0_enable, bg4_pri1_enable;
static Setting oam_pri0_enable, oam_pri1_enable;
static Setting oam_pri2_enable, oam_pri3_enable;
} ppu;
};

View File

@@ -1,169 +1,59 @@
#include "../../base.h"
#include "bcpu_op_adc.cpp"
#include "bcpu_op_and.cpp"
#include "bcpu_op_cmp.cpp"
#include "bcpu_op_eor.cpp"
#include "bcpu_op_incdec.cpp"
#include "bcpu_op_lda.cpp"
#include "bcpu_op_misc.cpp"
#include "bcpu_op_ora.cpp"
#include "bcpu_op_pc.cpp"
#include "bcpu_op_sbc.cpp"
#include "bcpu_op_shift.cpp"
#include "bcpu_op_sta.cpp"
#include "bcpu_op_stack.cpp"
#include "core/core.cpp"
#include "memory/memory.cpp"
#include "dma/dma.cpp"
#include "timing/timing.cpp"
#include "bcpu_exec.cpp"
#include "bcpu_mmio.cpp"
#include "bcpu_int.cpp"
uint8 bCPU::pio_status() {
return status.pio;
}
/***********
*** IRQ ***
***********
cycles:
[1] pbr,pc ; io
[2] pbr,pc ; io
[3] 0,s ; pbr
[4] 0,s-1 ; pch
[5] 0,s-2 ; pcl
[6] 0,s-3 ; p
[7] 0,va ; aavl
[8] 0,va+1 ; aavh
*/
void bCPU::irq(uint16 addr) {
if(cpustate == CPUSTATE_WAI) {
regs.pc.w++;
cpustate = CPUSTATE_RUN;
}
clock->add_cc1_cycles(mem_bus->speed(regs.pc)); //1
clock->add_cc1_cycles(6); //2
stack_write(regs.pc.b); //3
stack_write(regs.pc.h); //4
stack_write(regs.pc.l); //5
stack_write(regs.p); //6
rd.l = op_read(OPMODE_ADDR, addr); //7
rd.h = op_read(OPMODE_ADDR, addr + 1); //8
regs.pc.b = 0x00;
regs.pc.w = rd.w;
regs.p.d = 0;
regs.p.i = 1;
snes->notify(SNES::CPU_EXEC_OPCODE);
}
uint8 bCPU::pio_status() { return status.pio; }
void bCPU::run() {
uint16 v, h, hc, vs;
v = clock->vcounter();
h = clock->hcounter();
hc = clock->hcycles();
vs = clock->visible_scanlines();
//HDMA test
if(v < vs && h >= 278) {
if(status.hdma_triggered == false) {
status.hdma_triggered = true;
dma->hdma_run();
return;
}
if(run_state.hdma) {
exec_hdma();
return;
}
switch(cpustate) {
case CPUSTATE_RUN:
case CPUSTATE_WAI:
//NMI test
if(v >= (vs + 1) && status.nmi_triggered == false) {
if((v == (vs + 1) && hc >= 12) || (v > (vs + 1))) {
status.nmi_triggered = true;
status.nmi_pin = 0;
if(status.nmi_enabled == true) {
irq(0xffea);
return;
}
if(run_state.dma) {
exec_dma();
return;
}
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 = (regs.e == false) ? 0xffea : 0xfffa;
} else if(time.irq_pending == true) {
time.irq_pending = false;
aa.w = (regs.e == false) ? 0xffee : 0xfffe;
}
irq_run();
}
//IRQ test
if(!regs.p.i) {
if(status.virq_enabled == true && status.virq_enabled == true) {
if(v == status.virq_pos && h >= status.hirq_pos && status.irq_pin == 1) {
status.irq_triggered = true;
status.irq_pin = 0;
irq(0xffee);
return;
}
} else if(status.virq_enabled == true) {
if(v == status.virq_pos && status.irq_pin == 1) {
status.irq_triggered = true;
status.irq_pin = 0;
irq(0xffee);
return;
}
} else if(status.hirq_enabled == true) {
if(h >= status.hirq_pos && status.irq_pin == 1) {
status.irq_triggered = true;
status.irq_pin = 0;
irq(0xffee);
return;
}
}
}
exec_opcode();
break;
case CPUSTATE_DMA:
dma->run();
break;
case CPUSTATE_STP:
exec_opcode();
break;
}
}
void bCPU::scanline() {
uint16 v = clock->vcounter();
status.hdma_triggered = false;
if(v == 225 && 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;
}
if(status.virq_enabled == false) {
status.irq_pin = 1;
}
}
void bCPU::frame() {
status.hdma_triggered = false;
status.nmi_triggered = false;
status.r4210_read = false;
status.irq_pin = 1;
dma->hdma_initialize();
exec_cycle();
}
void bCPU::power() {
region = snes->region();
regs.a = regs.x = regs.y = 0x0000;
regs.s = 0x01ff;
reset();
}
void bCPU::reset() {
/* reset vector location */
regs.pc = mem_bus->read(0xfffc) | (mem_bus->read(0xfffd) << 8);
//reset vector location
regs.pc.d = 0;
regs.pc.l = r_mem->read(0xfffc);
regs.pc.h = r_mem->read(0xfffd);
/* registers are not fully reset by SNES */
//registers are not fully reset by SNES
regs.x.h = 0x00;
regs.y.h = 0x00;
regs.s.h = 0x01;
@@ -171,146 +61,37 @@ void bCPU::reset() {
regs.db = 0x00;
regs.p = 0x34;
regs.e = 1;
regs.mdr = 0x00;
cpustate = CPUSTATE_RUN;
dma->reset();
time_reset();
mmio_reset();
dma_reset();
optbl = optbl_e;
run_state.hdma = false;
run_state.dma = false;
run_state.irq = false;
run_state.wai = false;
run_state.stp = false;
status.hdma_triggered = false;
status.cycle_pos = 0;
status.cycle_count = 0;
status.cycles_executed = 0;
status.nmi_triggered = false;
status.nmi_pin = 1;
status.r4210_read = false;
apu_port[0] = 0x00;
apu_port[1] = 0x00;
apu_port[2] = 0x00;
apu_port[3] = 0x00;
status.irq_triggered = false;
status.irq_pin = 1;
}
frame();
void bCPU::cpu_c2() {
if(regs.d.l != 0x00) {
clock->add_cc1_cycles(6);
}
}
void bCPU::cpu_c4(uint16 a, uint16 b) {
if(((a & 0xff00) != (b & 0xff00)) || !regs.p.x) {
clock->add_cc1_cycles(6);
}
}
void bCPU::cpu_c6(uint16 a) {
if(regs.e) {
if((regs.pc.w & 0xff00) != (a & 0xff00)) {
clock->add_cc1_cycles(6);
}
}
}
void bCPU::cpu_io() {
clock->add_cc1_cycles(6);
}
uint8 bCPU::op_read() {
uint8 r;
r = mem_bus->read(regs.pc);
clock->add_cc1_cycles(mem_bus->speed(regs.pc));
regs.pc.w++;
return r;
}
uint8 bCPU::op_read(uint8 mode, uint32 addr) {
uint8 r;
switch(mode) {
case OPMODE_ADDR:
addr &= 0xffff;
break;
case OPMODE_LONG:
addr &= 0xffffff;
break;
case OPMODE_DBR:
addr &= 0xffffff;
addr = (regs.db << 16) + addr;
break;
case OPMODE_PBR:
addr &= 0xffff;
addr = (regs.pc.b << 16) | addr;
break;
case OPMODE_DP:
addr &= 0xffff;
addr = (regs.d + addr) & 0xffff;
break;
case OPMODE_SP:
addr &= 0xffff;
addr = (regs.s + addr) & 0xffff;
break;
}
r = mem_bus->read(addr);
clock->add_cc1_cycles(mem_bus->speed(addr));
return r;
}
void bCPU::op_write(uint8 mode, uint32 addr, uint8 value) {
switch(mode) {
case OPMODE_ADDR:
addr &= 0xffff;
break;
case OPMODE_LONG:
addr &= 0xffffff;
break;
case OPMODE_DBR:
addr &= 0xffffff;
addr = (regs.db << 16) + addr;
break;
case OPMODE_PBR:
addr &= 0xffff;
addr = (regs.pc.b << 16) | addr;
break;
case OPMODE_DP:
addr &= 0xffff;
addr = (regs.d + addr) & 0xffff;
break;
case OPMODE_SP:
addr &= 0xffff;
addr = (regs.s + addr) & 0xffff;
break;
}
mem_bus->write(addr, value);
clock->add_cc1_cycles(mem_bus->speed(addr));
}
uint8 bCPU::stack_read() {
byte r;
if(regs.e) {
regs.s.l++;
} else {
regs.s.w++;
}
r = mem_bus->read(regs.s);
clock->add_cc1_cycles(mem_bus->speed(regs.s));
return r;
}
void bCPU::stack_write(uint8 value) {
mem_bus->write(regs.s, value);
clock->add_cc1_cycles(mem_bus->speed(regs.s));
if(regs.e) {
regs.s.l--;
} else {
regs.s.w--;
}
//initial latch values for $213c/$213d
//[x]0035 : [y]0000 (53.0 -> 212) [lda $2137]
//[x]0038 : [y]0000 (56.5 -> 226) [nop : lda $2137]
add_cycles(186);
}
bCPU::bCPU() {
dma = new bDMA(this);
mmio = new bCPUMMIO(this);
init_op_tables();
}
bCPU::~bCPU() {
delete(mmio);
delete(dma);
}
bCPU::~bCPU() {}

View File

@@ -1,94 +1,57 @@
class bCPU;
class bDMA {
public:
bCPU *cpu;
struct {
//$420b
bool active;
//$420c
bool hdma_active;
//$43x0
bool direction;
bool hdma_indirect;
int8 incmode;
bool fixedxfer;
uint8 xfermode;
//$43x1
uint8 destaddr;
//$43x2-$43x4
uint32 srcaddr;
//$43x5-$43x6
uint16 xfersize;
//$43x7
uint8 hdma_indirect_bank;
//hdma-specific
bool hdma_first_line;
bool hdma_repeat;
uint16 hdma_line_counter;
uint32 hdma_address, hdma_iaddress;
bool hdma_completed;
}channel[8];
void hdma_write(uint8 i, uint8 l, uint8 x);
void hdma_run();
void hdma_initialize();
void run();
void reset();
uint16 dma_cputommio(uint8 i, uint8 index);
uint16 dma_mmiotocpu(uint8 i, uint8 index);
void dma_xfer_type0(uint8 i);
void dma_xfer_type1(uint8 i);
void dma_xfer_type2(uint8 i);
void dma_xfer_type3(uint8 i);
void dma_xfer_type4(uint8 i);
void dma_xfer_type5(uint8 i);
bDMA(bCPU *_cpu);
};
class bCPUMMIO : public MMIO {
public:
bCPU *cpu;
uint8 read (uint32 addr);
void write(uint32 addr, uint8 value);
bCPUMMIO(bCPU *_cpu);
};
class bCPU : public CPU {
private:
typedef void (bCPU::*op)();
op *optbl, optbl_e[256], optbl_MX[256], optbl_Mx[256], optbl_mX[256], optbl_mx[256];
public:
enum { CPUSTATE_RUN = 0, CPUSTATE_DMA, CPUSTATE_WAI, CPUSTATE_STP };
uint8 cpustate;
#include "core/core.h"
#include "memory/memory.h"
#include "dma/dma.h"
#include "timing/timing.h"
bDMA *dma;
enum {
OPMODE_ADDR = 1, OPMODE_LONG = 2,
OPMODE_DBR = 3, OPMODE_PBR = 4,
OPMODE_DP = 5, OPMODE_SP = 6
};
CPUReg24 aa, rd;
uint8 dp, sp;
enum { NTSC = 0, PAL = 1 };
uint8 region;
enum {
DMASTATE_DMASYNC,
DMASTATE_DMASYNC2,
DMASTATE_DMASYNC3,
DMASTATE_RUN,
DMASTATE_CPUSYNC,
HDMASTATE_IDMASYNC,
HDMASTATE_IDMASYNC2,
HDMASTATE_IDMASYNC3,
HDMASTATE_ICPUSYNC,
HDMASTATE_DMASYNC,
HDMASTATE_DMASYNC2,
HDMASTATE_DMASYNC3,
HDMASTATE_RUN,
HDMASTATE_CPUSYNC
};
struct {
bool hdma_triggered;
bool hdma;
bool dma;
bool irq;
bool stp;
bool wai;
} run_state;
bool nmi_triggered;
bool nmi_pin;
bool r4210_read;
struct {
uint8 cycle_pos, cycle_count;
uint8 opcode;
uint32 cycles_executed;
bool irq_triggered;
bool irq_pin;
uint8 dma_state, hdma_state;
uint32 dma_cycle_count, hdma_cycle_count;
//$4207-$420a
uint16 virq_trigger, hirq_trigger;
//$2181-$2183
uint32 wram_addr;
//$4016
uint8 joypad1_strobe_value;
uint8 joypad1_read_pos;
//$4016-$4017
bool joypad_strobe_latch;
uint8 joypad1_read_pos, joypad2_read_pos;
//$4200
bool nmi_enabled;
@@ -111,22 +74,25 @@ struct {
//$4214-$4216
uint16 r4214;
uint16 r4216;
}status;
} status;
uint8 pio_status();
void irq(uint16 addr);
void run();
void scanline();
void frame();
void power();
void reset();
inline bool hdma_test();
inline bool nmi_test();
inline bool irq_test();
inline uint8 pio_status();
inline void run();
inline uint32 clocks_executed();
inline void power();
inline void reset();
inline void irq_run();
//mmio commands
void mmio_reset();
uint8 mmio_r2180();
uint8 mmio_r21c2();
uint8 mmio_r21c3();
uint8 mmio_r4016();
uint8 mmio_r4017();
uint8 mmio_r4210();
uint8 mmio_r4211();
uint8 mmio_r4212();
@@ -137,6 +103,20 @@ struct {
uint8 mmio_r4217();
uint8 mmio_r4218();
uint8 mmio_r4219();
uint8 mmio_r421a();
uint8 mmio_r421b();
uint8 mmio_r43x0(uint8 i);
uint8 mmio_r43x1(uint8 i);
uint8 mmio_r43x2(uint8 i);
uint8 mmio_r43x3(uint8 i);
uint8 mmio_r43x4(uint8 i);
uint8 mmio_r43x5(uint8 i);
uint8 mmio_r43x6(uint8 i);
uint8 mmio_r43x7(uint8 i);
uint8 mmio_r43x8(uint8 i);
uint8 mmio_r43x9(uint8 i);
uint8 mmio_r43xa(uint8 i);
uint8 mmio_r43xb(uint8 i);
void mmio_w2180(uint8 value);
void mmio_w2181(uint8 value);
void mmio_w2182(uint8 value);
@@ -164,520 +144,21 @@ struct {
void mmio_w43x5(uint8 value, uint8 i);
void mmio_w43x6(uint8 value, uint8 i);
void mmio_w43x7(uint8 value, uint8 i);
void mmio_w43x8(uint8 value, uint8 i);
void mmio_w43x9(uint8 value, uint8 i);
void mmio_w43xa(uint8 value, uint8 i);
void mmio_w43xb(uint8 value, uint8 i);
void exec_opcode();
uint8 mmio_read (uint16 addr);
void mmio_write(uint16 addr, uint8 data);
uint8 op_read ();
uint8 op_read (uint8 mode, uint32 addr);
void op_write(uint8 mode, uint32 addr, uint8 value);
uint8 stack_read ();
void stack_write(uint8 value);
//cpu extra-cycle conditions
void cpu_c2();
void cpu_c4(uint16 a, uint16 b);
void cpu_c6(uint16 a);
void cpu_io();
//opcode functions
void init_op_tables();
//op_adc
inline void flags_adc_b();
inline void flags_adc_w();
void op_adc_constb();
void op_adc_constw();
void op_adc_addrb();
void op_adc_addrw();
void op_adc_addrxb();
void op_adc_addrxw();
void op_adc_dpb();
void op_adc_dpw();
void op_adc_idpb();
void op_adc_idpw();
void op_adc_ildpb();
void op_adc_ildpw();
void op_adc_longb();
void op_adc_longw();
void op_adc_longxb();
void op_adc_longxw();
void op_adc_addryb();
void op_adc_addryw();
void op_adc_dpxb();
void op_adc_dpxw();
void op_adc_idpxb();
void op_adc_idpxw();
void op_adc_idpyb();
void op_adc_idpyw();
void op_adc_ildpyb();
void op_adc_ildpyw();
void op_adc_srb();
void op_adc_srw();
void op_adc_isryb();
void op_adc_isryw();
//op_and
inline void flags_and_b();
inline void flags_and_w();
void op_and_constb();
void op_and_constw();
void op_and_addrb();
void op_and_addrw();
void op_and_addrxb();
void op_and_addrxw();
void op_and_dpb();
void op_and_dpw();
void op_and_idpb();
void op_and_idpw();
void op_and_ildpb();
void op_and_ildpw();
void op_and_longb();
void op_and_longw();
void op_and_longxb();
void op_and_longxw();
void op_and_addryb();
void op_and_addryw();
void op_and_dpxb();
void op_and_dpxw();
void op_and_idpxb();
void op_and_idpxw();
void op_and_idpyb();
void op_and_idpyw();
void op_and_ildpyb();
void op_and_ildpyw();
void op_and_srb();
void op_and_srw();
void op_and_isryb();
void op_and_isryw();
//op_cmp
inline void flags_cmp_b();
inline void flags_cmp_w();
void op_cmp_constb();
void op_cmp_constw();
void op_cmp_addrb();
void op_cmp_addrw();
void op_cmp_addrxb();
void op_cmp_addrxw();
void op_cmp_dpb();
void op_cmp_dpw();
void op_cmp_idpb();
void op_cmp_idpw();
void op_cmp_ildpb();
void op_cmp_ildpw();
void op_cmp_longb();
void op_cmp_longw();
void op_cmp_longxb();
void op_cmp_longxw();
void op_cmp_addryb();
void op_cmp_addryw();
void op_cmp_dpxb();
void op_cmp_dpxw();
void op_cmp_idpxb();
void op_cmp_idpxw();
void op_cmp_idpyb();
void op_cmp_idpyw();
void op_cmp_ildpyb();
void op_cmp_ildpyw();
void op_cmp_srb();
void op_cmp_srw();
void op_cmp_isryb();
void op_cmp_isryw();
//op_eor
inline void flags_eor_b();
inline void flags_eor_w();
void op_eor_constb();
void op_eor_constw();
void op_eor_addrb();
void op_eor_addrw();
void op_eor_addrxb();
void op_eor_addrxw();
void op_eor_dpb();
void op_eor_dpw();
void op_eor_idpb();
void op_eor_idpw();
void op_eor_ildpb();
void op_eor_ildpw();
void op_eor_longb();
void op_eor_longw();
void op_eor_longxb();
void op_eor_longxw();
void op_eor_addryb();
void op_eor_addryw();
void op_eor_dpxb();
void op_eor_dpxw();
void op_eor_idpxb();
void op_eor_idpxw();
void op_eor_idpyb();
void op_eor_idpyw();
void op_eor_ildpyb();
void op_eor_ildpyw();
void op_eor_srb();
void op_eor_srw();
void op_eor_isryb();
void op_eor_isryw();
//op_incdec
void op_incb();
void op_incw();
void op_inc_addrb();
void op_inc_addrw();
void op_inc_addrxb();
void op_inc_addrxw();
void op_inc_dpb();
void op_inc_dpw();
void op_inc_dpxb();
void op_inc_dpxw();
void op_inxb();
void op_inxw();
void op_inyb();
void op_inyw();
void op_decb();
void op_decw();
void op_dec_addrb();
void op_dec_addrw();
void op_dec_addrxb();
void op_dec_addrxw();
void op_dec_dpb();
void op_dec_dpw();
void op_dec_dpxb();
void op_dec_dpxw();
void op_dexb();
void op_dexw();
void op_deyb();
void op_deyw();
//op_lda
inline void flags_lda_b();
inline void flags_lda_w();
void op_lda_constb();
void op_lda_constw();
void op_lda_addrb();
void op_lda_addrw();
void op_lda_addrxb();
void op_lda_addrxw();
void op_lda_dpb();
void op_lda_dpw();
void op_lda_idpb();
void op_lda_idpw();
void op_lda_ildpb();
void op_lda_ildpw();
void op_lda_longb();
void op_lda_longw();
void op_lda_longxb();
void op_lda_longxw();
void op_lda_addryb();
void op_lda_addryw();
void op_lda_dpxb();
void op_lda_dpxw();
void op_lda_idpxb();
void op_lda_idpxw();
void op_lda_idpyb();
void op_lda_idpyw();
void op_lda_ildpyb();
void op_lda_ildpyw();
void op_lda_srb();
void op_lda_srw();
void op_lda_isryb();
void op_lda_isryw();
//op_misc
inline void flags_bit_b();
inline void flags_bit_w();
void op_bit_constb();
void op_bit_constw();
void op_bit_addrb();
void op_bit_addrw();
void op_bit_addrxb();
void op_bit_addrxw();
void op_bit_dpb();
void op_bit_dpw();
void op_bit_dpxb();
void op_bit_dpxw();
inline void flags_cpx_b();
inline void flags_cpx_w();
void op_cpx_constb();
void op_cpx_constw();
void op_cpx_addrb();
void op_cpx_addrw();
void op_cpx_dpb();
void op_cpx_dpw();
inline void flags_cpy_b();
inline void flags_cpy_w();
void op_cpy_constb();
void op_cpy_constw();
void op_cpy_addrb();
void op_cpy_addrw();
void op_cpy_dpb();
void op_cpy_dpw();
inline void flags_ldx_b();
inline void flags_ldx_w();
void op_ldx_constb();
void op_ldx_constw();
void op_ldx_addrb();
void op_ldx_addrw();
void op_ldx_addryb();
void op_ldx_addryw();
void op_ldx_dpb();
void op_ldx_dpw();
void op_ldx_dpyb();
void op_ldx_dpyw();
inline void flags_ldy_b();
inline void flags_ldy_w();
void op_ldy_constb();
void op_ldy_constw();
void op_ldy_addrb();
void op_ldy_addrw();
void op_ldy_addrxb();
void op_ldy_addrxw();
void op_ldy_dpb();
void op_ldy_dpw();
void op_ldy_dpxb();
void op_ldy_dpxw();
void op_stx_addrb();
void op_stx_addrw();
void op_stx_dpb();
void op_stx_dpw();
void op_stx_dpyb();
void op_stx_dpyw();
void op_sty_addrb();
void op_sty_addrw();
void op_sty_dpb();
void op_sty_dpw();
void op_sty_dpxb();
void op_sty_dpxw();
void op_stz_addrb();
void op_stz_addrw();
void op_stz_addrxb();
void op_stz_addrxw();
void op_stz_dpb();
void op_stz_dpw();
void op_stz_dpxb();
void op_stz_dpxw();
void op_xba();
void op_trb_addrb();
void op_trb_addrw();
void op_trb_dpb();
void op_trb_dpw();
void op_tsb_addrb();
void op_tsb_addrw();
void op_tsb_dpb();
void op_tsb_dpw();
void op_mvn();
void op_mvp();
void op_brk();
void op_cop();
void op_stp();
void op_wai();
void op_xce();
void op_nop();
void op_wdm();
void op_clc();
void op_cld();
void op_cli();
void op_clv();
void op_sec();
void op_sed();
void op_sei();
void op_rep();
void op_sep();
void op_taxb();
void op_taxw();
void op_tayb();
void op_tayw();
void op_tcd();
void op_tcs();
void op_tdc();
void op_tsc();
void op_tsxb();
void op_tsxw();
void op_txab();
void op_txaw();
void op_txsb();
void op_txsw();
void op_txyb();
void op_txyw();
void op_tyab();
void op_tyaw();
void op_tyxb();
void op_tyxw();
//op_ora
inline void flags_ora_b();
inline void flags_ora_w();
void op_ora_constb();
void op_ora_constw();
void op_ora_addrb();
void op_ora_addrw();
void op_ora_addrxb();
void op_ora_addrxw();
void op_ora_dpb();
void op_ora_dpw();
void op_ora_idpb();
void op_ora_idpw();
void op_ora_ildpb();
void op_ora_ildpw();
void op_ora_longb();
void op_ora_longw();
void op_ora_longxb();
void op_ora_longxw();
void op_ora_addryb();
void op_ora_addryw();
void op_ora_dpxb();
void op_ora_dpxw();
void op_ora_idpxb();
void op_ora_idpxw();
void op_ora_idpyb();
void op_ora_idpyw();
void op_ora_ildpyb();
void op_ora_ildpyw();
void op_ora_srb();
void op_ora_srw();
void op_ora_isryb();
void op_ora_isryw();
//op_pc
void op_jmp_addr();
void op_jmp_long();
void op_jmp_iaddr();
void op_jmp_iaddrx();
void op_jmp_iladdr();
void op_jsr_addr();
void op_jsr_long();
void op_jsr_iaddrx();
void op_rtie();
void op_rtin();
void op_rts();
void op_rtl();
void op_bra();
void op_brl();
void op_bcc();
void op_bcs();
void op_bne();
void op_beq();
void op_bpl();
void op_bmi();
void op_bvc();
void op_bvs();
//op_sbc
inline void flags_sbc_b();
inline void flags_sbc_w();
void op_sbc_constb();
void op_sbc_constw();
void op_sbc_addrb();
void op_sbc_addrw();
void op_sbc_addrxb();
void op_sbc_addrxw();
void op_sbc_dpb();
void op_sbc_dpw();
void op_sbc_idpb();
void op_sbc_idpw();
void op_sbc_ildpb();
void op_sbc_ildpw();
void op_sbc_longb();
void op_sbc_longw();
void op_sbc_longxb();
void op_sbc_longxw();
void op_sbc_addryb();
void op_sbc_addryw();
void op_sbc_dpxb();
void op_sbc_dpxw();
void op_sbc_idpxb();
void op_sbc_idpxw();
void op_sbc_idpyb();
void op_sbc_idpyw();
void op_sbc_ildpyb();
void op_sbc_ildpyw();
void op_sbc_srb();
void op_sbc_srw();
void op_sbc_isryb();
void op_sbc_isryw();
//op_shift
void op_aslb();
void op_aslw();
void op_asl_addrb();
void op_asl_addrw();
void op_asl_addrxb();
void op_asl_addrxw();
void op_asl_dpb();
void op_asl_dpw();
void op_asl_dpxb();
void op_asl_dpxw();
void op_lsrb();
void op_lsrw();
void op_lsr_addrb();
void op_lsr_addrw();
void op_lsr_addrxb();
void op_lsr_addrxw();
void op_lsr_dpb();
void op_lsr_dpw();
void op_lsr_dpxb();
void op_lsr_dpxw();
void op_rolb();
void op_rolw();
void op_rol_addrb();
void op_rol_addrw();
void op_rol_addrxb();
void op_rol_addrxw();
void op_rol_dpb();
void op_rol_dpw();
void op_rol_dpxb();
void op_rol_dpxw();
void op_rorb();
void op_rorw();
void op_ror_addrb();
void op_ror_addrw();
void op_ror_addrxb();
void op_ror_addrxw();
void op_ror_dpb();
void op_ror_dpw();
void op_ror_dpxb();
void op_ror_dpxw();
//op_sta
void op_sta_addrb();
void op_sta_addrw();
void op_sta_addrxb();
void op_sta_addrxw();
void op_sta_dpb();
void op_sta_dpw();
void op_sta_idpb();
void op_sta_idpw();
void op_sta_ildpb();
void op_sta_ildpw();
void op_sta_longb();
void op_sta_longw();
void op_sta_longxb();
void op_sta_longxw();
void op_sta_addryb();
void op_sta_addryw();
void op_sta_dpxb();
void op_sta_dpxw();
void op_sta_idpxb();
void op_sta_idpxw();
void op_sta_idpyb();
void op_sta_idpyw();
void op_sta_ildpyb();
void op_sta_ildpyw();
void op_sta_srb();
void op_sta_srw();
void op_sta_isryb();
void op_sta_isryw();
//op_stack
void op_phab();
void op_phaw();
void op_phb();
void op_phd();
void op_phk();
void op_php();
void op_phxb();
void op_phxw();
void op_phyb();
void op_phyw();
void op_plab();
void op_plaw();
void op_plb();
void op_pld();
void op_plp();
void op_plxb();
void op_plxw();
void op_plyb();
void op_plyw();
void op_pea();
void op_pei();
void op_per();
enum { CYCLE_OPREAD, CYCLE_READ, CYCLE_WRITE, CYCLE_IO };
inline void pre_exec_cycle();
inline void exec_hdma();
inline void exec_dma();
inline void exec_cycle();
inline void last_cycle();
inline bool in_opcode();
bCPU();
~bCPU();

View File

@@ -1,519 +1,163 @@
void bCPU::exec_opcode() {
(this->*optbl[op_read()])();
snes->notify(SNES::CPU_EXEC_OPCODE);
void bCPU::last_cycle() {
time.nmi_pending |= nmi_test();
time.irq_pending |= irq_test();
run_state.irq = (time.nmi_pending || time.irq_pending);
}
void bCPU::init_op_tables() {
optbl = optbl_e;
void bCPU::pre_exec_cycle() {
if(!run_state.dma && !run_state.hdma)return;
/* 0x */
optbl[0x00] = op_brk;
optbl[0x01] = op_ora_idpxb;
optbl[0x02] = op_cop;
optbl[0x03] = op_ora_srb;
optbl[0x04] = op_tsb_dpb;
optbl[0x05] = op_ora_dpb;
optbl[0x06] = op_asl_dpb;
optbl[0x07] = op_ora_ildpb;
optbl[0x08] = op_php;
optbl[0x09] = op_ora_constb;
optbl[0x0a] = op_aslb;
optbl[0x0b] = op_phd;
optbl[0x0c] = op_tsb_addrb;
optbl[0x0d] = op_ora_addrb;
optbl[0x0e] = op_asl_addrb;
optbl[0x0f] = op_ora_longb;
/* 1x */
optbl[0x10] = op_bpl;
optbl[0x11] = op_ora_idpyb;
optbl[0x12] = op_ora_idpb;
optbl[0x13] = op_ora_isryb;
optbl[0x14] = op_trb_dpb;
optbl[0x15] = op_ora_dpxb;
optbl[0x16] = op_asl_dpxb;
optbl[0x17] = op_ora_ildpyb;
optbl[0x18] = op_clc;
optbl[0x19] = op_ora_addryb;
optbl[0x1a] = op_incb;
optbl[0x1b] = op_tcs;
optbl[0x1c] = op_trb_addrb;
optbl[0x1d] = op_ora_addrxb;
optbl[0x1e] = op_asl_addrxb;
optbl[0x1f] = op_ora_longxb;
/* 2x */
optbl[0x20] = op_jsr_addr;
optbl[0x21] = op_and_idpxb;
optbl[0x22] = op_jsr_long;
optbl[0x23] = op_and_srb;
optbl[0x24] = op_bit_dpb;
optbl[0x25] = op_and_dpb;
optbl[0x26] = op_rol_dpb;
optbl[0x27] = op_and_ildpb;
optbl[0x28] = op_plp;
optbl[0x29] = op_and_constb;
optbl[0x2a] = op_rolb;
optbl[0x2b] = op_pld;
optbl[0x2c] = op_bit_addrb;
optbl[0x2d] = op_and_addrb;
optbl[0x2e] = op_rol_addrb;
optbl[0x2f] = op_and_longb;
/* 3x */
optbl[0x30] = op_bmi;
optbl[0x31] = op_and_idpyb;
optbl[0x32] = op_and_idpb;
optbl[0x33] = op_and_isryb;
optbl[0x34] = op_bit_dpxb;
optbl[0x35] = op_and_dpxb;
optbl[0x36] = op_rol_dpxb;
optbl[0x37] = op_and_ildpyb;
optbl[0x38] = op_sec;
optbl[0x39] = op_and_addryb;
optbl[0x3a] = op_decb;
optbl[0x3b] = op_tsc;
optbl[0x3c] = op_bit_addrxb;
optbl[0x3d] = op_and_addrxb;
optbl[0x3e] = op_rol_addrxb;
optbl[0x3f] = op_and_longxb;
/* 4x */
optbl[0x40] = op_rtie;
optbl[0x41] = op_eor_idpxb;
optbl[0x42] = op_wdm;
optbl[0x43] = op_eor_srb;
optbl[0x44] = op_mvp;
optbl[0x45] = op_eor_dpb;
optbl[0x46] = op_lsr_dpb;
optbl[0x47] = op_eor_ildpb;
optbl[0x48] = op_phab;
optbl[0x49] = op_eor_constb;
optbl[0x4a] = op_lsrb;
optbl[0x4b] = op_phk;
optbl[0x4c] = op_jmp_addr;
optbl[0x4d] = op_eor_addrb;
optbl[0x4e] = op_lsr_addrb;
optbl[0x4f] = op_eor_longb;
/* 5x */
optbl[0x50] = op_bvc;
optbl[0x51] = op_eor_idpyb;
optbl[0x52] = op_eor_idpb;
optbl[0x53] = op_eor_isryb;
optbl[0x54] = op_mvn;
optbl[0x55] = op_eor_dpxb;
optbl[0x56] = op_lsr_dpxb;
optbl[0x57] = op_eor_ildpyb;
optbl[0x58] = op_cli;
optbl[0x59] = op_eor_addryb;
optbl[0x5a] = op_phyb;
optbl[0x5b] = op_tcd;
optbl[0x5c] = op_jmp_long;
optbl[0x5d] = op_eor_addrxb;
optbl[0x5e] = op_lsr_addrxb;
optbl[0x5f] = op_eor_longxb;
/* 6x */
optbl[0x60] = op_rts;
optbl[0x61] = op_adc_idpxb;
optbl[0x62] = op_per;
optbl[0x63] = op_adc_srb;
optbl[0x64] = op_stz_dpb;
optbl[0x65] = op_adc_dpb;
optbl[0x66] = op_ror_dpb;
optbl[0x67] = op_adc_ildpb;
optbl[0x68] = op_plab;
optbl[0x69] = op_adc_constb;
optbl[0x6a] = op_rorb;
optbl[0x6b] = op_rtl;
optbl[0x6c] = op_jmp_iaddr;
optbl[0x6d] = op_adc_addrb;
optbl[0x6e] = op_ror_addrb;
optbl[0x6f] = op_adc_longb;
/* 7x */
optbl[0x70] = op_bvs;
optbl[0x71] = op_adc_idpyb;
optbl[0x72] = op_adc_idpb;
optbl[0x73] = op_adc_isryb;
optbl[0x74] = op_stz_dpxb;
optbl[0x75] = op_adc_dpxb;
optbl[0x76] = op_ror_dpxb;
optbl[0x77] = op_adc_ildpyb;
optbl[0x78] = op_sei;
optbl[0x79] = op_adc_addryb;
optbl[0x7a] = op_plyb;
optbl[0x7b] = op_tdc;
optbl[0x7c] = op_jmp_iaddrx;
optbl[0x7d] = op_adc_addrxb;
optbl[0x7e] = op_ror_addrxb;
optbl[0x7f] = op_adc_longxb;
/* 8x */
optbl[0x80] = op_bra;
optbl[0x81] = op_sta_idpxb;
optbl[0x82] = op_brl;
optbl[0x83] = op_sta_srb;
optbl[0x84] = op_sty_dpb;
optbl[0x85] = op_sta_dpb;
optbl[0x86] = op_stx_dpb;
optbl[0x87] = op_sta_ildpb;
optbl[0x88] = op_deyb;
optbl[0x89] = op_bit_constb;
optbl[0x8a] = op_txab;
optbl[0x8b] = op_phb;
optbl[0x8c] = op_sty_addrb;
optbl[0x8d] = op_sta_addrb;
optbl[0x8e] = op_stx_addrb;
optbl[0x8f] = op_sta_longb;
/* 9x */
optbl[0x90] = op_bcc;
optbl[0x91] = op_sta_idpyb;
optbl[0x92] = op_sta_idpb;
optbl[0x93] = op_sta_isryb;
optbl[0x94] = op_sty_dpxb;
optbl[0x95] = op_sta_dpxb;
optbl[0x96] = op_stx_dpyb;
optbl[0x97] = op_sta_ildpyb;
optbl[0x98] = op_tyab;
optbl[0x99] = op_sta_addryb;
optbl[0x9a] = op_txsb;
optbl[0x9b] = op_txyb;
optbl[0x9c] = op_stz_addrb;
optbl[0x9d] = op_sta_addrxb;
optbl[0x9e] = op_stz_addrxb;
optbl[0x9f] = op_sta_longxb;
/* ax */
optbl[0xa0] = op_ldy_constb;
optbl[0xa1] = op_lda_idpxb;
optbl[0xa2] = op_ldx_constb;
optbl[0xa3] = op_lda_srb;
optbl[0xa4] = op_ldy_dpb;
optbl[0xa5] = op_lda_dpb;
optbl[0xa6] = op_ldx_dpb;
optbl[0xa7] = op_lda_ildpb;
optbl[0xa8] = op_tayb;
optbl[0xa9] = op_lda_constb;
optbl[0xaa] = op_taxb;
optbl[0xab] = op_plb;
optbl[0xac] = op_ldy_addrb;
optbl[0xad] = op_lda_addrb;
optbl[0xae] = op_ldx_addrb;
optbl[0xaf] = op_lda_longb;
/* bx */
optbl[0xb0] = op_bcs;
optbl[0xb1] = op_lda_idpyb;
optbl[0xb2] = op_lda_idpb;
optbl[0xb3] = op_lda_isryb;
optbl[0xb4] = op_ldy_dpxb;
optbl[0xb5] = op_lda_dpxb;
optbl[0xb6] = op_ldx_dpyb;
optbl[0xb7] = op_lda_ildpyb;
optbl[0xb8] = op_clv;
optbl[0xb9] = op_lda_addryb;
optbl[0xba] = op_tsxb;
optbl[0xbb] = op_tyxb;
optbl[0xbc] = op_ldy_addrxb;
optbl[0xbd] = op_lda_addrxb;
optbl[0xbe] = op_ldx_addryb;
optbl[0xbf] = op_lda_longxb;
/* cx */
optbl[0xc0] = op_cpy_constb;
optbl[0xc1] = op_cmp_idpxb;
optbl[0xc2] = op_rep;
optbl[0xc3] = op_cmp_srb;
optbl[0xc4] = op_cpy_dpb;
optbl[0xc5] = op_cmp_dpb;
optbl[0xc6] = op_dec_dpb;
optbl[0xc7] = op_cmp_ildpb;
optbl[0xc8] = op_inyb;
optbl[0xc9] = op_cmp_constb;
optbl[0xca] = op_dexb;
optbl[0xcb] = op_wai;
optbl[0xcc] = op_cpy_addrb;
optbl[0xcd] = op_cmp_addrb;
optbl[0xce] = op_dec_addrb;
optbl[0xcf] = op_cmp_longb;
/* dx */
optbl[0xd0] = op_bne;
optbl[0xd1] = op_cmp_idpyb;
optbl[0xd2] = op_cmp_idpb;
optbl[0xd3] = op_cmp_isryb;
optbl[0xd4] = op_pei;
optbl[0xd5] = op_cmp_dpxb;
optbl[0xd6] = op_dec_dpxb;
optbl[0xd7] = op_cmp_ildpyb;
optbl[0xd8] = op_cld;
optbl[0xd9] = op_cmp_addryb;
optbl[0xda] = op_phxb;
optbl[0xdb] = op_stp;
optbl[0xdc] = op_jmp_iladdr;
optbl[0xdd] = op_cmp_addrxb;
optbl[0xde] = op_dec_addrxb;
optbl[0xdf] = op_cmp_longxb;
/* ex */
optbl[0xe0] = op_cpx_constb;
optbl[0xe1] = op_sbc_idpxb;
optbl[0xe2] = op_sep;
optbl[0xe3] = op_sbc_srb;
optbl[0xe4] = op_cpx_dpb;
optbl[0xe5] = op_sbc_dpb;
optbl[0xe6] = op_inc_dpb;
optbl[0xe7] = op_sbc_ildpb;
optbl[0xe8] = op_inxb;
optbl[0xe9] = op_sbc_constb;
optbl[0xea] = op_nop;
optbl[0xeb] = op_xba;
optbl[0xec] = op_cpx_addrb;
optbl[0xed] = op_sbc_addrb;
optbl[0xee] = op_inc_addrb;
optbl[0xef] = op_sbc_longb;
/* fx */
optbl[0xf0] = op_beq;
optbl[0xf1] = op_sbc_idpyb;
optbl[0xf2] = op_sbc_idpb;
optbl[0xf3] = op_sbc_isryb;
optbl[0xf4] = op_pea;
optbl[0xf5] = op_sbc_dpxb;
optbl[0xf6] = op_inc_dpxb;
optbl[0xf7] = op_sbc_ildpyb;
optbl[0xf8] = op_sed;
optbl[0xf9] = op_sbc_addryb;
optbl[0xfa] = op_plxb;
optbl[0xfb] = op_xce;
optbl[0xfc] = op_jsr_iaddrx;
optbl[0xfd] = op_sbc_addrxb;
optbl[0xfe] = op_inc_addrxb;
optbl[0xff] = op_sbc_longxb;
int c, z;
if(run_state.hdma) {
switch(status.hdma_state) {
case HDMASTATE_ICPUSYNC:
case HDMASTATE_CPUSYNC:
c = status.cycle_count;
z = c - (status.hdma_cycle_count % c);
if(!z)z = c;
add_cycles(z);
run_state.hdma = false;
break;
}
}
memcpy(optbl_MX, optbl_e, sizeof(optbl_e));
memcpy(optbl_Mx, optbl_e, sizeof(optbl_e));
memcpy(optbl_mX, optbl_e, sizeof(optbl_e));
memcpy(optbl_mx, optbl_e, sizeof(optbl_e));
/* adc */
optbl_mX[0x69] = optbl_mx[0x69] = op_adc_constw;
optbl_mX[0x6d] = optbl_mx[0x6d] = op_adc_addrw;
optbl_mX[0x7d] = optbl_mx[0x7d] = op_adc_addrxw;
optbl_mX[0x65] = optbl_mx[0x65] = op_adc_dpw;
optbl_mX[0x72] = optbl_mx[0x72] = op_adc_idpw;
optbl_mX[0x67] = optbl_mx[0x67] = op_adc_ildpw;
optbl_mX[0x6f] = optbl_mx[0x6f] = op_adc_longw;
optbl_mX[0x7f] = optbl_mx[0x7f] = op_adc_longxw;
optbl_mX[0x79] = optbl_mx[0x79] = op_adc_addryw;
optbl_mX[0x75] = optbl_mx[0x75] = op_adc_dpxw;
optbl_mX[0x61] = optbl_mx[0x61] = op_adc_idpxw;
optbl_mX[0x71] = optbl_mx[0x71] = op_adc_idpyw;
optbl_mX[0x77] = optbl_mx[0x77] = op_adc_ildpyw;
optbl_mX[0x63] = optbl_mx[0x63] = op_adc_srw;
optbl_mX[0x73] = optbl_mx[0x73] = op_adc_isryw;
/* and */
optbl_mX[0x29] = optbl_mx[0x29] = op_and_constw;
optbl_mX[0x2d] = optbl_mx[0x2d] = op_and_addrw;
optbl_mX[0x3d] = optbl_mx[0x3d] = op_and_addrxw;
optbl_mX[0x25] = optbl_mx[0x25] = op_and_dpw;
optbl_mX[0x32] = optbl_mx[0x32] = op_and_idpw;
optbl_mX[0x27] = optbl_mx[0x27] = op_and_ildpw;
optbl_mX[0x2f] = optbl_mx[0x2f] = op_and_longw;
optbl_mX[0x3f] = optbl_mx[0x3f] = op_and_longxw;
optbl_mX[0x39] = optbl_mx[0x39] = op_and_addryw;
optbl_mX[0x35] = optbl_mx[0x35] = op_and_dpxw;
optbl_mX[0x21] = optbl_mx[0x21] = op_and_idpxw;
optbl_mX[0x31] = optbl_mx[0x31] = op_and_idpyw;
optbl_mX[0x37] = optbl_mx[0x37] = op_and_ildpyw;
optbl_mX[0x23] = optbl_mx[0x23] = op_and_srw;
optbl_mX[0x33] = optbl_mx[0x33] = op_and_isryw;
/* cmp */
optbl_mX[0xc9] = optbl_mx[0xc9] = op_cmp_constw;
optbl_mX[0xcd] = optbl_mx[0xcd] = op_cmp_addrw;
optbl_mX[0xdd] = optbl_mx[0xdd] = op_cmp_addrxw;
optbl_mX[0xc5] = optbl_mx[0xc5] = op_cmp_dpw;
optbl_mX[0xd2] = optbl_mx[0xd2] = op_cmp_idpw;
optbl_mX[0xc7] = optbl_mx[0xc7] = op_cmp_ildpw;
optbl_mX[0xcf] = optbl_mx[0xcf] = op_cmp_longw;
optbl_mX[0xdf] = optbl_mx[0xdf] = op_cmp_longxw;
optbl_mX[0xd9] = optbl_mx[0xd9] = op_cmp_addryw;
optbl_mX[0xd5] = optbl_mx[0xd5] = op_cmp_dpxw;
optbl_mX[0xc1] = optbl_mx[0xc1] = op_cmp_idpxw;
optbl_mX[0xd1] = optbl_mx[0xd1] = op_cmp_idpyw;
optbl_mX[0xd7] = optbl_mx[0xd7] = op_cmp_ildpyw;
optbl_mX[0xc3] = optbl_mx[0xc3] = op_cmp_srw;
optbl_mX[0xd3] = optbl_mx[0xd3] = op_cmp_isryw;
/* eor */
optbl_mX[0x49] = optbl_mx[0x49] = op_eor_constw;
optbl_mX[0x4d] = optbl_mx[0x4d] = op_eor_addrw;
optbl_mX[0x5d] = optbl_mx[0x5d] = op_eor_addrxw;
optbl_mX[0x45] = optbl_mx[0x45] = op_eor_dpw;
optbl_mX[0x52] = optbl_mx[0x52] = op_eor_idpw;
optbl_mX[0x47] = optbl_mx[0x47] = op_eor_ildpw;
optbl_mX[0x4f] = optbl_mx[0x4f] = op_eor_longw;
optbl_mX[0x5f] = optbl_mx[0x5f] = op_eor_longxw;
optbl_mX[0x59] = optbl_mx[0x59] = op_eor_addryw;
optbl_mX[0x55] = optbl_mx[0x55] = op_eor_dpxw;
optbl_mX[0x41] = optbl_mx[0x41] = op_eor_idpxw;
optbl_mX[0x51] = optbl_mx[0x51] = op_eor_idpyw;
optbl_mX[0x57] = optbl_mx[0x57] = op_eor_ildpyw;
optbl_mX[0x43] = optbl_mx[0x43] = op_eor_srw;
optbl_mX[0x53] = optbl_mx[0x53] = op_eor_isryw;
/* lda */
optbl_mX[0xa9] = optbl_mx[0xa9] = op_lda_constw;
optbl_mX[0xad] = optbl_mx[0xad] = op_lda_addrw;
optbl_mX[0xbd] = optbl_mx[0xbd] = op_lda_addrxw;
optbl_mX[0xa5] = optbl_mx[0xa5] = op_lda_dpw;
optbl_mX[0xb2] = optbl_mx[0xb2] = op_lda_idpw;
optbl_mX[0xa7] = optbl_mx[0xa7] = op_lda_ildpw;
optbl_mX[0xaf] = optbl_mx[0xaf] = op_lda_longw;
optbl_mX[0xbf] = optbl_mx[0xbf] = op_lda_longxw;
optbl_mX[0xb9] = optbl_mx[0xb9] = op_lda_addryw;
optbl_mX[0xb5] = optbl_mx[0xb5] = op_lda_dpxw;
optbl_mX[0xa1] = optbl_mx[0xa1] = op_lda_idpxw;
optbl_mX[0xb1] = optbl_mx[0xb1] = op_lda_idpyw;
optbl_mX[0xb7] = optbl_mx[0xb7] = op_lda_ildpyw;
optbl_mX[0xa3] = optbl_mx[0xa3] = op_lda_srw;
optbl_mX[0xb3] = optbl_mx[0xb3] = op_lda_isryw;
/* ora */
optbl_mX[0x09] = optbl_mx[0x09] = op_ora_constw;
optbl_mX[0x0d] = optbl_mx[0x0d] = op_ora_addrw;
optbl_mX[0x1d] = optbl_mx[0x1d] = op_ora_addrxw;
optbl_mX[0x05] = optbl_mx[0x05] = op_ora_dpw;
optbl_mX[0x12] = optbl_mx[0x12] = op_ora_idpw;
optbl_mX[0x07] = optbl_mx[0x07] = op_ora_ildpw;
optbl_mX[0x0f] = optbl_mx[0x0f] = op_ora_longw;
optbl_mX[0x1f] = optbl_mx[0x1f] = op_ora_longxw;
optbl_mX[0x19] = optbl_mx[0x19] = op_ora_addryw;
optbl_mX[0x15] = optbl_mx[0x15] = op_ora_dpxw;
optbl_mX[0x01] = optbl_mx[0x01] = op_ora_idpxw;
optbl_mX[0x11] = optbl_mx[0x11] = op_ora_idpyw;
optbl_mX[0x17] = optbl_mx[0x17] = op_ora_ildpyw;
optbl_mX[0x03] = optbl_mx[0x03] = op_ora_srw;
optbl_mX[0x13] = optbl_mx[0x13] = op_ora_isryw;
/* sbc */
optbl_mX[0xe9] = optbl_mx[0xe9] = op_sbc_constw;
optbl_mX[0xed] = optbl_mx[0xed] = op_sbc_addrw;
optbl_mX[0xfd] = optbl_mx[0xfd] = op_sbc_addrxw;
optbl_mX[0xe5] = optbl_mx[0xe5] = op_sbc_dpw;
optbl_mX[0xf2] = optbl_mx[0xf2] = op_sbc_idpw;
optbl_mX[0xe7] = optbl_mx[0xe7] = op_sbc_ildpw;
optbl_mX[0xef] = optbl_mx[0xef] = op_sbc_longw;
optbl_mX[0xff] = optbl_mx[0xff] = op_sbc_longxw;
optbl_mX[0xf9] = optbl_mx[0xf9] = op_sbc_addryw;
optbl_mX[0xf5] = optbl_mx[0xf5] = op_sbc_dpxw;
optbl_mX[0xe1] = optbl_mx[0xe1] = op_sbc_idpxw;
optbl_mX[0xf1] = optbl_mx[0xf1] = op_sbc_idpyw;
optbl_mX[0xf7] = optbl_mx[0xf7] = op_sbc_ildpyw;
optbl_mX[0xe3] = optbl_mx[0xe3] = op_sbc_srw;
optbl_mX[0xf3] = optbl_mx[0xf3] = op_sbc_isryw;
/* sta */
optbl_mX[0x8d] = optbl_mx[0x8d] = op_sta_addrw;
optbl_mX[0x9d] = optbl_mx[0x9d] = op_sta_addrxw;
optbl_mX[0x85] = optbl_mx[0x85] = op_sta_dpw;
optbl_mX[0x92] = optbl_mx[0x92] = op_sta_idpw;
optbl_mX[0x87] = optbl_mx[0x87] = op_sta_ildpw;
optbl_mX[0x8f] = optbl_mx[0x8f] = op_sta_longw;
optbl_mX[0x9f] = optbl_mx[0x9f] = op_sta_longxw;
optbl_mX[0x99] = optbl_mx[0x99] = op_sta_addryw;
optbl_mX[0x95] = optbl_mx[0x95] = op_sta_dpxw;
optbl_mX[0x81] = optbl_mx[0x81] = op_sta_idpxw;
optbl_mX[0x91] = optbl_mx[0x91] = op_sta_idpyw;
optbl_mX[0x97] = optbl_mx[0x97] = op_sta_ildpyw;
optbl_mX[0x83] = optbl_mx[0x83] = op_sta_srw;
optbl_mX[0x93] = optbl_mx[0x93] = op_sta_isryw;
/* incdec */
optbl_mX[0x1a] = optbl_mx[0x1a] = op_incw;
optbl_mX[0xee] = optbl_mx[0xee] = op_inc_addrw;
optbl_mX[0xfe] = optbl_mx[0xfe] = op_inc_addrxw;
optbl_mX[0xe6] = optbl_mx[0xe6] = op_inc_dpw;
optbl_mX[0xf6] = optbl_mx[0xf6] = op_inc_dpxw;
optbl_mX[0x3a] = optbl_mx[0x3a] = op_decw;
optbl_mX[0xce] = optbl_mx[0xce] = op_dec_addrw;
optbl_mX[0xde] = optbl_mx[0xde] = op_dec_addrxw;
optbl_mX[0xc6] = optbl_mx[0xc6] = op_dec_dpw;
optbl_mX[0xd6] = optbl_mx[0xd6] = op_dec_dpxw;
optbl_Mx[0xe8] = optbl_mx[0xe8] = op_inxw;
optbl_Mx[0xc8] = optbl_mx[0xc8] = op_inyw;
optbl_Mx[0xca] = optbl_mx[0xca] = op_dexw;
optbl_Mx[0x88] = optbl_mx[0x88] = op_deyw;
/* misc */
optbl_mX[0x89] = optbl_mx[0x89] = op_bit_constw;
optbl_mX[0x2c] = optbl_mx[0x2c] = op_bit_addrw;
optbl_mX[0x3c] = optbl_mx[0x3c] = op_bit_addrxw;
optbl_mX[0x24] = optbl_mx[0x24] = op_bit_dpw;
optbl_mX[0x34] = optbl_mx[0x34] = op_bit_dpxw;
optbl_mX[0x9c] = optbl_mx[0x9c] = op_stz_addrw;
optbl_mX[0x9e] = optbl_mx[0x9e] = op_stz_addrxw;
optbl_mX[0x64] = optbl_mx[0x64] = op_stz_dpw;
optbl_mX[0x74] = optbl_mx[0x74] = op_stz_dpxw;
optbl_mX[0x1c] = optbl_mx[0x1c] = op_trb_addrw;
optbl_mX[0x14] = optbl_mx[0x14] = op_trb_dpw;
optbl_mX[0x0c] = optbl_mx[0x0c] = op_tsb_addrw;
optbl_mX[0x04] = optbl_mx[0x04] = op_tsb_dpw;
optbl_mX[0x8a] = optbl_mx[0x8a] = op_txaw;
optbl_mX[0x98] = optbl_mx[0x98] = op_tyaw;
optbl_Mx[0xe0] = optbl_mx[0xe0] = op_cpx_constw;
optbl_Mx[0xec] = optbl_mx[0xec] = op_cpx_addrw;
optbl_Mx[0xe4] = optbl_mx[0xe4] = op_cpx_dpw;
optbl_Mx[0xc0] = optbl_mx[0xc0] = op_cpy_constw;
optbl_Mx[0xcc] = optbl_mx[0xcc] = op_cpy_addrw;
optbl_Mx[0xc4] = optbl_mx[0xc4] = op_cpy_dpw;
optbl_Mx[0xa2] = optbl_mx[0xa2] = op_ldx_constw;
optbl_Mx[0xae] = optbl_mx[0xae] = op_ldx_addrw;
optbl_Mx[0xbe] = optbl_mx[0xbe] = op_ldx_addryw;
optbl_Mx[0xa6] = optbl_mx[0xa6] = op_ldx_dpw;
optbl_Mx[0xb6] = optbl_mx[0xb6] = op_ldx_dpyw;
optbl_Mx[0xa0] = optbl_mx[0xa0] = op_ldy_constw;
optbl_Mx[0xac] = optbl_mx[0xac] = op_ldy_addrw;
optbl_Mx[0xbc] = optbl_mx[0xbc] = op_ldy_addrxw;
optbl_Mx[0xa4] = optbl_mx[0xa4] = op_ldy_dpw;
optbl_Mx[0xb4] = optbl_mx[0xb4] = op_ldy_dpxw;
optbl_Mx[0x8e] = optbl_mx[0x8e] = op_stx_addrw;
optbl_Mx[0x86] = optbl_mx[0x86] = op_stx_dpw;
optbl_Mx[0x96] = optbl_mx[0x96] = op_stx_dpyw;
optbl_Mx[0x8c] = optbl_mx[0x8c] = op_sty_addrw;
optbl_Mx[0x84] = optbl_mx[0x84] = op_sty_dpw;
optbl_Mx[0x94] = optbl_mx[0x94] = op_sty_dpxw;
optbl_Mx[0xaa] = optbl_mx[0xaa] = op_taxw;
optbl_Mx[0xa8] = optbl_mx[0xa8] = op_tayw;
optbl_Mx[0xba] = optbl_mx[0xba] = op_tsxw;
optbl_Mx[0x9a] = optbl_mx[0x9a] = op_txsw;
optbl_Mx[0x9b] = optbl_mx[0x9b] = op_txyw;
optbl_Mx[0xbb] = optbl_mx[0xbb] = op_tyxw;
/* pc */
optbl_MX[0x40] = optbl_Mx[0x40] = op_rtin;
optbl_mX[0x40] = optbl_mx[0x40] = op_rtin;
/* shift */
optbl_mX[0x0a] = optbl_mx[0x0a] = op_aslw;
optbl_mX[0x0e] = optbl_mx[0x0e] = op_asl_addrw;
optbl_mX[0x1e] = optbl_mx[0x1e] = op_asl_addrxw;
optbl_mX[0x06] = optbl_mx[0x06] = op_asl_dpw;
optbl_mX[0x16] = optbl_mx[0x16] = op_asl_dpxw;
optbl_mX[0x4a] = optbl_mx[0x4a] = op_lsrw;
optbl_mX[0x4e] = optbl_mx[0x4e] = op_lsr_addrw;
optbl_mX[0x5e] = optbl_mx[0x5e] = op_lsr_addrxw;
optbl_mX[0x46] = optbl_mx[0x46] = op_lsr_dpw;
optbl_mX[0x56] = optbl_mx[0x56] = op_lsr_dpxw;
optbl_mX[0x2a] = optbl_mx[0x2a] = op_rolw;
optbl_mX[0x2e] = optbl_mx[0x2e] = op_rol_addrw;
optbl_mX[0x3e] = optbl_mx[0x3e] = op_rol_addrxw;
optbl_mX[0x26] = optbl_mx[0x26] = op_rol_dpw;
optbl_mX[0x36] = optbl_mx[0x36] = op_rol_dpxw;
optbl_mX[0x6a] = optbl_mx[0x6a] = op_rorw;
optbl_mX[0x6e] = optbl_mx[0x6e] = op_ror_addrw;
optbl_mX[0x7e] = optbl_mx[0x7e] = op_ror_addrxw;
optbl_mX[0x66] = optbl_mx[0x66] = op_ror_dpw;
optbl_mX[0x76] = optbl_mx[0x76] = op_ror_dpxw;
/* stack */
optbl_mX[0x48] = optbl_mx[0x48] = op_phaw;
optbl_mX[0x68] = optbl_mx[0x68] = op_plaw;
optbl_Mx[0xda] = optbl_mx[0xda] = op_phxw;
optbl_Mx[0x5a] = optbl_mx[0x5a] = op_phyw;
optbl_Mx[0xfa] = optbl_mx[0xfa] = op_plxw;
optbl_Mx[0x7a] = optbl_mx[0x7a] = op_plyw;
if(run_state.dma) {
switch(status.dma_state) {
case DMASTATE_CPUSYNC:
c = status.cycle_count;
z = c - (status.dma_cycle_count % c);
if(!z)z = c;
add_cycles(z);
run_state.dma = false;
break;
}
}
}
void bCPU::exec_hdma() {
int n;
static int z;
switch(status.hdma_state) {
case HDMASTATE_IDMASYNC:
status.hdma_cycle_count = 0;
z = 0;
if(!run_state.dma) {
exec_cycle();
status.hdma_state = HDMASTATE_IDMASYNC2;
} else {
status.hdma_state = HDMASTATE_IDMASYNC3;
}
break;
case HDMASTATE_IDMASYNC2:
n = 8 - dma_counter() + 8;
add_cycles(n);
status.hdma_cycle_count += n;
status.hdma_state = HDMASTATE_IDMASYNC3;
break;
case HDMASTATE_IDMASYNC3:
hdma_init();
if(!run_state.dma) {
status.hdma_state = HDMASTATE_ICPUSYNC;
} else {
run_state.hdma = false;
}
break;
case HDMASTATE_ICPUSYNC:
exec_cycle();
break;
case HDMASTATE_DMASYNC:
status.hdma_cycle_count = 0;
z = 0;
if(!run_state.dma) {
exec_cycle();
status.hdma_state = HDMASTATE_DMASYNC2;
} else {
status.hdma_state = HDMASTATE_DMASYNC3;
}
break;
case HDMASTATE_DMASYNC2:
n = 8 - dma_counter() + 8;
add_cycles(n);
status.hdma_cycle_count += n;
status.hdma_state = HDMASTATE_DMASYNC3;
break;
case HDMASTATE_DMASYNC3:
if(channel[z].hdma_line_counter) {
add_cycles(8);
status.hdma_cycle_count += 8;
}
if(++z < 8)break;
status.hdma_state = HDMASTATE_RUN;
break;
case HDMASTATE_RUN:
hdma_run(); //updates status.hdma_cycle_count
if(!run_state.dma) {
status.hdma_state = HDMASTATE_CPUSYNC;
} else {
run_state.hdma = false;
}
break;
case HDMASTATE_CPUSYNC:
exec_cycle();
break;
}
}
void bCPU::exec_dma() {
int n;
static int z;
switch(status.dma_state) {
case DMASTATE_DMASYNC:
exec_cycle();
status.dma_state = DMASTATE_DMASYNC2;
break;
case DMASTATE_DMASYNC2:
n = 8 - dma_counter() + 8;
add_cycles(n);
status.dma_cycle_count = n;
z = 0;
status.dma_state = DMASTATE_DMASYNC3;
break;
case DMASTATE_DMASYNC3:
if(channel[z].dma_enabled == true) {
add_cycles(8);
status.dma_cycle_count += 8;
}
if(++z < 8)break;
status.dma_state = DMASTATE_RUN;
break;
case DMASTATE_RUN:
dma_run(); //updates status.dma_cycle_count
cycle_edge();
break;
case DMASTATE_CPUSYNC:
exec_cycle();
break;
}
}
void bCPU::exec_cycle() {
if(status.cycle_pos) {
(this->*optbl[status.opcode])();
#ifdef DEBUGGER
if(status.cycle_pos == 0) {
snes->notify(SNES::CPU_EXEC_OPCODE_END);
}
#endif
return;
}
//on first cycle?
#ifdef DEBUGGER
snes->notify(SNES::CPU_EXEC_OPCODE_BEGIN);
#endif
status.opcode = op_readpc();
status.cycle_pos = 1;
}
//only return true when we are on an opcode edge
bool bCPU::in_opcode() {
return (status.cycle_pos != 0);
}

50
src/cpu/bcpu/bcpu_int.cpp Normal file
View File

@@ -0,0 +1,50 @@
void bCPU::irq_run() {
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() {
if(time.nmi_transition == 0)return false;
time.nmi_transition = 0;
run_state.wai = false;
return true;
}
bool bCPU::irq_test() {
if(time.irq_transition == 1)goto _true;
if(time.irq_read == 0) {
if(time.irq_line == 1 && (irq_trigger_pos_match(0) || irq_trigger_pos_match(2))) {
return false;
}
goto _true;
}
if(time.irq_line == 0) {
time.irq_line = 1;
goto _true;
}
return false;
_true:
time.irq_transition = 0;
run_state.wai = false;
return (regs.p.i) ? false : true;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,464 +0,0 @@
inline void bCPU::flags_adc_b() {
int32 r = regs.a.l + rd.l + regs.p.c;
//bcd
if(regs.p.d) {
if(((r ) & 15) > 9)r += 6;
if(((r >> 4) & 15) > 9)r += 6 << 4;
}
regs.p.n = !!(r & 0x80);
regs.p.v = !!(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
regs.p.z = ((byte)r == 0);
regs.p.c = (r > 0xff);
regs.a.l = r;
}
inline void bCPU::flags_adc_w() {
int32 r = regs.a.w + rd.w + regs.p.c;
//bcd
if(regs.p.d) {
if(((r ) & 15) > 9)r += 6;
if(((r >> 4) & 15) > 9)r += 6 << 4;
if(((r >> 8) & 15) > 9)r += 6 << 8;
if(((r >> 12) & 15) > 9)r += 6 << 12;
}
regs.p.n = !!(r & 0x8000);
regs.p.v = !!(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
regs.p.z = ((word)r == 0);
regs.p.c = (r > 0xffff);
regs.a.w = r;
}
/************************
*** 0x69: adc #const ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; idl
[2a] pbr,pc+2 ; idh [1]
*/
void bCPU::op_adc_constb() {
rd.l = op_read(); //2
flags_adc_b();
}
void bCPU::op_adc_constw() {
rd.l = op_read(); //2
rd.h = op_read(); //2a
flags_adc_w();
}
/**********************
*** 0x6d: adc addr ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aa ; data low
[4a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_adc_addrb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_DBR, aa.w); //4
flags_adc_b();
}
void bCPU::op_adc_addrw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_DBR, aa.w); //4
rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a
flags_adc_w();
}
/************************
*** 0x7d: adc addr,x ***
************************
cycles:
[1 ] pbr,pc ; operadc
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[3a] dbr,aah,aal+xl ; io [4]
[4 ] dbr,aa+x ; data low
[4a] dbr,aa+x+1 ; data high [1]
*/
void bCPU::op_adc_addrxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.x.w); //3a
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4
flags_adc_b();
}
void bCPU::op_adc_addrxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.x.w); //3a
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a
flags_adc_w();
}
/********************
*** 0x65: adc dp ***
********************
cycles:
[1 ] pbr,pc ; operadc
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; data low
[3a] 0,d+dp+1 ; data high [1]
*/
void bCPU::op_adc_dpb() {
dp = op_read(); //2
cpu_c2(); //2a
rd.l = op_read(OPMODE_DP, dp); //3
flags_adc_b();
}
void bCPU::op_adc_dpw() {
dp = op_read(); //2
cpu_c2(); //2a
rd.l = op_read(OPMODE_DP, dp); //3
rd.h = op_read(OPMODE_DP, dp + 1); //3a
flags_adc_w();
}
/**********************
*** 0x72: adc (dp) ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] dbr,aa ; data low
[5a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_adc_idpb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
rd.l = op_read(OPMODE_DBR, aa.w); //5
flags_adc_b();
}
void bCPU::op_adc_idpw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
rd.l = op_read(OPMODE_DBR, aa.w); //5
rd.h = op_read(OPMODE_DBR, aa.w + 1); //5
flags_adc_w();
}
/**********************
*** 0x67: adc [dp] ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] 0,d+dp+2 ; aab
[6 ] aab,aa ; data low
[6a] aab,aa+1 ; data high [1]
*/
void bCPU::op_adc_ildpb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
rd.l = op_read(OPMODE_LONG, aa.d); //6
flags_adc_b();
}
void bCPU::op_adc_ildpw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
rd.l = op_read(OPMODE_LONG, aa.d); //6
rd.h = op_read(OPMODE_LONG, aa.d + 1); //6a
flags_adc_w();
}
/**********************
*** 0x6f: adc long ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] pbr,pc+3 ; aab
[5 ] aab,aa ; data low
[5a] aab,aa+1 ; data high
*/
void bCPU::op_adc_longb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
rd.l = op_read(OPMODE_LONG, aa.d); //5
flags_adc_b();
}
void bCPU::op_adc_longw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
rd.l = op_read(OPMODE_LONG, aa.d); //5
rd.h = op_read(OPMODE_LONG, aa.d + 1); //5a
flags_adc_w();
}
/************************
*** 0x7f: adc long,x ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] pbr,pc+3 ; aab
[5 ] aab,aa+x ; data low
[5a] aab,aa+x+1 ; data high
*/
void bCPU::op_adc_longxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5
flags_adc_b();
}
void bCPU::op_adc_longxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5
rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a
flags_adc_w();
}
/************************
*** 0x79: adc addr,y ***
************************
cycles:
[1 ] pbr,pc ; operadc
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[3a] dbr,aah,aal+yl ; io [4]
[4 ] dbr,aa+y ; data low
[4a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_adc_addryb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.y.w); //3a
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4
flags_adc_b();
}
void bCPU::op_adc_addryw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.y.w); //3a
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a
flags_adc_w();
}
/**********************
*** 0x75: adc dp,x ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; data low
[4a] 0,d+dp+x+1 ; data high
*/
void bCPU::op_adc_dpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
flags_adc_b();
}
void bCPU::op_adc_dpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
flags_adc_w();
}
/************************
*** 0x61: adc (dp,x) ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; aal
[5 ] 0,d+dp+x+1 ; aah
[6 ] dbr,aa ; data low
[6a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_adc_idpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
rd.l = op_read(OPMODE_DBR, aa.w); //6
flags_adc_b();
}
void bCPU::op_adc_idpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
rd.l = op_read(OPMODE_DBR, aa.w); //6
rd.h = op_read(OPMODE_DBR, aa.w + 1); //6a
flags_adc_w();
}
/************************
*** 0x71: adc (dp),y ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[4a] dbr,aah,aal+yl ; io [4]
[5 ] dbr,aa+y ; data low
[5a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_adc_idpyb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
cpu_c4(aa.w, aa.w + regs.y.w); //4a
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5
flags_adc_b();
}
void bCPU::op_adc_idpyw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
cpu_c4(aa.w, aa.w + regs.y.w); //4a
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a
flags_adc_w();
}
/************************
*** 0x77: adc [dp],y ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] 0,d+dp+2 ; aab
[6 ] aab,aa+y ; data low
[6a] aab,aa+y+1 ; data high [1]
*/
void bCPU::op_adc_ildpyb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6
flags_adc_b();
}
void bCPU::op_adc_ildpyw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6
rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a
flags_adc_w();
}
/**********************
*** 0x63: adc sr,s ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; sp
[3 ] pbr,pc+1 ; io
[4 ] 0,s+sp ; data low
[4a] 0,s+sp+1 ; data high [1]
*/
void bCPU::op_adc_srb() {
sp = op_read(); //2
cpu_io(); //3
rd.l = op_read(OPMODE_SP, sp); //4
flags_adc_b();
}
void bCPU::op_adc_srw() {
sp = op_read(); //2
cpu_io(); //3
rd.l = op_read(OPMODE_SP, sp); //4
rd.h = op_read(OPMODE_SP, sp + 1); //4a
flags_adc_w();
}
/**************************
*** 0x73: adc (sr,s),y ***
**************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; sp
[3 ] pbr,pc+1 ; io
[4 ] 0,s+sp ; aal
[5 ] 0,s+sp+1 ; aah
[6 ] 0,s+sp+1 ; io
[7 ] dbr,aa+y ; data low
[7a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_adc_isryb() {
sp = op_read(); //2
cpu_io(); //3
aa.l = op_read(OPMODE_SP, sp); //4
aa.h = op_read(OPMODE_SP, sp + 1); //5
cpu_io(); //6
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7
flags_adc_b();
}
void bCPU::op_adc_isryw() {
sp = op_read(); //2
cpu_io(); //3
aa.l = op_read(OPMODE_SP, sp); //4
aa.h = op_read(OPMODE_SP, sp + 1); //5
cpu_io(); //6
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a
flags_adc_w();
}

View File

@@ -1,444 +0,0 @@
inline void bCPU::flags_and_b() {
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
inline void bCPU::flags_and_w() {
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
/************************
*** 0x29: and #const ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; idl
[2a] pbr,pc+2 ; idh [1]
*/
void bCPU::op_and_constb() {
regs.a.l &= op_read(); //2
flags_and_b();
}
void bCPU::op_and_constw() {
regs.a.l &= op_read(); //2
regs.a.h &= op_read(); //2a
flags_and_w();
}
/**********************
*** 0x2d: and addr ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aa ; data low
[4a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_and_addrb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
regs.a.l &= op_read(OPMODE_DBR, aa.w); //4
flags_and_b();
}
void bCPU::op_and_addrw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
regs.a.l &= op_read(OPMODE_DBR, aa.w); //4
regs.a.h &= op_read(OPMODE_DBR, aa.w + 1); //4a
flags_and_w();
}
/************************
*** 0x3d: and addr,x ***
************************
cycles:
[1 ] pbr,pc ; operand
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[3a] dbr,aah,aal+xl ; io [4]
[4 ] dbr,aa+x ; data low
[4a] dbr,aa+x+1 ; data high [1]
*/
void bCPU::op_and_addrxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.x.w); //3a
regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.x.w); //4
flags_and_b();
}
void bCPU::op_and_addrxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.x.w); //3a
regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.x.w); //4
regs.a.h &= op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a
flags_and_w();
}
/********************
*** 0x25: and dp ***
********************
cycles:
[1 ] pbr,pc ; operand
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; data low
[3a] 0,d+dp+1 ; data high [1]
*/
void bCPU::op_and_dpb() {
dp = op_read(); //2
cpu_c2(); //2a
regs.a.l &= op_read(OPMODE_DP, dp); //3
flags_and_b();
}
void bCPU::op_and_dpw() {
dp = op_read(); //2
cpu_c2(); //2a
regs.a.l &= op_read(OPMODE_DP, dp); //3
regs.a.h &= op_read(OPMODE_DP, dp + 1); //3a
flags_and_w();
}
/**********************
*** 0x32: and (dp) ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] dbr,aa ; data low
[5a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_and_idpb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
regs.a.l &= op_read(OPMODE_DBR, aa.w); //5
flags_and_b();
}
void bCPU::op_and_idpw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
regs.a.l &= op_read(OPMODE_DBR, aa.w); //5
regs.a.h &= op_read(OPMODE_DBR, aa.w + 1); //5
flags_and_w();
}
/**********************
*** 0x27: and [dp] ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] 0,d+dp+2 ; aab
[6 ] aab,aa ; data low
[6a] aab,aa+1 ; data high [1]
*/
void bCPU::op_and_ildpb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
regs.a.l &= op_read(OPMODE_LONG, aa.d); //6
flags_and_b();
}
void bCPU::op_and_ildpw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
regs.a.l &= op_read(OPMODE_LONG, aa.d); //6
regs.a.h &= op_read(OPMODE_LONG, aa.d + 1); //6a
flags_and_w();
}
/**********************
*** 0x2f: and long ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] pbr,pc+3 ; aab
[5 ] aab,aa ; data low
[5a] aab,aa+1 ; data high
*/
void bCPU::op_and_longb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
regs.a.l &= op_read(OPMODE_LONG, aa.d); //5
flags_and_b();
}
void bCPU::op_and_longw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
regs.a.l &= op_read(OPMODE_LONG, aa.d); //5
regs.a.h &= op_read(OPMODE_LONG, aa.d + 1); //5a
flags_and_w();
}
/************************
*** 0x3f: and long,x ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] pbr,pc+3 ; aab
[5 ] aab,aa+x ; data low
[5a] aab,aa+x+1 ; data high
*/
void bCPU::op_and_longxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
regs.a.l &= op_read(OPMODE_LONG, aa.d + regs.x.w); //5
flags_and_b();
}
void bCPU::op_and_longxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
regs.a.l &= op_read(OPMODE_LONG, aa.d + regs.x.w); //5
regs.a.h &= op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a
flags_and_w();
}
/************************
*** 0x39: and addr,y ***
************************
cycles:
[1 ] pbr,pc ; operand
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[3a] dbr,aah,aal+yl ; io [4]
[4 ] dbr,aa+y ; data low
[4a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_and_addryb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.y.w); //3a
regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.y.w); //4
flags_and_b();
}
void bCPU::op_and_addryw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.y.w); //3a
regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.y.w); //4
regs.a.h &= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a
flags_and_w();
}
/**********************
*** 0x35: and dp,x ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; data low
[4a] 0,d+dp+x+1 ; data high
*/
void bCPU::op_and_dpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
regs.a.l &= op_read(OPMODE_DP, dp + regs.x.w); //4
flags_and_b();
}
void bCPU::op_and_dpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
regs.a.l &= op_read(OPMODE_DP, dp + regs.x.w); //4
regs.a.h &= op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
flags_and_w();
}
/************************
*** 0x21: and (dp,x) ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; aal
[5 ] 0,d+dp+x+1 ; aah
[6 ] dbr,aa ; data low
[6a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_and_idpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
regs.a.l &= op_read(OPMODE_DBR, aa.w); //6
flags_and_b();
}
void bCPU::op_and_idpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
regs.a.l &= op_read(OPMODE_DBR, aa.w); //6
regs.a.h &= op_read(OPMODE_DBR, aa.w + 1); //6a
flags_and_w();
}
/************************
*** 0x31: and (dp),y ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[4a] dbr,aah,aal+yl ; io [4]
[5 ] dbr,aa+y ; data low
[5a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_and_idpyb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
cpu_c4(aa.w, aa.w + regs.y.w); //4a
regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.y.w); //5
flags_and_b();
}
void bCPU::op_and_idpyw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
cpu_c4(aa.w, aa.w + regs.y.w); //4a
regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.y.w); //5
regs.a.h &= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a
flags_and_w();
}
/************************
*** 0x37: and [dp],y ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] 0,d+dp+2 ; aab
[6 ] aab,aa+y ; data low
[6a] aab,aa+y+1 ; data high [1]
*/
void bCPU::op_and_ildpyb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
regs.a.l &= op_read(OPMODE_LONG, aa.d + regs.y.w); //6
flags_and_b();
}
void bCPU::op_and_ildpyw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
regs.a.l &= op_read(OPMODE_LONG, aa.d + regs.y.w); //6
regs.a.h &= op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a
flags_and_w();
}
/**********************
*** 0x23: and sr,s ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; sp
[3 ] pbr,pc+1 ; io
[4 ] 0,s+sp ; data low
[4a] 0,s+sp+1 ; data high [1]
*/
void bCPU::op_and_srb() {
sp = op_read(); //2
cpu_io(); //3
regs.a.l &= op_read(OPMODE_SP, sp); //4
flags_and_b();
}
void bCPU::op_and_srw() {
sp = op_read(); //2
cpu_io(); //3
regs.a.l &= op_read(OPMODE_SP, sp); //4
regs.a.h &= op_read(OPMODE_SP, sp + 1); //4a
flags_and_w();
}
/**************************
*** 0x33: and (sr,s),y ***
**************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; sp
[3 ] pbr,pc+1 ; io
[4 ] 0,s+sp ; aal
[5 ] 0,s+sp+1 ; aah
[6 ] 0,s+sp+1 ; io
[7 ] dbr,aa+y ; data low
[7a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_and_isryb() {
sp = op_read(); //2
cpu_io(); //3
aa.l = op_read(OPMODE_SP, sp); //4
aa.h = op_read(OPMODE_SP, sp + 1); //5
cpu_io(); //6
regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.y.w); //7
flags_and_b();
}
void bCPU::op_and_isryw() {
sp = op_read(); //2
cpu_io(); //3
aa.l = op_read(OPMODE_SP, sp); //4
aa.h = op_read(OPMODE_SP, sp + 1); //5
cpu_io(); //6
regs.a.l &= op_read(OPMODE_DBR, aa.w + regs.y.w); //7
regs.a.h &= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a
flags_and_w();
}

View File

@@ -1,448 +0,0 @@
inline void bCPU::flags_cmp_b() {
int32 r = regs.a.l - rd.l;
regs.p.n = !!(r & 0x80);
regs.p.z = ((uint8)r == 0);
regs.p.c = (r >= 0);
}
inline void bCPU::flags_cmp_w() {
int32 r = regs.a.w - rd.w;
regs.p.n = !!(r & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.p.c = (r >= 0);
}
/************************
*** 0xc9: cmp #const ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; idl
[2a] pbr,pc+2 ; idh [1]
*/
void bCPU::op_cmp_constb() {
rd.l = op_read(); //2
flags_cmp_b();
}
void bCPU::op_cmp_constw() {
rd.l = op_read(); //2
rd.h = op_read(); //2a
flags_cmp_w();
}
/**********************
*** 0xcd: cmp addr ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aa ; data low
[4a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_cmp_addrb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_DBR, aa.w); //4
flags_cmp_b();
}
void bCPU::op_cmp_addrw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_DBR, aa.w); //4
rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a
flags_cmp_w();
}
/************************
*** 0xdd: cmp addr,x ***
************************
cycles:
[1 ] pbr,pc ; opercmp
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[3a] dbr,aah,aal+xl ; io [4]
[4 ] dbr,aa+x ; data low
[4a] dbr,aa+x+1 ; data high [1]
*/
void bCPU::op_cmp_addrxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.x.w); //3a
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4
flags_cmp_b();
}
void bCPU::op_cmp_addrxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.x.w); //3a
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a
flags_cmp_w();
}
/********************
*** 0xc5: cmp dp ***
********************
cycles:
[1 ] pbr,pc ; opercmp
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; data low
[3a] 0,d+dp+1 ; data high [1]
*/
void bCPU::op_cmp_dpb() {
dp = op_read(); //2
cpu_c2(); //2a
rd.l = op_read(OPMODE_DP, dp); //3
flags_cmp_b();
}
void bCPU::op_cmp_dpw() {
dp = op_read(); //2
cpu_c2(); //2a
rd.l = op_read(OPMODE_DP, dp); //3
rd.h = op_read(OPMODE_DP, dp + 1); //3a
flags_cmp_w();
}
/**********************
*** 0xd2: cmp (dp) ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] dbr,aa ; data low
[5a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_cmp_idpb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
rd.l = op_read(OPMODE_DBR, aa.w); //5
flags_cmp_b();
}
void bCPU::op_cmp_idpw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
rd.l = op_read(OPMODE_DBR, aa.w); //5
rd.h = op_read(OPMODE_DBR, aa.w + 1); //5
flags_cmp_w();
}
/**********************
*** 0xc7: cmp [dp] ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] 0,d+dp+2 ; aab
[6 ] aab,aa ; data low
[6a] aab,aa+1 ; data high [1]
*/
void bCPU::op_cmp_ildpb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
rd.l = op_read(OPMODE_LONG, aa.d); //6
flags_cmp_b();
}
void bCPU::op_cmp_ildpw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
rd.l = op_read(OPMODE_LONG, aa.d); //6
rd.h = op_read(OPMODE_LONG, aa.d + 1); //6a
flags_cmp_w();
}
/**********************
*** 0xcf: cmp long ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] pbr,pc+3 ; aab
[5 ] aab,aa ; data low
[5a] aab,aa+1 ; data high
*/
void bCPU::op_cmp_longb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
rd.l = op_read(OPMODE_LONG, aa.d); //5
flags_cmp_b();
}
void bCPU::op_cmp_longw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
rd.l = op_read(OPMODE_LONG, aa.d); //5
rd.h = op_read(OPMODE_LONG, aa.d + 1); //5a
flags_cmp_w();
}
/************************
*** 0xdf: cmp long,x ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] pbr,pc+3 ; aab
[5 ] aab,aa+x ; data low
[5a] aab,aa+x+1 ; data high
*/
void bCPU::op_cmp_longxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5
flags_cmp_b();
}
void bCPU::op_cmp_longxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5
rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a
flags_cmp_w();
}
/************************
*** 0xd9: cmp addr,y ***
************************
cycles:
[1 ] pbr,pc ; opercmp
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[3a] dbr,aah,aal+yl ; io [4]
[4 ] dbr,aa+y ; data low
[4a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_cmp_addryb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.y.w); //3a
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4
flags_cmp_b();
}
void bCPU::op_cmp_addryw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.y.w); //3a
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a
flags_cmp_w();
}
/**********************
*** 0xd5: cmp dp,x ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; data low
[4a] 0,d+dp+x+1 ; data high
*/
void bCPU::op_cmp_dpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
flags_cmp_b();
}
void bCPU::op_cmp_dpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
flags_cmp_w();
}
/************************
*** 0xc1: cmp (dp,x) ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; aal
[5 ] 0,d+dp+x+1 ; aah
[6 ] dbr,aa ; data low
[6a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_cmp_idpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
rd.l = op_read(OPMODE_DBR, aa.w); //6
flags_cmp_b();
}
void bCPU::op_cmp_idpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
rd.l = op_read(OPMODE_DBR, aa.w); //6
rd.h = op_read(OPMODE_DBR, aa.w + 1); //6a
flags_cmp_w();
}
/************************
*** 0xd1: cmp (dp),y ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[4a] dbr,aah,aal+yl ; io [4]
[5 ] dbr,aa+y ; data low
[5a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_cmp_idpyb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
cpu_c4(aa.w, aa.w + regs.y.w); //4a
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5
flags_cmp_b();
}
void bCPU::op_cmp_idpyw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
cpu_c4(aa.w, aa.w + regs.y.w); //4a
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a
flags_cmp_w();
}
/************************
*** 0xd7: cmp [dp],y ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] 0,d+dp+2 ; aab
[6 ] aab,aa+y ; data low
[6a] aab,aa+y+1 ; data high [1]
*/
void bCPU::op_cmp_ildpyb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6
flags_cmp_b();
}
void bCPU::op_cmp_ildpyw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6
rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a
flags_cmp_w();
}
/**********************
*** 0xc3: cmp sr,s ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; sp
[3 ] pbr,pc+1 ; io
[4 ] 0,s+sp ; data low
[4a] 0,s+sp+1 ; data high [1]
*/
void bCPU::op_cmp_srb() {
sp = op_read(); //2
cpu_io(); //3
rd.l = op_read(OPMODE_SP, sp); //4
flags_cmp_b();
}
void bCPU::op_cmp_srw() {
sp = op_read(); //2
cpu_io(); //3
rd.l = op_read(OPMODE_SP, sp); //4
rd.h = op_read(OPMODE_SP, sp + 1); //4a
flags_cmp_w();
}
/**************************
*** 0xd3: cmp (sr,s),y ***
**************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; sp
[3 ] pbr,pc+1 ; io
[4 ] 0,s+sp ; aal
[5 ] 0,s+sp+1 ; aah
[6 ] 0,s+sp+1 ; io
[7 ] dbr,aa+y ; data low
[7a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_cmp_isryb() {
sp = op_read(); //2
cpu_io(); //3
aa.l = op_read(OPMODE_SP, sp); //4
aa.h = op_read(OPMODE_SP, sp + 1); //5
cpu_io(); //6
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7
flags_cmp_b();
}
void bCPU::op_cmp_isryw() {
sp = op_read(); //2
cpu_io(); //3
aa.l = op_read(OPMODE_SP, sp); //4
aa.h = op_read(OPMODE_SP, sp + 1); //5
cpu_io(); //6
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a
flags_cmp_w();
}

View File

@@ -1,444 +0,0 @@
inline void bCPU::flags_eor_b() {
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
inline void bCPU::flags_eor_w() {
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
/************************
*** 0x49: eor #const ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; idl
[2a] pbr,pc+2 ; idh [1]
*/
void bCPU::op_eor_constb() {
regs.a.l ^= op_read(); //2
flags_eor_b();
}
void bCPU::op_eor_constw() {
regs.a.l ^= op_read(); //2
regs.a.h ^= op_read(); //2a
flags_eor_w();
}
/**********************
*** 0x4d: eor addr ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aa ; data low
[4a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_eor_addrb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
regs.a.l ^= op_read(OPMODE_DBR, aa.w); //4
flags_eor_b();
}
void bCPU::op_eor_addrw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
regs.a.l ^= op_read(OPMODE_DBR, aa.w); //4
regs.a.h ^= op_read(OPMODE_DBR, aa.w + 1); //4a
flags_eor_w();
}
/************************
*** 0x5d: eor addr,x ***
************************
cycles:
[1 ] pbr,pc ; opereor
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[3a] dbr,aah,aal+xl ; io [4]
[4 ] dbr,aa+x ; data low
[4a] dbr,aa+x+1 ; data high [1]
*/
void bCPU::op_eor_addrxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.x.w); //3a
regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.x.w); //4
flags_eor_b();
}
void bCPU::op_eor_addrxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.x.w); //3a
regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.x.w); //4
regs.a.h ^= op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a
flags_eor_w();
}
/********************
*** 0x45: eor dp ***
********************
cycles:
[1 ] pbr,pc ; opereor
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; data low
[3a] 0,d+dp+1 ; data high [1]
*/
void bCPU::op_eor_dpb() {
dp = op_read(); //2
cpu_c2(); //2a
regs.a.l ^= op_read(OPMODE_DP, dp); //3
flags_eor_b();
}
void bCPU::op_eor_dpw() {
dp = op_read(); //2
cpu_c2(); //2a
regs.a.l ^= op_read(OPMODE_DP, dp); //3
regs.a.h ^= op_read(OPMODE_DP, dp + 1); //3a
flags_eor_w();
}
/**********************
*** 0x52: eor (dp) ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] dbr,aa ; data low
[5a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_eor_idpb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
regs.a.l ^= op_read(OPMODE_DBR, aa.w); //5
flags_eor_b();
}
void bCPU::op_eor_idpw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
regs.a.l ^= op_read(OPMODE_DBR, aa.w); //5
regs.a.h ^= op_read(OPMODE_DBR, aa.w + 1); //5
flags_eor_w();
}
/**********************
*** 0x47: eor [dp] ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] 0,d+dp+2 ; aab
[6 ] aab,aa ; data low
[6a] aab,aa+1 ; data high [1]
*/
void bCPU::op_eor_ildpb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
regs.a.l ^= op_read(OPMODE_LONG, aa.d); //6
flags_eor_b();
}
void bCPU::op_eor_ildpw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
regs.a.l ^= op_read(OPMODE_LONG, aa.d); //6
regs.a.h ^= op_read(OPMODE_LONG, aa.d + 1); //6a
flags_eor_w();
}
/**********************
*** 0x4f: eor long ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] pbr,pc+3 ; aab
[5 ] aab,aa ; data low
[5a] aab,aa+1 ; data high
*/
void bCPU::op_eor_longb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
regs.a.l ^= op_read(OPMODE_LONG, aa.d); //5
flags_eor_b();
}
void bCPU::op_eor_longw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
regs.a.l ^= op_read(OPMODE_LONG, aa.d); //5
regs.a.h ^= op_read(OPMODE_LONG, aa.d + 1); //5a
flags_eor_w();
}
/************************
*** 0x5f: eor long,x ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] pbr,pc+3 ; aab
[5 ] aab,aa+x ; data low
[5a] aab,aa+x+1 ; data high
*/
void bCPU::op_eor_longxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
regs.a.l ^= op_read(OPMODE_LONG, aa.d + regs.x.w); //5
flags_eor_b();
}
void bCPU::op_eor_longxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
regs.a.l ^= op_read(OPMODE_LONG, aa.d + regs.x.w); //5
regs.a.h ^= op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a
flags_eor_w();
}
/************************
*** 0x59: eor addr,y ***
************************
cycles:
[1 ] pbr,pc ; opereor
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[3a] dbr,aah,aal+yl ; io [4]
[4 ] dbr,aa+y ; data low
[4a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_eor_addryb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.y.w); //3a
regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.y.w); //4
flags_eor_b();
}
void bCPU::op_eor_addryw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.y.w); //3a
regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.y.w); //4
regs.a.h ^= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a
flags_eor_w();
}
/**********************
*** 0x55: eor dp,x ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; data low
[4a] 0,d+dp+x+1 ; data high
*/
void bCPU::op_eor_dpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
regs.a.l ^= op_read(OPMODE_DP, dp + regs.x.w); //4
flags_eor_b();
}
void bCPU::op_eor_dpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
regs.a.l ^= op_read(OPMODE_DP, dp + regs.x.w); //4
regs.a.h ^= op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
flags_eor_w();
}
/************************
*** 0x41: eor (dp,x) ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; aal
[5 ] 0,d+dp+x+1 ; aah
[6 ] dbr,aa ; data low
[6a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_eor_idpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
regs.a.l ^= op_read(OPMODE_DBR, aa.w); //6
flags_eor_b();
}
void bCPU::op_eor_idpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
regs.a.l ^= op_read(OPMODE_DBR, aa.w); //6
regs.a.h ^= op_read(OPMODE_DBR, aa.w + 1); //6a
flags_eor_w();
}
/************************
*** 0x51: eor (dp),y ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[4a] dbr,aah,aal+yl ; io [4]
[5 ] dbr,aa+y ; data low
[5a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_eor_idpyb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
cpu_c4(aa.w, aa.w + regs.y.w); //4a
regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.y.w); //5
flags_eor_b();
}
void bCPU::op_eor_idpyw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
cpu_c4(aa.w, aa.w + regs.y.w); //4a
regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.y.w); //5
regs.a.h ^= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a
flags_eor_w();
}
/************************
*** 0x57: eor [dp],y ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] 0,d+dp+2 ; aab
[6 ] aab,aa+y ; data low
[6a] aab,aa+y+1 ; data high [1]
*/
void bCPU::op_eor_ildpyb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
regs.a.l ^= op_read(OPMODE_LONG, aa.d + regs.y.w); //6
flags_eor_b();
}
void bCPU::op_eor_ildpyw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
regs.a.l ^= op_read(OPMODE_LONG, aa.d + regs.y.w); //6
regs.a.h ^= op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a
flags_eor_w();
}
/**********************
*** 0x43: eor sr,s ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; sp
[3 ] pbr,pc+1 ; io
[4 ] 0,s+sp ; data low
[4a] 0,s+sp+1 ; data high [1]
*/
void bCPU::op_eor_srb() {
sp = op_read(); //2
cpu_io(); //3
regs.a.l ^= op_read(OPMODE_SP, sp); //4
flags_eor_b();
}
void bCPU::op_eor_srw() {
sp = op_read(); //2
cpu_io(); //3
regs.a.l ^= op_read(OPMODE_SP, sp); //4
regs.a.h ^= op_read(OPMODE_SP, sp + 1); //4a
flags_eor_w();
}
/**************************
*** 0x53: eor (sr,s),y ***
**************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; sp
[3 ] pbr,pc+1 ; io
[4 ] 0,s+sp ; aal
[5 ] 0,s+sp+1 ; aah
[6 ] 0,s+sp+1 ; io
[7 ] dbr,aa+y ; data low
[7a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_eor_isryb() {
sp = op_read(); //2
cpu_io(); //3
aa.l = op_read(OPMODE_SP, sp); //4
aa.h = op_read(OPMODE_SP, sp + 1); //5
cpu_io(); //6
regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.y.w); //7
flags_eor_b();
}
void bCPU::op_eor_isryw() {
sp = op_read(); //2
cpu_io(); //3
aa.l = op_read(OPMODE_SP, sp); //4
aa.h = op_read(OPMODE_SP, sp + 1); //5
cpu_io(); //6
regs.a.l ^= op_read(OPMODE_DBR, aa.w + regs.y.w); //7
regs.a.h ^= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a
flags_eor_w();
}

View File

@@ -1,433 +0,0 @@
/*****************
*** 0x1a: inc ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void bCPU::op_incb() {
cpu_io(); //2
regs.a.l++;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
void bCPU::op_incw() {
cpu_io(); //2
regs.a.w++;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
/**********************
*** 0xee: inc addr ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aa ; data low
[4a] dbr,aa+1 ; data high [1]
[5 ] dbr,aa+1 ; io
[6a] dbr,aa+1 ; data high [1]
[6 ] dbr,aa ; data low
*/
void bCPU::op_inc_addrb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_DBR, aa.w); //4
rd.l++;
cpu_io(); //5
op_write(OPMODE_DBR, aa.w, rd.l); //6
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_inc_addrw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_DBR, aa.w); //4
rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a
rd.w++;
cpu_io(); //5
op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a
op_write(OPMODE_DBR, aa.w, rd.l); //6
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/************************
*** 0xfe: inc addr,x ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aah,aal+xl ; io
[5 ] dbr,aa+x ; data low
[5a] dbr,aa+x+1 ; data high [1]
[6 ] dbr,aa+x+1 ; io
[7a] dbr,aa+x+1 ; data high [1]
[7 ] dbr,aa+x ; data low
*/
void bCPU::op_inc_addrxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_io(); //4
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
rd.l++;
cpu_io(); //6
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_inc_addrxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_io(); //4
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //5a
rd.w++;
cpu_io(); //6
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); //7a
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/********************
*** 0xe6: inc dp ***
********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; data low
[3a] 0,d+dp+1 ; data high [1]
[4 ] 0,d+dp+1 ; io
[5a] 0,d+dp+1 ; data high [1]
[5 ] 0,d+dp ; data low
*/
void bCPU::op_inc_dpb() {
dp = op_read(); //2
cpu_c2(); //2a
rd.l = op_read(OPMODE_DP, dp); //3
rd.l++;
cpu_io(); //4
op_write(OPMODE_DP, dp, rd.l); //5
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_inc_dpw() {
dp = op_read(); //2
cpu_c2(); //2a
rd.l = op_read(OPMODE_DP, dp); //3
rd.h = op_read(OPMODE_DP, dp + 1); //3a
rd.w++;
cpu_io(); //4
op_write(OPMODE_DP, dp + 1, rd.h); //5a
op_write(OPMODE_DP, dp, rd.l); //5
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/**********************
*** 0xf6: inc dp,x ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; data low
[4a] 0,d+dp+x+1 ; data high [1]
[5 ] 0,d+dp+x+1 ; io
[6a] 0,d+dp+x+1 ; data high [1]
[6 ] 0,d+dp+x ; data low
*/
void bCPU::op_inc_dpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
rd.l++;
cpu_io(); //5
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_inc_dpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
rd.w++;
cpu_io(); //5
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); //6a
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/*****************
*** 0xe8: inx ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void bCPU::op_inxb() {
cpu_io(); //2
regs.x.l++;
regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
}
void bCPU::op_inxw() {
cpu_io(); //2
regs.x.w++;
regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
/*****************
*** 0xc8: iny ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void bCPU::op_inyb() {
cpu_io(); //2
regs.y.l++;
regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
}
void bCPU::op_inyw() {
cpu_io(); //2
regs.y.w++;
regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
}
/*****************
*** 0x3a: dec ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void bCPU::op_decb() {
cpu_io(); //2
regs.a.l--;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
void bCPU::op_decw() {
cpu_io(); //2
regs.a.w--;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
/**********************
*** 0xce: dec addr ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aa ; data low
[4a] dbr,aa+1 ; data high [1]
[5 ] dbr,aa+1 ; io
[6a] dbr,aa+1 ; data high [1]
[6 ] dbr,aa ; data low
*/
void bCPU::op_dec_addrb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_DBR, aa.w); //4
rd.l--;
cpu_io(); //5
op_write(OPMODE_DBR, aa.w, rd.l); //6
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_dec_addrw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_DBR, aa.w); //4
rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a
rd.w--;
cpu_io(); //5
op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a
op_write(OPMODE_DBR, aa.w, rd.l); //6
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/************************
*** 0xde: dec addr,x ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aah,aal+xl ; io
[5 ] dbr,aa+x ; data low
[5a] dbr,aa+x+1 ; data high [1]
[6 ] dbr,aa+x+1 ; io
[7a] dbr,aa+x+1 ; data high [1]
[7 ] dbr,aa+x ; data low
*/
void bCPU::op_dec_addrxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_io(); //4
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
rd.l--;
cpu_io(); //6
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_dec_addrxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_io(); //4
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //5a
rd.w--;
cpu_io(); //6
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); //7a
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/********************
*** 0xc6: dec dp ***
********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; data low
[3a] 0,d+dp+1 ; data high [1]
[4 ] 0,d+dp+1 ; io
[5a] 0,d+dp+1 ; data high [1]
[5 ] 0,d+dp ; data low
*/
void bCPU::op_dec_dpb() {
dp = op_read(); //2
cpu_c2(); //2a
rd.l = op_read(OPMODE_DP, dp); //3
rd.l--;
cpu_io(); //4
op_write(OPMODE_DP, dp, rd.l); //5
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_dec_dpw() {
dp = op_read(); //2
cpu_c2(); //2a
rd.l = op_read(OPMODE_DP, dp); //3
rd.h = op_read(OPMODE_DP, dp + 1); //3a
rd.w--;
cpu_io(); //4
op_write(OPMODE_DP, dp + 1, rd.h); //5a
op_write(OPMODE_DP, dp, rd.l); //5
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/**********************
*** 0xd6: dec dp,x ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; data low
[4a] 0,d+dp+x+1 ; data high [1]
[5 ] 0,d+dp+x+1 ; io
[6a] 0,d+dp+x+1 ; data high [1]
[6 ] 0,d+dp+x ; data low
*/
void bCPU::op_dec_dpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
rd.l--;
cpu_io(); //5
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_dec_dpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
rd.w--;
cpu_io(); //5
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); //6a
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/*****************
*** 0xca: dex ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void bCPU::op_dexb() {
cpu_io(); //2
regs.x.l--;
regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
}
void bCPU::op_dexw() {
cpu_io(); //2
regs.x.w--;
regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
/*****************
*** 0x88: dey ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void bCPU::op_deyb() {
cpu_io(); //2
regs.y.l--;
regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
}
void bCPU::op_deyw() {
cpu_io(); //2
regs.y.w--;
regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
}

View File

@@ -1,444 +0,0 @@
inline void bCPU::flags_lda_b() {
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
inline void bCPU::flags_lda_w() {
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
/************************
*** 0xa9: lda #const ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; idl
[2a] pbr,pc+2 ; idh [1]
*/
void bCPU::op_lda_constb() {
regs.a.l = op_read(); //2
flags_lda_b();
}
void bCPU::op_lda_constw() {
regs.a.l = op_read(); //2
regs.a.h = op_read(); //2a
flags_lda_w();
}
/**********************
*** 0xad: lda addr ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aa ; data low
[4a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_lda_addrb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
regs.a.l = op_read(OPMODE_DBR, aa.w); //4
flags_lda_b();
}
void bCPU::op_lda_addrw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
regs.a.l = op_read(OPMODE_DBR, aa.w); //4
regs.a.h = op_read(OPMODE_DBR, aa.w + 1); //4a
flags_lda_w();
}
/************************
*** 0xbd: lda addr,x ***
************************
cycles:
[1 ] pbr,pc ; operand
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[3a] dbr,aah,aal+xl ; io [4]
[4 ] dbr,aa+x ; data low
[4a] dbr,aa+x+1 ; data high [1]
*/
void bCPU::op_lda_addrxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.x.w); //3a
regs.a.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4
flags_lda_b();
}
void bCPU::op_lda_addrxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.x.w); //3a
regs.a.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4
regs.a.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a
flags_lda_w();
}
/********************
*** 0xa5: lda dp ***
********************
cycles:
[1 ] pbr,pc ; operand
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; data low
[3a] 0,d+dp+1 ; data high [1]
*/
void bCPU::op_lda_dpb() {
dp = op_read(); //2
cpu_c2(); //2a
regs.a.l = op_read(OPMODE_DP, dp); //3
flags_lda_b();
}
void bCPU::op_lda_dpw() {
dp = op_read(); //2
cpu_c2(); //2a
regs.a.l = op_read(OPMODE_DP, dp); //3
regs.a.h = op_read(OPMODE_DP, dp + 1); //3a
flags_lda_w();
}
/**********************
*** 0xb2: lda (dp) ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] dbr,aa ; data low
[5a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_lda_idpb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
regs.a.l = op_read(OPMODE_DBR, aa.w); //5
flags_lda_b();
}
void bCPU::op_lda_idpw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
regs.a.l = op_read(OPMODE_DBR, aa.w); //5
regs.a.h = op_read(OPMODE_DBR, aa.w + 1); //5
flags_lda_w();
}
/**********************
*** 0xa7: lda [dp] ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] 0,d+dp+2 ; aab
[6 ] aab,aa ; data low
[6a] aab,aa+1 ; data high [1]
*/
void bCPU::op_lda_ildpb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
regs.a.l = op_read(OPMODE_LONG, aa.d); //6
flags_lda_b();
}
void bCPU::op_lda_ildpw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
regs.a.l = op_read(OPMODE_LONG, aa.d); //6
regs.a.h = op_read(OPMODE_LONG, aa.d + 1); //6a
flags_lda_w();
}
/**********************
*** 0xaf: lda long ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] pbr,pc+3 ; aab
[5 ] aab,aa ; data low
[5a] aab,aa+1 ; data high
*/
void bCPU::op_lda_longb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
regs.a.l = op_read(OPMODE_LONG, aa.d); //5
flags_lda_b();
}
void bCPU::op_lda_longw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
regs.a.l = op_read(OPMODE_LONG, aa.d); //5
regs.a.h = op_read(OPMODE_LONG, aa.d + 1); //5a
flags_lda_w();
}
/************************
*** 0xbf: lda long,x ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] pbr,pc+3 ; aab
[5 ] aab,aa+x ; data low
[5a] aab,aa+x+1 ; data high
*/
void bCPU::op_lda_longxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
regs.a.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5
flags_lda_b();
}
void bCPU::op_lda_longxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
regs.a.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5
regs.a.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a
flags_lda_w();
}
/************************
*** 0xb9: lda addr,y ***
************************
cycles:
[1 ] pbr,pc ; operand
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[3a] dbr,aah,aal+yl ; io [4]
[4 ] dbr,aa+y ; data low
[4a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_lda_addryb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.y.w); //3a
regs.a.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4
flags_lda_b();
}
void bCPU::op_lda_addryw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.y.w); //3a
regs.a.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4
regs.a.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a
flags_lda_w();
}
/**********************
*** 0xb5: lda dp,x ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; data low
[4a] 0,d+dp+x+1 ; data high
*/
void bCPU::op_lda_dpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
regs.a.l = op_read(OPMODE_DP, dp + regs.x.w); //4
flags_lda_b();
}
void bCPU::op_lda_dpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
regs.a.l = op_read(OPMODE_DP, dp + regs.x.w); //4
regs.a.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
flags_lda_w();
}
/************************
*** 0xa1: lda (dp,x) ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; aal
[5 ] 0,d+dp+x+1 ; aah
[6 ] dbr,aa ; data low
[6a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_lda_idpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
regs.a.l = op_read(OPMODE_DBR, aa.w); //6
flags_lda_b();
}
void bCPU::op_lda_idpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
regs.a.l = op_read(OPMODE_DBR, aa.w); //6
regs.a.h = op_read(OPMODE_DBR, aa.w + 1); //6a
flags_lda_w();
}
/************************
*** 0xb1: lda (dp),y ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[4a] dbr,aah,aal+yl ; io [4]
[5 ] dbr,aa+y ; data low
[5a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_lda_idpyb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
cpu_c4(aa.w, aa.w + regs.y.w); //4a
regs.a.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5
flags_lda_b();
}
void bCPU::op_lda_idpyw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
cpu_c4(aa.w, aa.w + regs.y.w); //4a
regs.a.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5
regs.a.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a
flags_lda_w();
}
/************************
*** 0xb7: lda [dp],y ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] 0,d+dp+2 ; aab
[6 ] aab,aa+y ; data low
[6a] aab,aa+y+1 ; data high [1]
*/
void bCPU::op_lda_ildpyb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
regs.a.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6
flags_lda_b();
}
void bCPU::op_lda_ildpyw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
regs.a.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6
regs.a.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a
flags_lda_w();
}
/**********************
*** 0xa3: lda sr,s ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; sp
[3 ] pbr,pc+1 ; io
[4 ] 0,s+sp ; data low
[4a] 0,s+sp+1 ; data high [1]
*/
void bCPU::op_lda_srb() {
sp = op_read(); //2
cpu_io(); //3
regs.a.l = op_read(OPMODE_SP, sp); //4
flags_lda_b();
}
void bCPU::op_lda_srw() {
sp = op_read(); //2
cpu_io(); //3
regs.a.l = op_read(OPMODE_SP, sp); //4
regs.a.h = op_read(OPMODE_SP, sp + 1); //4a
flags_lda_w();
}
/**************************
*** 0xb3: lda (sr,s),y ***
**************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; sp
[3 ] pbr,pc+1 ; io
[4 ] 0,s+sp ; aal
[5 ] 0,s+sp+1 ; aah
[6 ] 0,s+sp+1 ; io
[7 ] dbr,aa+y ; data low
[7a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_lda_isryb() {
sp = op_read(); //2
cpu_io(); //3
aa.l = op_read(OPMODE_SP, sp); //4
aa.h = op_read(OPMODE_SP, sp + 1); //5
cpu_io(); //6
regs.a.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7
flags_lda_b();
}
void bCPU::op_lda_isryw() {
sp = op_read(); //2
cpu_io(); //3
aa.l = op_read(OPMODE_SP, sp); //4
aa.h = op_read(OPMODE_SP, sp + 1); //5
cpu_io(); //6
regs.a.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7
regs.a.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a
flags_lda_w();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,444 +0,0 @@
inline void bCPU::flags_ora_b() {
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
inline void bCPU::flags_ora_w() {
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
/************************
*** 0x09: ora #const ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; idl
[2a] pbr,pc+2 ; idh [1]
*/
void bCPU::op_ora_constb() {
regs.a.l |= op_read(); //2
flags_ora_b();
}
void bCPU::op_ora_constw() {
regs.a.l |= op_read(); //2
regs.a.h |= op_read(); //2a
flags_ora_w();
}
/**********************
*** 0x0d: ora addr ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aa ; data low
[4a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_ora_addrb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
regs.a.l |= op_read(OPMODE_DBR, aa.w); //4
flags_ora_b();
}
void bCPU::op_ora_addrw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
regs.a.l |= op_read(OPMODE_DBR, aa.w); //4
regs.a.h |= op_read(OPMODE_DBR, aa.w + 1); //4a
flags_ora_w();
}
/************************
*** 0x1d: ora addr,x ***
************************
cycles:
[1 ] pbr,pc ; operora
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[3a] dbr,aah,aal+xl ; io [4]
[4 ] dbr,aa+x ; data low
[4a] dbr,aa+x+1 ; data high [1]
*/
void bCPU::op_ora_addrxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.x.w); //3a
regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.x.w); //4
flags_ora_b();
}
void bCPU::op_ora_addrxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.x.w); //3a
regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.x.w); //4
regs.a.h |= op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a
flags_ora_w();
}
/********************
*** 0x05: ora dp ***
********************
cycles:
[1 ] pbr,pc ; operora
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; data low
[3a] 0,d+dp+1 ; data high [1]
*/
void bCPU::op_ora_dpb() {
dp = op_read(); //2
cpu_c2(); //2a
regs.a.l |= op_read(OPMODE_DP, dp); //3
flags_ora_b();
}
void bCPU::op_ora_dpw() {
dp = op_read(); //2
cpu_c2(); //2a
regs.a.l |= op_read(OPMODE_DP, dp); //3
regs.a.h |= op_read(OPMODE_DP, dp + 1); //3a
flags_ora_w();
}
/**********************
*** 0x12: ora (dp) ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] dbr,aa ; data low
[5a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_ora_idpb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
regs.a.l |= op_read(OPMODE_DBR, aa.w); //5
flags_ora_b();
}
void bCPU::op_ora_idpw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
regs.a.l |= op_read(OPMODE_DBR, aa.w); //5
regs.a.h |= op_read(OPMODE_DBR, aa.w + 1); //5
flags_ora_w();
}
/**********************
*** 0x07: ora [dp] ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] 0,d+dp+2 ; aab
[6 ] aab,aa ; data low
[6a] aab,aa+1 ; data high [1]
*/
void bCPU::op_ora_ildpb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
regs.a.l |= op_read(OPMODE_LONG, aa.d); //6
flags_ora_b();
}
void bCPU::op_ora_ildpw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
regs.a.l |= op_read(OPMODE_LONG, aa.d); //6
regs.a.h |= op_read(OPMODE_LONG, aa.d + 1); //6a
flags_ora_w();
}
/**********************
*** 0x0f: ora long ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] pbr,pc+3 ; aab
[5 ] aab,aa ; data low
[5a] aab,aa+1 ; data high
*/
void bCPU::op_ora_longb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
regs.a.l |= op_read(OPMODE_LONG, aa.d); //5
flags_ora_b();
}
void bCPU::op_ora_longw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
regs.a.l |= op_read(OPMODE_LONG, aa.d); //5
regs.a.h |= op_read(OPMODE_LONG, aa.d + 1); //5a
flags_ora_w();
}
/************************
*** 0x1f: ora long,x ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] pbr,pc+3 ; aab
[5 ] aab,aa+x ; data low
[5a] aab,aa+x+1 ; data high
*/
void bCPU::op_ora_longxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
regs.a.l |= op_read(OPMODE_LONG, aa.d + regs.x.w); //5
flags_ora_b();
}
void bCPU::op_ora_longxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
regs.a.l |= op_read(OPMODE_LONG, aa.d + regs.x.w); //5
regs.a.h |= op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a
flags_ora_w();
}
/************************
*** 0x19: ora addr,y ***
************************
cycles:
[1 ] pbr,pc ; operora
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[3a] dbr,aah,aal+yl ; io [4]
[4 ] dbr,aa+y ; data low
[4a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_ora_addryb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.y.w); //3a
regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.y.w); //4
flags_ora_b();
}
void bCPU::op_ora_addryw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.y.w); //3a
regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.y.w); //4
regs.a.h |= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a
flags_ora_w();
}
/**********************
*** 0x15: ora dp,x ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; data low
[4a] 0,d+dp+x+1 ; data high
*/
void bCPU::op_ora_dpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
regs.a.l |= op_read(OPMODE_DP, dp + regs.x.w); //4
flags_ora_b();
}
void bCPU::op_ora_dpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
regs.a.l |= op_read(OPMODE_DP, dp + regs.x.w); //4
regs.a.h |= op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
flags_ora_w();
}
/************************
*** 0x01: ora (dp,x) ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; aal
[5 ] 0,d+dp+x+1 ; aah
[6 ] dbr,aa ; data low
[6a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_ora_idpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
regs.a.l |= op_read(OPMODE_DBR, aa.w); //6
flags_ora_b();
}
void bCPU::op_ora_idpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
regs.a.l |= op_read(OPMODE_DBR, aa.w); //6
regs.a.h |= op_read(OPMODE_DBR, aa.w + 1); //6a
flags_ora_w();
}
/************************
*** 0x11: ora (dp),y ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[4a] dbr,aah,aal+yl ; io [4]
[5 ] dbr,aa+y ; data low
[5a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_ora_idpyb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
cpu_c4(aa.w, aa.w + regs.y.w); //4a
regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.y.w); //5
flags_ora_b();
}
void bCPU::op_ora_idpyw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
cpu_c4(aa.w, aa.w + regs.y.w); //4a
regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.y.w); //5
regs.a.h |= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a
flags_ora_w();
}
/************************
*** 0x17: ora [dp],y ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] 0,d+dp+2 ; aab
[6 ] aab,aa+y ; data low
[6a] aab,aa+y+1 ; data high [1]
*/
void bCPU::op_ora_ildpyb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
regs.a.l |= op_read(OPMODE_LONG, aa.d + regs.y.w); //6
flags_ora_b();
}
void bCPU::op_ora_ildpyw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
regs.a.l |= op_read(OPMODE_LONG, aa.d + regs.y.w); //6
regs.a.h |= op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a
flags_ora_w();
}
/**********************
*** 0x03: ora sr,s ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; sp
[3 ] pbr,pc+1 ; io
[4 ] 0,s+sp ; data low
[4a] 0,s+sp+1 ; data high [1]
*/
void bCPU::op_ora_srb() {
sp = op_read(); //2
cpu_io(); //3
regs.a.l |= op_read(OPMODE_SP, sp); //4
flags_ora_b();
}
void bCPU::op_ora_srw() {
sp = op_read(); //2
cpu_io(); //3
regs.a.l |= op_read(OPMODE_SP, sp); //4
regs.a.h |= op_read(OPMODE_SP, sp + 1); //4a
flags_ora_w();
}
/**************************
*** 0x13: ora (sr,s),y ***
**************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; sp
[3 ] pbr,pc+1 ; io
[4 ] 0,s+sp ; aal
[5 ] 0,s+sp+1 ; aah
[6 ] 0,s+sp+1 ; io
[7 ] dbr,aa+y ; data low
[7a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_ora_isryb() {
sp = op_read(); //2
cpu_io(); //3
aa.l = op_read(OPMODE_SP, sp); //4
aa.h = op_read(OPMODE_SP, sp + 1); //5
cpu_io(); //6
regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.y.w); //7
flags_ora_b();
}
void bCPU::op_ora_isryw() {
sp = op_read(); //2
cpu_io(); //3
aa.l = op_read(OPMODE_SP, sp); //4
aa.h = op_read(OPMODE_SP, sp + 1); //5
cpu_io(); //6
regs.a.l |= op_read(OPMODE_DBR, aa.w + regs.y.w); //7
regs.a.h |= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a
flags_ora_w();
}

View File

@@ -1,441 +0,0 @@
/**********************
*** 0x4c: jmp addr ***
**********************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; new pcl
[3] pbr,pc+2 ; new pch
*/
void bCPU::op_jmp_addr() {
rd.l = op_read(); //2
rd.h = op_read(); //3
regs.pc.w = rd.w;
}
/**********************
*** 0x5c: jmp long ***
**********************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; new pcl
[3] pbr,pc+2 ; new pch
[4] pbr,pc+3 ; new pbr
*/
void bCPU::op_jmp_long() {
rd.l = op_read(); //2
rd.h = op_read(); //3
rd.b = op_read(); //4
regs.pc.d = rd.d;
}
/************************
*** 0x6c: jmp (addr) ***
************************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; aal
[3] pbr,pc+2 ; aah
[4] 0,aa ; new pcl
[5] 0,aa+1 ; new pch
*/
void bCPU::op_jmp_iaddr() {
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_ADDR, aa.w); //4
rd.h = op_read(OPMODE_ADDR, aa.w + 1); //5
regs.pc.w = rd.w;
}
/**************************
*** 0x7c: jmp (addr,x) ***
**************************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; aal
[3] pbr,pc+2 ; aah
[4] pbr,pc+2 ; io
[5] pbr,aa+x ; new pcl
[6] pbr,aa+x+1 ; new pch
*/
void bCPU::op_jmp_iaddrx() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_io(); //4
rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w); //5
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1); //6
regs.pc.w = rd.w;
}
/************************
*** 0xdc: jmp [addr] ***
************************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; aal
[3] pbr,pc+2 ; aah
[4] 0,aa ; new pcl
[5] 0,aa+1 ; new pch
[6] 0,aa+2 ; new pbr
*/
void bCPU::op_jmp_iladdr() {
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_ADDR, aa.w); //4
rd.h = op_read(OPMODE_ADDR, aa.w + 1); //5
rd.b = op_read(OPMODE_ADDR, aa.w + 2); //6
regs.pc.d = rd.d;
}
/**********************
*** 0x20: jsr addr ***
**********************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; new pcl
[3] pbr,pc+2 ; new pch
[4] pbr,pc+2 ; io
[5] 0,s ; pch
[6] 0,s-1 ; pcl
*/
void bCPU::op_jsr_addr() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_io(); //4
regs.pc.w--;
stack_write(regs.pc.h); //5
stack_write(regs.pc.l); //6
regs.pc.w = aa.w;
}
/**********************
*** 0x22: jsr long ***
**********************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; new pcl
[3] pbr,pc+2 ; new pch
[4] 0,s ; pbr
[5] 0,s ; io
[6] pbr,pc+3 ; new pbr
[7] 0,s-1 ; pch
[8] 0,s-2 ; pcl
*/
void bCPU::op_jsr_long() {
aa.l = op_read(); //2
aa.h = op_read(); //3
stack_write(regs.pc.b); //4
cpu_io(); //5
aa.b = op_read(); //6
regs.pc.w--;
stack_write(regs.pc.h); //7
stack_write(regs.pc.l); //8
regs.pc.d = aa.d;
}
/**************************
*** 0xfc: jsr (addr,x) ***
**************************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; aal
[3] 0,s ; pch
[4] 0,s-1 ; pcl
[5] pbr,pc+2 ; aah
[6] pbr,pc+2 ; io
[7] pbr,aa+x ; new pcl
[8] pbr,aa+x+1 ; new pch
*/
void bCPU::op_jsr_iaddrx() {
aa.l = op_read(); //2
stack_write(regs.pc.h); //3
stack_write(regs.pc.l); //4
aa.h = op_read(); //5
cpu_io(); //6
rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w); //7
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1); //8
regs.pc.w = rd.w;
}
/*****************
*** 0x40: rti ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
[3] pbr,pc+1 ; io
[4] 0,s+1 ; p
[5] 0,s+2 ; new pcl
[6] 0,s+3 ; new pch
[7] 0,s+4 ; pbr [7]
*/
void bCPU::op_rtie() {
cpu_io(); //2
cpu_io(); //3
regs.p = stack_read(); //4
rd.l = stack_read(); //5
rd.h = stack_read(); //6
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
regs.pc.w = rd.w;
}
void bCPU::op_rtin() {
cpu_io(); //2
cpu_io(); //3
regs.p = stack_read(); //4
rd.l = stack_read(); //5
rd.h = stack_read(); //6
rd.b = stack_read(); //7
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
regs.pc.d = rd.d;
switch((regs.p >> 4) & 3) {
case 0:optbl = optbl_mx;break;
case 1:optbl = optbl_mX;break;
case 2:optbl = optbl_Mx;break;
case 3:optbl = optbl_MX;break;
}
}
/*****************
*** 0x60: rts ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
[3] pbr,pc+1 ; io
[4] 0,s+1 ; pcl
[5] 0,s+2 ; pch
[6] 0,s+2 ; io
*/
void bCPU::op_rts() {
cpu_io(); //2
cpu_io(); //3
rd.l = stack_read(); //4
rd.h = stack_read(); //5
cpu_io(); //6
regs.pc.w = rd.w;
regs.pc.w++;
}
/*****************
*** 0x6b: rtl ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
[3] pbr,pc+1 ; io
[4] 0,s+1 ; pcl
[5] 0,s+2 ; pch
[6] 0,s+3 ; pbr
*/
void bCPU::op_rtl() {
cpu_io(); //2
cpu_io(); //3
rd.l = stack_read(); //4
rd.h = stack_read(); //5
rd.b = stack_read(); //6
regs.pc.d = rd.d;
regs.pc.w++;
}
/**********************
*** 0x80: bra near ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; offset
[2a] pbr,pc+1 ; io [5]
[2b] pbr,pc+1 ; io [6]
*/
void bCPU::op_bra() {
uint16 r;
rd.l = op_read(); //2
cpu_io(); //2a
r = regs.pc + (int8)rd.l;
cpu_c6(r); //2b
regs.pc.w = r;
}
/*********************
*** 0x82: brl far ***
*********************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; offset low
[3] pbr,pc+2 ; offset high
[4] pbr,pc+2 ; io
*/
void bCPU::op_brl() {
uint16 r;
rd.l = op_read(); //2
rd.h = op_read(); //3
cpu_io(); //4
r = regs.pc + (int16)rd.w;
regs.pc.w = r;
}
/**********************
*** 0x90: bcc near ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; offset
[2a] pbr,pc+1 ; io [5]
[2b] pbr,pc+1 ; io [6]
*/
void bCPU::op_bcc() {
uint16 r;
rd.l = op_read(); //2
if(!regs.p.c) {
cpu_io(); //2a
r = regs.pc + (int8)rd.l;
cpu_c6(r); //2b
regs.pc.w = r;
}
}
/**********************
*** 0xb0: bcs near ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; offset
[2a] pbr,pc+1 ; io [5]
[2b] pbr,pc+1 ; io [6]
*/
void bCPU::op_bcs() {
uint16 r;
rd.l = op_read(); //2
if(regs.p.c) {
cpu_io(); //2a
r = regs.pc + (int8)rd.l;
cpu_c6(r); //2b
regs.pc.w = r;
}
}
/**********************
*** 0xd0: bne near ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; offset
[2a] pbr,pc+1 ; io [5]
[2b] pbr,pc+1 ; io [6]
*/
void bCPU::op_bne() {
uint16 r;
rd.l = op_read(); //2
if(!regs.p.z) {
cpu_io(); //2a
r = regs.pc + (int8)rd.l;
cpu_c6(r); //2b
regs.pc.w = r;
}
}
/**********************
*** 0xf0: beq near ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; offset
[2a] pbr,pc+1 ; io [5]
[2b] pbr,pc+1 ; io [6]
*/
void bCPU::op_beq() {
uint16 r;
rd.l = op_read(); //2
if(regs.p.z) {
cpu_io(); //2a
r = regs.pc + (int8)rd.l;
cpu_c6(r); //2b
regs.pc.w = r;
}
}
/**********************
*** 0x10: bpl near ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; offset
[2a] pbr,pc+1 ; io [5]
[2b] pbr,pc+1 ; io [6]
*/
void bCPU::op_bpl() {
uint16 r;
rd.l = op_read(); //2
if(!regs.p.n) {
cpu_io(); //2a
r = regs.pc + (int8)rd.l;
cpu_c6(r); //2b
regs.pc.w = r;
}
}
/**********************
*** 0x30: bmi near ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; offset
[2a] pbr,pc+1 ; io [5]
[2b] pbr,pc+1 ; io [6]
*/
void bCPU::op_bmi() {
uint16 r;
rd.l = op_read(); //2
if(regs.p.n) {
cpu_io(); //2a
r = regs.pc + (int8)rd.l;
cpu_c6(r); //2b
regs.pc.w = r;
}
}
/**********************
*** 0x50: bvc near ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; offset
[2a] pbr,pc+1 ; io [5]
[2b] pbr,pc+1 ; io [6]
*/
void bCPU::op_bvc() {
uint16 r;
rd.l = op_read(); //2
if(!regs.p.v) {
cpu_io(); //2a
r = regs.pc + (int8)rd.l;
cpu_c6(r); //2b
regs.pc.w = r;
}
}
/**********************
*** 0x70: bvs near ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; offset
[2a] pbr,pc+1 ; io [5]
[2b] pbr,pc+1 ; io [6]
*/
void bCPU::op_bvs() {
uint16 r;
rd.l = op_read(); //2
if(regs.p.v) {
cpu_io(); //2a
r = regs.pc + (int8)rd.l;
cpu_c6(r); //2b
regs.pc.w = r;
}
}

View File

@@ -1,464 +0,0 @@
inline void bCPU::flags_sbc_b() {
int32 r = regs.a.l - rd.l - !regs.p.c;
//bcd
if(regs.p.d) {
if(((r ) & 15) > 9)r -= 6;
if(((r >> 4) & 15) > 9)r -= 6 << 4;
}
regs.p.n = !!(r & 0x80);
regs.p.v = !!((regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
regs.p.z = ((byte)r == 0);
regs.p.c = (r >= 0);
regs.a.l = r;
}
inline void bCPU::flags_sbc_w() {
int32 r = regs.a.w - rd.w - !regs.p.c;
//bcd
if(regs.p.d) {
if(((r ) & 15) > 9)r -= 6;
if(((r >> 4) & 15) > 9)r -= 6 << 4;
if(((r >> 8) & 15) > 9)r -= 6 << 8;
if(((r >> 12) & 15) > 9)r -= 6 << 12;
}
regs.p.n = !!(r & 0x8000);
regs.p.v = !!((regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
regs.p.z = ((word)r == 0);
regs.p.c = (r >= 0);
regs.a.w = r;
}
/************************
*** 0xe9: sbc #const ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; idl
[2a] pbr,pc+2 ; idh [1]
*/
void bCPU::op_sbc_constb() {
rd.l = op_read(); //2
flags_sbc_b();
}
void bCPU::op_sbc_constw() {
rd.l = op_read(); //2
rd.h = op_read(); //2a
flags_sbc_w();
}
/**********************
*** 0xed: sbc addr ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aa ; data low
[4a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_sbc_addrb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_DBR, aa.w); //4
flags_sbc_b();
}
void bCPU::op_sbc_addrw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_DBR, aa.w); //4
rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a
flags_sbc_w();
}
/************************
*** 0xfd: sbc addr,x ***
************************
cycles:
[1 ] pbr,pc ; opersbc
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[3a] dbr,aah,aal+xl ; io [4]
[4 ] dbr,aa+x ; data low
[4a] dbr,aa+x+1 ; data high [1]
*/
void bCPU::op_sbc_addrxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.x.w); //3a
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4
flags_sbc_b();
}
void bCPU::op_sbc_addrxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.x.w); //3a
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //4
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //4a
flags_sbc_w();
}
/********************
*** 0xe5: sbc dp ***
********************
cycles:
[1 ] pbr,pc ; opersbc
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; data low
[3a] 0,d+dp+1 ; data high [1]
*/
void bCPU::op_sbc_dpb() {
dp = op_read(); //2
cpu_c2(); //2a
rd.l = op_read(OPMODE_DP, dp); //3
flags_sbc_b();
}
void bCPU::op_sbc_dpw() {
dp = op_read(); //2
cpu_c2(); //2a
rd.l = op_read(OPMODE_DP, dp); //3
rd.h = op_read(OPMODE_DP, dp + 1); //3a
flags_sbc_w();
}
/**********************
*** 0xf2: sbc (dp) ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] dbr,aa ; data low
[5a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_sbc_idpb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
rd.l = op_read(OPMODE_DBR, aa.w); //5
flags_sbc_b();
}
void bCPU::op_sbc_idpw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
rd.l = op_read(OPMODE_DBR, aa.w); //5
rd.h = op_read(OPMODE_DBR, aa.w + 1); //5
flags_sbc_w();
}
/**********************
*** 0xe7: sbc [dp] ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] 0,d+dp+2 ; aab
[6 ] aab,aa ; data low
[6a] aab,aa+1 ; data high [1]
*/
void bCPU::op_sbc_ildpb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
rd.l = op_read(OPMODE_LONG, aa.d); //6
flags_sbc_b();
}
void bCPU::op_sbc_ildpw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
rd.l = op_read(OPMODE_LONG, aa.d); //6
rd.h = op_read(OPMODE_LONG, aa.d + 1); //6a
flags_sbc_w();
}
/**********************
*** 0xef: sbc long ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] pbr,pc+3 ; aab
[5 ] aab,aa ; data low
[5a] aab,aa+1 ; data high
*/
void bCPU::op_sbc_longb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
rd.l = op_read(OPMODE_LONG, aa.d); //5
flags_sbc_b();
}
void bCPU::op_sbc_longw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
rd.l = op_read(OPMODE_LONG, aa.d); //5
rd.h = op_read(OPMODE_LONG, aa.d + 1); //5a
flags_sbc_w();
}
/************************
*** 0xff: sbc long,x ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] pbr,pc+3 ; aab
[5 ] aab,aa+x ; data low
[5a] aab,aa+x+1 ; data high
*/
void bCPU::op_sbc_longxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5
flags_sbc_b();
}
void bCPU::op_sbc_longxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w); //5
rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1); //5a
flags_sbc_w();
}
/************************
*** 0xf9: sbc addr,y ***
************************
cycles:
[1 ] pbr,pc ; opersbc
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[3a] dbr,aah,aal+yl ; io [4]
[4 ] dbr,aa+y ; data low
[4a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_sbc_addryb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.y.w); //3a
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4
flags_sbc_b();
}
void bCPU::op_sbc_addryw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.y.w); //3a
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //4
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //4a
flags_sbc_w();
}
/**********************
*** 0xf5: sbc dp,x ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; data low
[4a] 0,d+dp+x+1 ; data high
*/
void bCPU::op_sbc_dpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
flags_sbc_b();
}
void bCPU::op_sbc_dpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
flags_sbc_w();
}
/************************
*** 0xe1: sbc (dp,x) ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; aal
[5 ] 0,d+dp+x+1 ; aah
[6 ] dbr,aa ; data low
[6a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_sbc_idpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
rd.l = op_read(OPMODE_DBR, aa.w); //6
flags_sbc_b();
}
void bCPU::op_sbc_idpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
rd.l = op_read(OPMODE_DBR, aa.w); //6
rd.h = op_read(OPMODE_DBR, aa.w + 1); //6a
flags_sbc_w();
}
/************************
*** 0xf1: sbc (dp),y ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[4a] dbr,aah,aal+yl ; io [4]
[5 ] dbr,aa+y ; data low
[5a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_sbc_idpyb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
cpu_c4(aa.w, aa.w + regs.y.w); //4a
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5
flags_sbc_b();
}
void bCPU::op_sbc_idpyw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
cpu_c4(aa.w, aa.w + regs.y.w); //4a
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //5
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //5a
flags_sbc_w();
}
/************************
*** 0xf7: sbc [dp],y ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] 0,d+dp+2 ; aab
[6 ] aab,aa+y ; data low
[6a] aab,aa+y+1 ; data high [1]
*/
void bCPU::op_sbc_ildpyb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6
flags_sbc_b();
}
void bCPU::op_sbc_ildpyw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w); //6
rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1); //6a
flags_sbc_w();
}
/**********************
*** 0xe3: sbc sr,s ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; sp
[3 ] pbr,pc+1 ; io
[4 ] 0,s+sp ; data low
[4a] 0,s+sp+1 ; data high [1]
*/
void bCPU::op_sbc_srb() {
sp = op_read(); //2
cpu_io(); //3
rd.l = op_read(OPMODE_SP, sp); //4
flags_sbc_b();
}
void bCPU::op_sbc_srw() {
sp = op_read(); //2
cpu_io(); //3
rd.l = op_read(OPMODE_SP, sp); //4
rd.h = op_read(OPMODE_SP, sp + 1); //4a
flags_sbc_w();
}
/**************************
*** 0xf3: sbc (sr,s),y ***
**************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; sp
[3 ] pbr,pc+1 ; io
[4 ] 0,s+sp ; aal
[5 ] 0,s+sp+1 ; aah
[6 ] 0,s+sp+1 ; io
[7 ] dbr,aa+y ; data low
[7a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_sbc_isryb() {
sp = op_read(); //2
cpu_io(); //3
aa.l = op_read(OPMODE_SP, sp); //4
aa.h = op_read(OPMODE_SP, sp + 1); //5
cpu_io(); //6
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7
flags_sbc_b();
}
void bCPU::op_sbc_isryw() {
sp = op_read(); //2
cpu_io(); //3
aa.l = op_read(OPMODE_SP, sp); //4
aa.h = op_read(OPMODE_SP, sp + 1); //5
cpu_io(); //6
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w); //7
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a
flags_sbc_w();
}

View File

@@ -1,779 +0,0 @@
/*****************
*** 0x0a: asl ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void bCPU::op_aslb() {
cpu_io(); //2
regs.p.c = !!(regs.a.l & 0x80);
regs.a.l <<= 1;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
void bCPU::op_aslw() {
cpu_io(); //2
regs.p.c = !!(regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
/**********************
*** 0x0e: asl addr ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aa ; data low
[4a] dbr,aa+1 ; data high [1]
[5 ] dbr,aa+1 ; io
[6a] dbr,aa+1 ; data high [1]
[6 ] dbr,aa ; data low
*/
void bCPU::op_asl_addrb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_DBR, aa.w); //4
regs.p.c = !!(rd.l & 0x80);
rd.l <<= 1;
cpu_io(); //5
op_write(OPMODE_DBR, aa.w, rd.l); //6
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_asl_addrw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_DBR, aa.w); //4
rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a
regs.p.c = !!(rd.w & 0x8000);
rd.w <<= 1;
cpu_io(); //5
op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a
op_write(OPMODE_DBR, aa.w, rd.l); //6
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/************************
*** 0x1e: asl addr,x ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aah,aal+xl ; io
[5 ] dbr,aa+x ; data low
[5a] dbr,aa+x+1 ; data high [1]
[6 ] dbr,aa+x+1 ; io
[7a] dbr,aa+x+1 ; data high [1]
[7 ] dbr,aa+x ; data low
*/
void bCPU::op_asl_addrxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_io(); //4
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
regs.p.c = !!(rd.l & 0x80);
rd.l <<= 1;
cpu_io(); //6
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_asl_addrxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_io(); //4
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //5a
regs.p.c = !!(rd.w & 0x8000);
rd.w <<= 1;
cpu_io(); //6
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); //7a
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/********************
*** 0x06: asl dp ***
********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; data low
[3a] 0,d+dp+1 ; data high [1]
[4 ] 0,d+dp+1 ; io
[5a] 0,d+dp+1 ; data high [1]
[5 ] 0,d+dp ; data low
*/
void bCPU::op_asl_dpb() {
dp = op_read(); //2
cpu_c2(); //2a
rd.l = op_read(OPMODE_DP, dp); //3
regs.p.c = !!(rd.l & 0x80);
rd.l <<= 1;
cpu_io(); //4
op_write(OPMODE_DP, dp, rd.l); //5
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_asl_dpw() {
dp = op_read(); //2
cpu_c2(); //2a
rd.l = op_read(OPMODE_DP, dp); //3
rd.h = op_read(OPMODE_DP, dp + 1); //3a
regs.p.c = !!(rd.w & 0x8000);
rd.w <<= 1;
cpu_io(); //4
op_write(OPMODE_DP, dp + 1, rd.h); //5a
op_write(OPMODE_DP, dp, rd.l); //5
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/**********************
*** 0x16: asl dp,x ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; data low
[4a] 0,d+dp+x+1 ; data high [1]
[5 ] 0,d+dp+x+1 ; io
[6a] 0,d+dp+x+1 ; data high [1]
[6 ] 0,d+dp+x ; data low
*/
void bCPU::op_asl_dpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
regs.p.c = !!(rd.l & 0x80);
rd.l <<= 1;
cpu_io(); //5
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_asl_dpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
regs.p.c = !!(rd.w & 0x8000);
rd.w <<= 1;
cpu_io(); //5
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); //6a
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/*****************
*** 0x4a: lsr ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void bCPU::op_lsrb() {
cpu_io(); //2
regs.p.c = regs.a.l & 1;
regs.a.l >>= 1;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
void bCPU::op_lsrw() {
cpu_io(); //2
regs.p.c = regs.a.w & 1;
regs.a.w >>= 1;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
/**********************
*** 0x4e: lsr addr ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aa ; data low
[4a] dbr,aa+1 ; data high [1]
[5 ] dbr,aa+1 ; io
[6a] dbr,aa+1 ; data high [1]
[6 ] dbr,aa ; data low
*/
void bCPU::op_lsr_addrb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_DBR, aa.w); //4
regs.p.c = rd.l & 1;
rd.l >>= 1;
cpu_io(); //5
op_write(OPMODE_DBR, aa.w, rd.l); //6
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_lsr_addrw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_DBR, aa.w); //4
rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a
regs.p.c = rd.w & 1;
rd.w >>= 1;
cpu_io(); //5
op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a
op_write(OPMODE_DBR, aa.w, rd.l); //6
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/************************
*** 0x5e: lsr addr,x ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aah,aal+xl ; io
[5 ] dbr,aa+x ; data low
[5a] dbr,aa+x+1 ; data high [1]
[6 ] dbr,aa+x+1 ; io
[7a] dbr,aa+x+1 ; data high [1]
[7 ] dbr,aa+x ; data low
*/
void bCPU::op_lsr_addrxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_io(); //4
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
regs.p.c = rd.l & 1;
rd.l >>= 1;
cpu_io(); //6
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_lsr_addrxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_io(); //4
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //5a
regs.p.c = rd.w & 1;
rd.w >>= 1;
cpu_io(); //6
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); //7a
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/********************
*** 0x46: lsr dp ***
********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; data low
[3a] 0,d+dp+1 ; data high [1]
[4 ] 0,d+dp+1 ; io
[5a] 0,d+dp+1 ; data high [1]
[5 ] 0,d+dp ; data low
*/
void bCPU::op_lsr_dpb() {
dp = op_read(); //2
cpu_c2(); //2a
rd.l = op_read(OPMODE_DP, dp); //3
regs.p.c = rd.l & 1;
rd.l >>= 1;
cpu_io(); //4
op_write(OPMODE_DP, dp, rd.l); //5
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_lsr_dpw() {
dp = op_read(); //2
cpu_c2(); //2a
rd.l = op_read(OPMODE_DP, dp); //3
rd.h = op_read(OPMODE_DP, dp + 1); //3a
regs.p.c = rd.w & 1;
rd.w >>= 1;
cpu_io(); //4
op_write(OPMODE_DP, dp + 1, rd.h); //5a
op_write(OPMODE_DP, dp, rd.l); //5
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/**********************
*** 0x56: lsr dp,x ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; data low
[4a] 0,d+dp+x+1 ; data high [1]
[5 ] 0,d+dp+x+1 ; io
[6a] 0,d+dp+x+1 ; data high [1]
[6 ] 0,d+dp+x ; data low
*/
void bCPU::op_lsr_dpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
regs.p.c = rd.l & 1;
rd.l >>= 1;
cpu_io(); //5
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_lsr_dpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
regs.p.c = rd.w & 1;
rd.w >>= 1;
cpu_io(); //5
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); //6a
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/*****************
*** 0x2a: rol ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void bCPU::op_rolb() {
uint8 c = regs.p.c;
cpu_io(); //2
regs.p.c = !!(regs.a.l & 0x80);
regs.a.l <<= 1;
regs.a.l |= c;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
void bCPU::op_rolw() {
uint16 c = regs.p.c;
cpu_io(); //2
regs.p.c = !!(regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.a.w |= c;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
/**********************
*** 0x2e: rol addr ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aa ; data low
[4a] dbr,aa+1 ; data high [1]
[5 ] dbr,aa+1 ; io
[6a] dbr,aa+1 ; data high [1]
[6 ] dbr,aa ; data low
*/
void bCPU::op_rol_addrb() {
uint8 c = regs.p.c;
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_DBR, aa.w); //4
regs.p.c = !!(rd.l & 0x80);
rd.l <<= 1;
rd.l |= c;
cpu_io(); //5
op_write(OPMODE_DBR, aa.w, rd.l); //6
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_rol_addrw() {
uint16 c = regs.p.c;
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_DBR, aa.w); //4
rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a
regs.p.c = !!(rd.w & 0x8000);
rd.w <<= 1;
rd.w |= c;
cpu_io(); //5
op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a
op_write(OPMODE_DBR, aa.w, rd.l); //6
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/************************
*** 0x3e: rol addr,x ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aah,aal+xl ; io
[5 ] dbr,aa+x ; data low
[5a] dbr,aa+x+1 ; data high [1]
[6 ] dbr,aa+x+1 ; io
[7a] dbr,aa+x+1 ; data high [1]
[7 ] dbr,aa+x ; data low
*/
void bCPU::op_rol_addrxb() {
uint8 c = regs.p.c;
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_io(); //4
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
regs.p.c = !!(rd.l & 0x80);
rd.l <<= 1;
rd.l |= c;
cpu_io(); //6
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_rol_addrxw() {
uint16 c = regs.p.c;
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_io(); //4
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //5a
regs.p.c = !!(rd.w & 0x8000);
rd.w <<= 1;
rd.w |= c;
cpu_io(); //6
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); //7a
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/********************
*** 0x26: rol dp ***
********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; data low
[3a] 0,d+dp+1 ; data high [1]
[4 ] 0,d+dp+1 ; io
[5a] 0,d+dp+1 ; data high [1]
[5 ] 0,d+dp ; data low
*/
void bCPU::op_rol_dpb() {
uint8 c = regs.p.c;
dp = op_read(); //2
cpu_c2(); //2a
rd.l = op_read(OPMODE_DP, dp); //3
regs.p.c = !!(rd.l & 0x80);
rd.l <<= 1;
rd.l |= c;
cpu_io(); //4
op_write(OPMODE_DP, dp, rd.l); //5
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_rol_dpw() {
uint16 c = regs.p.c;
dp = op_read(); //2
cpu_c2(); //2a
rd.l = op_read(OPMODE_DP, dp); //3
rd.h = op_read(OPMODE_DP, dp + 1); //3a
regs.p.c = !!(rd.w & 0x8000);
rd.w <<= 1;
rd.w |= c;
cpu_io(); //4
op_write(OPMODE_DP, dp + 1, rd.h); //5a
op_write(OPMODE_DP, dp, rd.l); //5
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/**********************
*** 0x36: rol dp,x ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; data low
[4a] 0,d+dp+x+1 ; data high [1]
[5 ] 0,d+dp+x+1 ; io
[6a] 0,d+dp+x+1 ; data high [1]
[6 ] 0,d+dp+x ; data low
*/
void bCPU::op_rol_dpxb() {
uint8 c = regs.p.c;
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
regs.p.c = !!(rd.l & 0x80);
rd.l <<= 1;
rd.l |= c;
cpu_io(); //5
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_rol_dpxw() {
uint16 c = regs.p.c;
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
regs.p.c = !!(rd.w & 0x8000);
rd.w <<= 1;
rd.w |= c;
cpu_io(); //5
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); //6a
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/*****************
*** 0x6a: ror ***
*****************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; io
*/
void bCPU::op_rorb() {
uint8 c = (regs.p.c)?0x80:0;
cpu_io(); //2
regs.p.c = regs.a.l & 1;
regs.a.l >>= 1;
regs.a.l |= c;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
void bCPU::op_rorw() {
uint16 c = (regs.p.c)?0x8000:0;
cpu_io(); //2
regs.p.c = regs.a.w & 1;
regs.a.w >>= 1;
regs.a.w |= c;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
/**********************
*** 0x6e: ror addr ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aa ; data low
[4a] dbr,aa+1 ; data high [1]
[5 ] dbr,aa+1 ; io
[6a] dbr,aa+1 ; data high [1]
[6 ] dbr,aa ; data low
*/
void bCPU::op_ror_addrb() {
uint8 c = (regs.p.c)?0x80:0;
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_DBR, aa.w); //4
regs.p.c = rd.l & 1;
rd.l >>= 1;
rd.l |= c;
cpu_io(); //5
op_write(OPMODE_DBR, aa.w, rd.l); //6
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_ror_addrw() {
uint16 c = (regs.p.c)?0x8000:0;
aa.l = op_read(); //2
aa.h = op_read(); //3
rd.l = op_read(OPMODE_DBR, aa.w); //4
rd.h = op_read(OPMODE_DBR, aa.w + 1); //4a
regs.p.c = rd.w & 1;
rd.w >>= 1;
rd.w |= c;
cpu_io(); //5
op_write(OPMODE_DBR, aa.w + 1, rd.h); //6a
op_write(OPMODE_DBR, aa.w, rd.l); //6
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/************************
*** 0x7e: ror addr,x ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aah,aal+xl ; io
[5 ] dbr,aa+x ; data low
[5a] dbr,aa+x+1 ; data high [1]
[6 ] dbr,aa+x+1 ; io
[7a] dbr,aa+x+1 ; data high [1]
[7 ] dbr,aa+x ; data low
*/
void bCPU::op_ror_addrxb() {
uint8 c = (regs.p.c)?0x80:0;
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_io(); //4
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
regs.p.c = rd.l & 1;
rd.l >>= 1;
rd.l |= c;
cpu_io(); //6
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_ror_addrxw() {
uint16 c = (regs.p.c)?0x8000:0;
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_io(); //4
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w); //5
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1); //5a
regs.p.c = rd.w & 1;
rd.w >>= 1;
rd.w |= c;
cpu_io(); //6
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h); //7a
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l); //7
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/********************
*** 0x66: ror dp ***
********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; data low
[3a] 0,d+dp+1 ; data high [1]
[4 ] 0,d+dp+1 ; io
[5a] 0,d+dp+1 ; data high [1]
[5 ] 0,d+dp ; data low
*/
void bCPU::op_ror_dpb() {
uint8 c = (regs.p.c)?0x80:0;
dp = op_read(); //2
cpu_c2(); //2a
rd.l = op_read(OPMODE_DP, dp); //3
regs.p.c = rd.l & 1;
rd.l >>= 1;
rd.l |= c;
cpu_io(); //4
op_write(OPMODE_DP, dp, rd.l); //5
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_ror_dpw() {
uint16 c = (regs.p.c)?0x8000:0;
dp = op_read(); //2
cpu_c2(); //2a
rd.l = op_read(OPMODE_DP, dp); //3
rd.h = op_read(OPMODE_DP, dp + 1); //3a
regs.p.c = rd.w & 1;
rd.w >>= 1;
rd.w |= c;
cpu_io(); //4
op_write(OPMODE_DP, dp + 1, rd.h); //5a
op_write(OPMODE_DP, dp, rd.l); //5
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
/**********************
*** 0x76: ror dp,x ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; data low
[4a] 0,d+dp+x+1 ; data high [1]
[5 ] 0,d+dp+x+1 ; io
[6a] 0,d+dp+x+1 ; data high [1]
[6 ] 0,d+dp+x ; data low
*/
void bCPU::op_ror_dpxb() {
uint8 c = (regs.p.c)?0x80:0;
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
regs.p.c = rd.l & 1;
rd.l >>= 1;
rd.l |= c;
cpu_io(); //5
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
void bCPU::op_ror_dpxw() {
uint16 c = (regs.p.c)?0x8000:0;
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
rd.l = op_read(OPMODE_DP, dp + regs.x.w); //4
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //4a
regs.p.c = rd.w & 1;
rd.w >>= 1;
rd.w |= c;
cpu_io(); //5
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h); //6a
op_write(OPMODE_DP, dp + regs.x.w, rd.l); //6
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}

View File

@@ -1,387 +0,0 @@
/**********************
*** 0x8d: sta addr ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] dbr,aa ; data low
[4a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_sta_addrb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
op_write(OPMODE_DBR, aa.w, regs.a.l); //4
}
void bCPU::op_sta_addrw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
op_write(OPMODE_DBR, aa.w, regs.a.l); //4
op_write(OPMODE_DBR, aa.w + 1, regs.a.h); //4a
}
/************************
*** 0x9d: sta addr,x ***
************************
cycles:
[1 ] pbr,pc ; operand
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[3a] dbr,aah,aal+xl ; io [4]
[4 ] dbr,aa+x ; data low
[4a] dbr,aa+x+1 ; data high [1]
*/
void bCPU::op_sta_addrxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.x.w); //3a
op_write(OPMODE_DBR, aa.w + regs.x.w, regs.a.l); //4
}
void bCPU::op_sta_addrxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.x.w); //3a
op_write(OPMODE_DBR, aa.w + regs.x.w, regs.a.l); //4
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, regs.a.h); //4a
}
/********************
*** 0x85: sta dp ***
********************
cycles:
[1 ] pbr,pc ; operand
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; data low
[3a] 0,d+dp+1 ; data high [1]
*/
void bCPU::op_sta_dpb() {
dp = op_read(); //2
cpu_c2(); //2a
op_write(OPMODE_DP, dp, regs.a.l); //3
}
void bCPU::op_sta_dpw() {
dp = op_read(); //2
cpu_c2(); //2a
op_write(OPMODE_DP, dp, regs.a.l); //3
op_write(OPMODE_DP, dp + 1, regs.a.h); //3a
}
/**********************
*** 0x92: sta (dp) ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] dbr,aa ; data low
[5a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_sta_idpb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
op_write(OPMODE_DBR, aa.w, regs.a.l); //5
}
void bCPU::op_sta_idpw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
op_write(OPMODE_DBR, aa.w, regs.a.l); //5
op_write(OPMODE_DBR, aa.w + 1, regs.a.h); //5
}
/**********************
*** 0x87: sta [dp] ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] 0,d+dp+2 ; aab
[6 ] aab,aa ; data low
[6a] aab,aa+1 ; data high [1]
*/
void bCPU::op_sta_ildpb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
op_write(OPMODE_LONG, aa.d, regs.a.l); //6
}
void bCPU::op_sta_ildpw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
op_write(OPMODE_LONG, aa.d, regs.a.l); //6
op_write(OPMODE_LONG, aa.d + 1, regs.a.h); //6a
}
/**********************
*** 0x8f: sta long ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] pbr,pc+3 ; aab
[5 ] aab,aa ; data low
[5a] aab,aa+1 ; data high
*/
void bCPU::op_sta_longb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
op_write(OPMODE_LONG, aa.d, regs.a.l); //5
}
void bCPU::op_sta_longw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
op_write(OPMODE_LONG, aa.d, regs.a.l); //5
op_write(OPMODE_LONG, aa.d + 1, regs.a.h); //5a
}
/************************
*** 0x9f: sta long,x ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[4 ] pbr,pc+3 ; aab
[5 ] aab,aa+x ; data low
[5a] aab,aa+x+1 ; data high
*/
void bCPU::op_sta_longxb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
op_write(OPMODE_LONG, aa.d + regs.x.w, regs.a.l); //5
}
void bCPU::op_sta_longxw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
aa.b = op_read(); //4
op_write(OPMODE_LONG, aa.d + regs.x.w, regs.a.l); //5
op_write(OPMODE_LONG, aa.d + regs.x.w + 1, regs.a.h); //5a
}
/************************
*** 0x99: sta addr,y ***
************************
cycles:
[1 ] pbr,pc ; operand
[2 ] pbr,pc+1 ; aal
[3 ] pbr,pc+2 ; aah
[3a] dbr,aah,aal+yl ; io [4]
[4 ] dbr,aa+y ; data low
[4a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_sta_addryb() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.y.w); //3a
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //4
}
void bCPU::op_sta_addryw() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_c4(aa.w, aa.w + regs.y.w); //3a
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //4
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h); //4a
}
/**********************
*** 0x95: sta dp,x ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; data low
[4a] 0,d+dp+x+1 ; data high
*/
void bCPU::op_sta_dpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
op_write(OPMODE_DP, dp + regs.x.w, regs.a.l); //4
}
void bCPU::op_sta_dpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
op_write(OPMODE_DP, dp + regs.x.w, regs.a.l); //4
op_write(OPMODE_DP, dp + regs.x.w + 1, regs.a.h); //4a
}
/************************
*** 0x81: sta (dp,x) ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] pbr,pc+1 ; io
[4 ] 0,d+dp+x ; aal
[5 ] 0,d+dp+x+1 ; aah
[6 ] dbr,aa ; data low
[6a] dbr,aa+1 ; data high [1]
*/
void bCPU::op_sta_idpxb() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
op_write(OPMODE_DBR, aa.w, regs.a.l); //6
}
void bCPU::op_sta_idpxw() {
dp = op_read(); //2
cpu_c2(); //2a
cpu_io(); //3
aa.l = op_read(OPMODE_DP, dp + regs.x.w); //4
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1); //5
op_write(OPMODE_DBR, aa.w, regs.a.l); //6
op_write(OPMODE_DBR, aa.w + 1, regs.a.h); //6a
}
/************************
*** 0x91: sta (dp),y ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[4a] dbr,aah,aal+yl ; io [4]
[5 ] dbr,aa+y ; data low
[5a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_sta_idpyb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
cpu_c4(aa.w, aa.w + regs.y.w); //4a
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //5
}
void bCPU::op_sta_idpyw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
cpu_c4(aa.w, aa.w + regs.y.w); //4a
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //5
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h); //5a
}
/************************
*** 0x97: sta [dp],y ***
************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io [2]
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] 0,d+dp+2 ; aab
[6 ] aab,aa+y ; data low
[6a] aab,aa+y+1 ; data high [1]
*/
void bCPU::op_sta_ildpyb() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
op_write(OPMODE_LONG, aa.d + regs.y.w, regs.a.l); //6
}
void bCPU::op_sta_ildpyw() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
aa.b = op_read(OPMODE_DP, dp + 2); //5
op_write(OPMODE_LONG, aa.d + regs.y.w, regs.a.l); //6
op_write(OPMODE_LONG, aa.d + regs.y.w + 1, regs.a.h); //6a
}
/**********************
*** 0x83: sta sr,s ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; sp
[3 ] pbr,pc+1 ; io
[4 ] 0,s+sp ; data low
[4a] 0,s+sp+1 ; data high [1]
*/
void bCPU::op_sta_srb() {
sp = op_read(); //2
cpu_io(); //3
op_write(OPMODE_SP, sp, regs.a.l); //4
}
void bCPU::op_sta_srw() {
sp = op_read(); //2
cpu_io(); //3
op_write(OPMODE_SP, sp, regs.a.l); //4
op_write(OPMODE_SP, sp + 1, regs.a.h); //4a
}
/**************************
*** 0x93: sta (sr,s),y ***
**************************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; sp
[3 ] pbr,pc+1 ; io
[4 ] 0,s+sp ; aal
[5 ] 0,s+sp+1 ; aah
[6 ] 0,s+sp+1 ; io
[7 ] dbr,aa+y ; data low
[7a] dbr,aa+y+1 ; data high [1]
*/
void bCPU::op_sta_isryb() {
sp = op_read(); //2
cpu_io(); //3
aa.l = op_read(OPMODE_SP, sp); //4
aa.h = op_read(OPMODE_SP, sp + 1); //5
cpu_io(); //6
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //7
}
void bCPU::op_sta_isryw() {
sp = op_read(); //2
cpu_io(); //3
aa.l = op_read(OPMODE_SP, sp); //4
aa.h = op_read(OPMODE_SP, sp + 1); //5
cpu_io(); //6
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //7
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h); //7a
}

View File

@@ -1,317 +0,0 @@
/*****************
*** 0x48: pha ***
*****************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; io
[3a] 0,s ; reg high [1]
[3 ] 0,s-1 ; reg low
*/
void bCPU::op_phab() {
cpu_io(); //2
stack_write(regs.a.l); //3
}
void bCPU::op_phaw() {
cpu_io(); //2
stack_write(regs.a.h); //3a
stack_write(regs.a.l); //3
}
/*****************
*** 0x8b: phb ***
*****************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; io
[3 ] 0,s-1 ; dbr
*/
void bCPU::op_phb() {
cpu_io(); //2
stack_write(regs.db); //3
}
/*****************
*** 0x0b: phd ***
*****************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; io
[3a] 0,s ; reg high
[3 ] 0,s-1 ; reg low
*/
void bCPU::op_phd() {
cpu_io(); //2
stack_write(regs.d.h); //3a
stack_write(regs.d.l); //3
}
/*****************
*** 0x4b: phk ***
*****************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; io
[3 ] 0,s-1 ; pcb
*/
void bCPU::op_phk() {
cpu_io(); //2
stack_write(regs.pc.b); //3
}
/*****************
*** 0x08: php ***
*****************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; io
[3 ] 0,s-1 ; reg low
*/
void bCPU::op_php() {
cpu_io(); //2
stack_write(regs.p); //3
}
/*****************
*** 0xda: phx ***
*****************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; io
[3a] 0,s ; reg high [1]
[3 ] 0,s-1 ; reg low
*/
void bCPU::op_phxb() {
cpu_io(); //2
stack_write(regs.x.l); //3
}
void bCPU::op_phxw() {
cpu_io(); //2
stack_write(regs.x.h); //3a
stack_write(regs.x.l); //3
}
/*****************
*** 0x5a: phy ***
*****************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; io
[3a] 0,s ; reg high [1]
[3 ] 0,s-1 ; reg low
*/
void bCPU::op_phyb() {
cpu_io(); //2
stack_write(regs.y.l); //3
}
void bCPU::op_phyw() {
cpu_io(); //2
stack_write(regs.y.h); //3a
stack_write(regs.y.l); //3
}
/*****************
*** 0x68: pla ***
*****************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; io
[3 ] pbr,pc+1 ; io
[4 ] 0,s+1 ; reg low
[4a] 0,s+2 ; reg high [1]
*/
void bCPU::op_plab() {
cpu_io(); //2
cpu_io(); //3
regs.a.l = stack_read(); //4
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
void bCPU::op_plaw() {
cpu_io(); //2
cpu_io(); //3
regs.a.l = stack_read(); //4
regs.a.h = stack_read(); //4a
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
/*****************
*** 0xab: plb ***
*****************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; io
[3 ] pbr,pc+1 ; io
[4 ] 0,s+1 ; reg low
*/
void bCPU::op_plb() {
cpu_io(); //2
cpu_io(); //3
regs.db = stack_read(); //4
regs.p.n = !!(regs.db & 0x80);
regs.p.z = (regs.db == 0);
}
/*****************
*** 0x2b: pld ***
*****************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; io
[3 ] pbr,pc+1 ; io
[4 ] 0,s+1 ; reg low
[4a] 0,s+2 ; reg high
*/
void bCPU::op_pld() {
cpu_io(); //2
cpu_io(); //3
regs.d.l = stack_read(); //4
regs.d.h = stack_read(); //4a
regs.p.n = !!(regs.d.w & 0x8000);
regs.p.z = (regs.d.w == 0);
}
/*****************
*** 0x28: plp ***
*****************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; io
[3 ] pbr,pc+1 ; io
[4 ] 0,s+1 ; reg low
*/
void bCPU::op_plp() {
cpu_io(); //2
cpu_io(); //3
regs.p = stack_read(); //4
if(regs.e) {
regs.p |= 0x30;
} else {
switch((regs.p >> 4) & 3) {
case 0:optbl = optbl_mx;break;
case 1:optbl = optbl_mX;break;
case 2:optbl = optbl_Mx;break;
case 3:optbl = optbl_MX;break;
}
}
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
}
/*****************
*** 0xfa: plx ***
*****************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; io
[3 ] pbr,pc+1 ; io
[4 ] 0,s+1 ; reg low
[4a] 0,s+2 ; reg high [1]
*/
void bCPU::op_plxb() {
cpu_io(); //2
cpu_io(); //3
regs.x.l = stack_read(); //4
regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
}
void bCPU::op_plxw() {
cpu_io(); //2
cpu_io(); //3
regs.x.l = stack_read(); //4
regs.x.h = stack_read(); //4a
regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
/*****************
*** 0x7a: ply ***
*****************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; io
[3 ] pbr,pc+1 ; io
[4 ] 0,s+1 ; reg low
[4a] 0,s+2 ; reg high [1]
*/
void bCPU::op_plyb() {
cpu_io(); //2
cpu_io(); //3
regs.y.l = stack_read(); //4
regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
}
void bCPU::op_plyw() {
cpu_io(); //2
cpu_io(); //3
regs.y.l = stack_read(); //4
regs.y.h = stack_read(); //4a
regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
}
/**********************
*** 0xf4: pea addr ***
**********************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; aal
[3] pbr,pc+2 ; aah
[4] 0,s ; aah
[5] 0,s-1 ; aal
*/
void bCPU::op_pea() {
aa.l = op_read(); //2
aa.h = op_read(); //3
stack_write(aa.h); //4
stack_write(aa.l); //5
}
/**********************
*** 0xd4: pei (dp) ***
**********************
cycles:
[1 ] pbr,pc ; opcode
[2 ] pbr,pc+1 ; dp
[2a] pbr,pc+1 ; io
[3 ] 0,d+dp ; aal
[4 ] 0,d+dp+1 ; aah
[5 ] 0,s ; aah
[6 ] 0,s-1 ; aal
*/
void bCPU::op_pei() {
dp = op_read(); //2
cpu_c2(); //2a
aa.l = op_read(OPMODE_DP, dp); //3
aa.h = op_read(OPMODE_DP, dp + 1); //4
stack_write(aa.h); //5
stack_write(aa.l); //6
}
/**********************
*** 0x62: per addr ***
**********************
cycles:
[1] pbr,pc ; opcode
[2] pbr,pc+1 ; offset low
[3] pbr,pc+2 ; offset high
[4] pbr,pc+2 ; io
[5] 0,s ; pch+offset
[6] 0,s-1 ; pcl+offset
*/
void bCPU::op_per() {
aa.l = op_read(); //2
aa.h = op_read(); //3
cpu_io(); //4
rd.w = regs.pc.d + (int16)aa.w;
stack_write(rd.h); //5
stack_write(rd.l); //6
}

View File

@@ -0,0 +1,18 @@
#define CLASS_NAME "bCPU"
#include "../../../lib/opgen.cpp"
int main() {
fph = fopen("op.h", "wb");
fpt = fopen("optable.cpp", "wb");
generate("op_read.cpp", "op_read.b");
generate("op_rmw.cpp", "op_rmw.b");
generate("op_write.cpp", "op_write.b");
generate("op_pc.cpp", "op_pc.b");
generate("op_misc.cpp", "op_misc.b");
fclose(fph);
fclose(fpt);
return 0;
}

3
src/cpu/bcpu/core/cc.bat Normal file
View File

@@ -0,0 +1,3 @@
cl /O2 /wd4996 bcpugen.cpp
@pause
@del *.obj

View File

@@ -0,0 +1 @@
@del *.exe

View File

@@ -0,0 +1,28 @@
#include "opfn.cpp"
#include "op_read.cpp"
#include "op_rmw.cpp"
#include "op_write.cpp"
#include "op_pc.cpp"
#include "op_misc.cpp"
void bCPU::cpu_c2() {
if(regs.d.l != 0x00) {
cpu_io();
}
}
void bCPU::cpu_c4(uint16 x, uint16 y) {
if(!regs.p.x || (x & 0xff00) != (y & 0xff00)) {
cpu_io();
}
}
void bCPU::cpu_c6(uint16 addr) {
if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) {
cpu_io();
}
}
void bCPU::init_op_tables() {
#include "optable.cpp"
}

62
src/cpu/bcpu/core/core.h Normal file
View File

@@ -0,0 +1,62 @@
/* External functions:
* void last_cycle();
* void cpu_io();
* uint8 mem_read(uint32 addr);
* void mem_write(uint32 addr, uint8 value);
*/
void (bCPU::*optbl[256])();
CPUReg24 aa, rd;
uint8 dp, sp;
//op_read
inline void op_adc_b();
inline void op_adc_w();
inline void op_and_b();
inline void op_and_w();
inline void op_bit_b();
inline void op_bit_w();
inline void op_cmp_b();
inline void op_cmp_w();
inline void op_cpx_b();
inline void op_cpx_w();
inline void op_cpy_b();
inline void op_cpy_w();
inline void op_eor_b();
inline void op_eor_w();
inline void op_lda_b();
inline void op_lda_w();
inline void op_ldx_b();
inline void op_ldx_w();
inline void op_ldy_b();
inline void op_ldy_w();
inline void op_ora_b();
inline void op_ora_w();
inline void op_sbc_b();
inline void op_sbc_w();
//op_rmw
inline void op_inc_b();
inline void op_inc_w();
inline void op_dec_b();
inline void op_dec_w();
inline void op_asl_b();
inline void op_asl_w();
inline void op_lsr_b();
inline void op_lsr_w();
inline void op_rol_b();
inline void op_rol_w();
inline void op_ror_b();
inline void op_ror_w();
inline void op_trb_b();
inline void op_trb_w();
inline void op_tsb_b();
inline void op_tsb_w();
inline void cpu_c2();
inline void cpu_c4(uint16 x, uint16 y);
inline void cpu_c6(uint16 addr);
inline void init_op_tables();
#include "op.h"

256
src/cpu/bcpu/core/op.h Normal file
View File

@@ -0,0 +1,256 @@
void op_adc_const();
void op_and_const();
void op_cmp_const();
void op_cpx_const();
void op_cpy_const();
void op_eor_const();
void op_lda_const();
void op_ldx_const();
void op_ldy_const();
void op_ora_const();
void op_sbc_const();
void op_adc_addr();
void op_and_addr();
void op_bit_addr();
void op_cmp_addr();
void op_cpx_addr();
void op_cpy_addr();
void op_eor_addr();
void op_lda_addr();
void op_ldx_addr();
void op_ldy_addr();
void op_ora_addr();
void op_sbc_addr();
void op_adc_addrx();
void op_and_addrx();
void op_bit_addrx();
void op_cmp_addrx();
void op_eor_addrx();
void op_lda_addrx();
void op_ldy_addrx();
void op_ora_addrx();
void op_sbc_addrx();
void op_adc_addry();
void op_and_addry();
void op_cmp_addry();
void op_eor_addry();
void op_lda_addry();
void op_ldx_addry();
void op_ora_addry();
void op_sbc_addry();
void op_adc_long();
void op_and_long();
void op_cmp_long();
void op_eor_long();
void op_lda_long();
void op_ora_long();
void op_sbc_long();
void op_adc_longx();
void op_and_longx();
void op_cmp_longx();
void op_eor_longx();
void op_lda_longx();
void op_ora_longx();
void op_sbc_longx();
void op_adc_dp();
void op_and_dp();
void op_bit_dp();
void op_cmp_dp();
void op_cpx_dp();
void op_cpy_dp();
void op_eor_dp();
void op_lda_dp();
void op_ldx_dp();
void op_ldy_dp();
void op_ora_dp();
void op_sbc_dp();
void op_adc_dpx();
void op_and_dpx();
void op_bit_dpx();
void op_cmp_dpx();
void op_eor_dpx();
void op_lda_dpx();
void op_ldy_dpx();
void op_ora_dpx();
void op_sbc_dpx();
void op_ldx_dpy();
void op_adc_idp();
void op_and_idp();
void op_cmp_idp();
void op_eor_idp();
void op_lda_idp();
void op_ora_idp();
void op_sbc_idp();
void op_adc_idpx();
void op_and_idpx();
void op_cmp_idpx();
void op_eor_idpx();
void op_lda_idpx();
void op_ora_idpx();
void op_sbc_idpx();
void op_adc_idpy();
void op_and_idpy();
void op_cmp_idpy();
void op_eor_idpy();
void op_lda_idpy();
void op_ora_idpy();
void op_sbc_idpy();
void op_adc_ildp();
void op_and_ildp();
void op_cmp_ildp();
void op_eor_ildp();
void op_lda_ildp();
void op_ora_ildp();
void op_sbc_ildp();
void op_adc_ildpy();
void op_and_ildpy();
void op_cmp_ildpy();
void op_eor_ildpy();
void op_lda_ildpy();
void op_ora_ildpy();
void op_sbc_ildpy();
void op_adc_sr();
void op_and_sr();
void op_cmp_sr();
void op_eor_sr();
void op_lda_sr();
void op_ora_sr();
void op_sbc_sr();
void op_adc_isry();
void op_and_isry();
void op_cmp_isry();
void op_eor_isry();
void op_lda_isry();
void op_ora_isry();
void op_sbc_isry();
void op_bit_const();
void op_inc();
void op_inx();
void op_iny();
void op_dec();
void op_dex();
void op_dey();
void op_asl();
void op_lsr();
void op_rol();
void op_ror();
void op_inc_addr();
void op_dec_addr();
void op_asl_addr();
void op_lsr_addr();
void op_rol_addr();
void op_ror_addr();
void op_trb_addr();
void op_tsb_addr();
void op_inc_addrx();
void op_dec_addrx();
void op_asl_addrx();
void op_lsr_addrx();
void op_rol_addrx();
void op_ror_addrx();
void op_inc_dp();
void op_dec_dp();
void op_asl_dp();
void op_lsr_dp();
void op_rol_dp();
void op_ror_dp();
void op_trb_dp();
void op_tsb_dp();
void op_inc_dpx();
void op_dec_dpx();
void op_asl_dpx();
void op_lsr_dpx();
void op_rol_dpx();
void op_ror_dpx();
void op_sta_addr();
void op_stx_addr();
void op_sty_addr();
void op_stz_addr();
void op_sta_addrx();
void op_stz_addrx();
void op_sta_addry();
void op_sta_long();
void op_sta_longx();
void op_sta_dp();
void op_stx_dp();
void op_sty_dp();
void op_stz_dp();
void op_sta_dpx();
void op_sty_dpx();
void op_stz_dpx();
void op_stx_dpy();
void op_sta_idp();
void op_sta_ildp();
void op_sta_idpx();
void op_sta_idpy();
void op_sta_ildpy();
void op_sta_sr();
void op_sta_isry();
void op_bcc();
void op_bcs();
void op_bne();
void op_beq();
void op_bpl();
void op_bmi();
void op_bvc();
void op_bvs();
void op_bra();
void op_brl();
void op_jmp_addr();
void op_jmp_long();
void op_jmp_iaddr();
void op_jmp_iaddrx();
void op_jmp_iladdr();
void op_jsr_addr();
void op_jsr_long();
void op_jsr_iaddrx();
void op_rti();
void op_rts();
void op_rtl();
void op_nop();
void op_wdm();
void op_xba();
void op_mvn();
void op_mvp();
void op_brk();
void op_cop();
void op_stp();
void op_wai();
void op_xce();
void op_clc();
void op_cld();
void op_cli();
void op_clv();
void op_sec();
void op_sed();
void op_sei();
void op_rep();
void op_sep();
void op_tax();
void op_tay();
void op_txa();
void op_txy();
void op_tya();
void op_tyx();
void op_tcd();
void op_tcs();
void op_tdc();
void op_tsc();
void op_tsx();
void op_txs();
void op_pha();
void op_phx();
void op_phy();
void op_phd();
void op_phb();
void op_phk();
void op_php();
void op_pla();
void op_plx();
void op_ply();
void op_pld();
void op_plb();
void op_plp();
void op_pea();
void op_pei();
void op_per();

282
src/cpu/bcpu/core/op_misc.b Normal file
View File

@@ -0,0 +1,282 @@
nop(0xea) {
1:last_cycle();
cpu_io();
}
wdm(0x42) {
1:last_cycle();
op_readpc();
}
xba(0xeb) {
1:cpu_io();
2:last_cycle();
cpu_io();
regs.a.l ^= regs.a.h;
regs.a.h ^= regs.a.l;
regs.a.l ^= regs.a.h;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
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:cpu_io();
if(regs.p.x) { regs.x.l$1; regs.y.l$1; }
else { regs.x.w$1; regs.y.w$1; }
6:last_cycle();
cpu_io();
if(regs.a.w--)regs.pc.w -= 3;
}
brk(0x00, 0xfffe, 0xffff, 0xffe6, 0xffe7),
cop(0x02, 0xfff4, 0xfff5, 0xffe4, 0xffe5) {
1:op_readpc();
if(regs.e)skip;
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_readlong((regs.e) ? $2 : $4);
regs.pc.w = rd.w;
}
stp(0xdb) {
1:cpu_io();
run_state.stp = true;
2:last_cycle();
cpu_io();
regs.pc.w--;
}
wai(0xcb) {
1:cpu_io();
run_state.wai = true;
2:last_cycle();
cpu_io();
//no wakeup delay if last_cycle() cancelled wai
if(run_state.wai == false)end;
3:last_cycle();
cpu_io();
//sleep another i/o cycle
//note: this should alert the debugger that wai is continuing...
if(run_state.wai == true)status.cycle_pos--;
//wai wakeup delay (one i/o cycle)
4:last_cycle();
cpu_io();
}
xce(0xfb) {
1:last_cycle();
cpu_io();
bool c = regs.p.c;
regs.p.c = regs.e;
regs.e = c;
if(regs.e) {
regs.p |= 0x30;
regs.x.h = 0x00;
regs.y.h = 0x00;
regs.s.h = 0x01;
}
}
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();
cpu_io();
$1;
}
rep(0xc2, &=~),
sep(0xe2, |=) {
1:rd.l = op_readpc();
2:last_cycle();
cpu_io();
regs.p $1 rd.l;
if(regs.e)regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
}
tax(0xaa, regs.p.x, x, a),
tay(0xa8, regs.p.x, y, a),
txa(0x8a, regs.p.m, a, x),
txy(0x9b, regs.p.x, y, x),
tya(0x98, regs.p.m, a, y),
tyx(0xbb, regs.p.x, x, y) {
1:last_cycle();
cpu_io();
if($1) {
regs.$2.l = regs.$3.l;
regs.p.n = !!(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0);
} else {
regs.$2.w = regs.$3.w;
regs.p.n = !!(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0);
}
}
tcd(0x5b) {
1:last_cycle();
cpu_io();
regs.d.w = regs.a.w;
regs.p.n = !!(regs.d.w & 0x8000);
regs.p.z = (regs.d.w == 0);
}
tcs(0x1b) {
1:last_cycle();
cpu_io();
regs.s.w = regs.a.w;
if(regs.e)regs.s.h = 0x01;
}
tdc(0x7b) {
1:last_cycle();
cpu_io();
regs.a.w = regs.d.w;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
tsc(0x3b) {
1:last_cycle();
cpu_io();
regs.a.w = regs.s.w;
if(regs.e) {
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
tsx(0xba) {
1:last_cycle();
cpu_io();
if(regs.p.x) {
regs.x.l = regs.s.l;
regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
} else {
regs.x.w = regs.s.w;
regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
}
txs(0x9a) {
1:last_cycle();
cpu_io();
if(regs.e) {
regs.s.l = regs.x.l;
} else {
regs.s.w = regs.x.w;
}
}
pha(0x48, regs.p.m, a),
phx(0xda, regs.p.x, x),
phy(0x5a, regs.p.x, y),
phd(0x0b, 0, d) {
1:cpu_io();
if($1)skip;
2: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:cpu_io();
2:last_cycle();
op_writestack($1);
}
pla(0x68, regs.p.m, a),
plx(0xfa, regs.p.x, x),
ply(0x7a, regs.p.x, y),
pld(0x2b, 0, d) {
1:cpu_io();
2:cpu_io();
3:if($1)last_cycle();
regs.$2.l = op_readstack();
if($1) {
regs.p.n = !!(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0);
end;
}
4:last_cycle();
regs.$2.h = op_readstack();
regs.p.n = !!(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0);
}
plb(0xab) {
1:cpu_io();
2:cpu_io();
3:last_cycle();
regs.db = op_readstack();
regs.p.n = !!(regs.db & 0x80);
regs.p.z = (regs.db == 0);
}
plp(0x28) {
1:cpu_io();
2:cpu_io();
3:last_cycle();
regs.p = op_readstack();
if(regs.e)regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
}
pea(0xf4) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_writestack(aa.h);
4:last_cycle();
op_writestack(aa.l);
}
pei(0xd4) {
1:dp = op_readpc();
2:cpu_c2();
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:cpu_io();
rd.w = regs.pc.d + (int16)aa.w;
4:op_writestack(rd.h);
5:last_cycle();
op_writestack(rd.l);
}

View File

@@ -0,0 +1,864 @@
void bCPU::op_nop() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_wdm() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
op_readpc();
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_xba() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
} break;
case 2: {
last_cycle();
cpu_io();
regs.a.l ^= regs.a.h;
regs.a.h ^= regs.a.l;
regs.a.l ^= regs.a.h;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_mvn() {
switch(status.cycle_pos++) {
case 1: {
dp = op_readpc();
} break;
case 2: {
sp = op_readpc();
} break;
case 3: {
regs.db = dp;
rd.l = op_readlong((sp << 16) | regs.x.w);
} break;
case 4: {
op_writelong((dp << 16) | regs.y.w, rd.l);
} break;
case 5: {
cpu_io();
if(regs.p.x) { regs.x.l++; regs.y.l++; }
else { regs.x.w++; regs.y.w++; }
} break;
case 6: {
last_cycle();
cpu_io();
if(regs.a.w--)regs.pc.w -= 3;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_mvp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_readpc();
} break;
case 2: {
sp = op_readpc();
} break;
case 3: {
regs.db = dp;
rd.l = op_readlong((sp << 16) | regs.x.w);
} break;
case 4: {
op_writelong((dp << 16) | regs.y.w, rd.l);
} break;
case 5: {
cpu_io();
if(regs.p.x) { regs.x.l--; regs.y.l--; }
else { regs.x.w--; regs.y.w--; }
} break;
case 6: {
last_cycle();
cpu_io();
if(regs.a.w--)regs.pc.w -= 3;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_brk() {
switch(status.cycle_pos++) {
case 1: {
op_readpc();
if(regs.e)status.cycle_pos++;
} break;
case 2: {
op_writestack(regs.pc.b);
} break;
case 3: {
op_writestack(regs.pc.h);
} break;
case 4: {
op_writestack(regs.pc.l);
} break;
case 5: {
op_writestack(regs.p);
} break;
case 6: {
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_readlong((regs.e) ? 0xffff : 0xffe7);
regs.pc.w = rd.w;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_cop() {
switch(status.cycle_pos++) {
case 1: {
op_readpc();
if(regs.e)status.cycle_pos++;
} break;
case 2: {
op_writestack(regs.pc.b);
} break;
case 3: {
op_writestack(regs.pc.h);
} break;
case 4: {
op_writestack(regs.pc.l);
} break;
case 5: {
op_writestack(regs.p);
} break;
case 6: {
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_readlong((regs.e) ? 0xfff5 : 0xffe5);
regs.pc.w = rd.w;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_stp() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
run_state.stp = true;
} break;
case 2: {
last_cycle();
cpu_io();
regs.pc.w--;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_wai() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
run_state.wai = true;
} break;
case 2: {
last_cycle();
cpu_io();
//no wakeup delay if last_cycle() cancelled wai
if(run_state.wai == false)status.cycle_pos = 0;
} break;
case 3: {
last_cycle();
cpu_io();
//sleep another i/o cycle
//note: this should alert the debugger that wai is continuing...
if(run_state.wai == true)status.cycle_pos--;
//wai wakeup delay (one i/o cycle)
} break;
case 4: {
last_cycle();
cpu_io();
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_xce() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
bool c = regs.p.c;
regs.p.c = regs.e;
regs.e = c;
if(regs.e) {
regs.p |= 0x30;
regs.x.h = 0x00;
regs.y.h = 0x00;
regs.s.h = 0x01;
}
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_clc() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
regs.p.c = 0;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_cld() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
regs.p.d = 0;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_cli() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
regs.p.i = 0;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_clv() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
regs.p.v = 0;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sec() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
regs.p.c = 1;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sed() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
regs.p.d = 1;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sei() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
regs.p.i = 1;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_rep() {
switch(status.cycle_pos++) {
case 1: {
rd.l = op_readpc();
} break;
case 2: {
last_cycle();
cpu_io();
regs.p &=~ rd.l;
if(regs.e)regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sep() {
switch(status.cycle_pos++) {
case 1: {
rd.l = op_readpc();
} break;
case 2: {
last_cycle();
cpu_io();
regs.p |= rd.l;
if(regs.e)regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_tax() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
if(regs.p.x) {
regs.x.l = regs.a.l;
regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
} else {
regs.x.w = regs.a.w;
regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_tay() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
if(regs.p.x) {
regs.y.l = regs.a.l;
regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
} else {
regs.y.w = regs.a.w;
regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
}
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_txa() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
if(regs.p.m) {
regs.a.l = regs.x.l;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.a.w = regs.x.w;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_txy() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
if(regs.p.x) {
regs.y.l = regs.x.l;
regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
} else {
regs.y.w = regs.x.w;
regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
}
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_tya() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
if(regs.p.m) {
regs.a.l = regs.y.l;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.a.w = regs.y.w;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_tyx() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
if(regs.p.x) {
regs.x.l = regs.y.l;
regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
} else {
regs.x.w = regs.y.w;
regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_tcd() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
regs.d.w = regs.a.w;
regs.p.n = !!(regs.d.w & 0x8000);
regs.p.z = (regs.d.w == 0);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_tcs() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
regs.s.w = regs.a.w;
if(regs.e)regs.s.h = 0x01;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_tdc() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
regs.a.w = regs.d.w;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_tsc() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
regs.a.w = regs.s.w;
if(regs.e) {
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_tsx() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
if(regs.p.x) {
regs.x.l = regs.s.l;
regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
} else {
regs.x.w = regs.s.w;
regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_txs() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
cpu_io();
if(regs.e) {
regs.s.l = regs.x.l;
} else {
regs.s.w = regs.x.w;
}
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_pha() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
if(regs.p.m)status.cycle_pos++;
} break;
case 2: {
op_writestack(regs.a.h);
} break;
case 3: {
last_cycle();
op_writestack(regs.a.l);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_phx() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
if(regs.p.x)status.cycle_pos++;
} break;
case 2: {
op_writestack(regs.x.h);
} break;
case 3: {
last_cycle();
op_writestack(regs.x.l);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_phy() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
if(regs.p.x)status.cycle_pos++;
} break;
case 2: {
op_writestack(regs.y.h);
} break;
case 3: {
last_cycle();
op_writestack(regs.y.l);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_phd() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
if(0)status.cycle_pos++;
} break;
case 2: {
op_writestack(regs. d.h);
} break;
case 3: {
last_cycle();
op_writestack(regs. d.l);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_phb() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
} break;
case 2: {
last_cycle();
op_writestack(regs.db);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_phk() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
} break;
case 2: {
last_cycle();
op_writestack(regs.pc.b);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_php() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
} break;
case 2: {
last_cycle();
op_writestack(regs.p);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_pla() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
} break;
case 2: {
cpu_io();
} break;
case 3: {
if(regs.p.m)last_cycle();
regs.a.l = op_readstack();
if(regs.p.m) {
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
status.cycle_pos = 0;
}
} break;
case 4: {
last_cycle();
regs.a.h = op_readstack();
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_plx() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
} break;
case 2: {
cpu_io();
} break;
case 3: {
if(regs.p.x)last_cycle();
regs.x.l = op_readstack();
if(regs.p.x) {
regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
status.cycle_pos = 0;
}
} break;
case 4: {
last_cycle();
regs.x.h = op_readstack();
regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_ply() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
} break;
case 2: {
cpu_io();
} break;
case 3: {
if(regs.p.x)last_cycle();
regs.y.l = op_readstack();
if(regs.p.x) {
regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
status.cycle_pos = 0;
}
} break;
case 4: {
last_cycle();
regs.y.h = op_readstack();
regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_pld() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
} break;
case 2: {
cpu_io();
} break;
case 3: {
if(0)last_cycle();
regs. d.l = op_readstack();
if(0) {
regs.p.n = !!(regs. d.l & 0x80);
regs.p.z = (regs. d.l == 0);
status.cycle_pos = 0;
}
} break;
case 4: {
last_cycle();
regs. d.h = op_readstack();
regs.p.n = !!(regs. d.w & 0x8000);
regs.p.z = (regs. d.w == 0);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_plb() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
} break;
case 2: {
cpu_io();
} break;
case 3: {
last_cycle();
regs.db = op_readstack();
regs.p.n = !!(regs.db & 0x80);
regs.p.z = (regs.db == 0);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_plp() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
} break;
case 2: {
cpu_io();
} break;
case 3: {
last_cycle();
regs.p = op_readstack();
if(regs.e)regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_pea() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_readpc();
} break;
case 3: {
op_writestack(aa.h);
} break;
case 4: {
last_cycle();
op_writestack(aa.l);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_pei() {
switch(status.cycle_pos++) {
case 1: {
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
aa.l = op_readdp(dp);
} break;
case 4: {
aa.h = op_readdp(dp + 1);
} break;
case 5: {
op_writestack(aa.h);
} break;
case 6: {
last_cycle();
op_writestack(aa.l);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_per() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
rd.w = regs.pc.d + (int16)aa.w;
} break;
case 4: {
op_writestack(rd.h);
} break;
case 5: {
last_cycle();
op_writestack(rd.l);
status.cycle_pos = 0;
} break;
}
}

160
src/cpu/bcpu/core/op_pc.b Normal file
View File

@@ -0,0 +1,160 @@
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:cpu_c6(aa.w);
3:last_cycle();
cpu_io();
}
bra(0x80) {
1:rd.l = op_readpc();
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
2:cpu_c6(aa.w);
3:last_cycle();
cpu_io();
}
brl(0x82) {
1:rd.l = op_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_readpc();
2:last_cycle();
rd.h = op_readpc();
regs.pc.w = rd.w;
}
jmp_long(0x5c) {
1:rd.l = op_readpc();
2:rd.h = op_readpc();
3:last_cycle();
rd.b = op_readpc();
regs.pc.d = rd.d & 0xffffff;
}
jmp_iaddr(0x6c) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:rd.l = op_readaddr(aa.w);
4:last_cycle();
rd.h = op_readaddr(aa.w + 1);
regs.pc.w = rd.w;
}
jmp_iaddrx(0x7c) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_io();
4:rd.l = op_readpbr(aa.w + regs.x.w);
5:last_cycle();
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
}
jmp_iladdr(0xdc) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:rd.l = op_readaddr(aa.w);
4:rd.h = op_readaddr(aa.w + 1);
5:last_cycle();
rd.b = op_readaddr(aa.w + 2);
regs.pc.d = rd.d & 0xffffff;
}
jsr_addr(0x20) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_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:cpu_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 = aa.d & 0xffffff;
}
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:cpu_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:cpu_io();
2:cpu_io();
3:regs.p = op_readstack();
if(regs.e)regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
4:rd.l = op_readstack();
5:if(regs.e)last_cycle();
rd.h = op_readstack();
if(regs.e) {
regs.pc.w = rd.w;
end;
}
6:last_cycle();
rd.b = op_readstack();
regs.pc.d = rd.d & 0xffffff;
}
rts(0x60) {
1:cpu_io();
2:cpu_io();
3:rd.l = op_readstack();
4:rd.h = op_readstack();
5:last_cycle();
cpu_io();
regs.pc.w = rd.w;
regs.pc.w++;
}
rtl(0x6b) {
1:cpu_io();
2:cpu_io();
3:rd.l = op_readstack();
4:rd.h = op_readstack();
5:last_cycle();
rd.b = op_readstack();
regs.pc.d = rd.d & 0xffffff;
regs.pc.w++;
}

483
src/cpu/bcpu/core/op_pc.cpp Normal file
View File

@@ -0,0 +1,483 @@
void bCPU::op_bcc() {
switch(status.cycle_pos++) {
case 1: {
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 {
status.cycle_pos = 0;
}
} break;
case 2: {
cpu_c6(aa.w);
} break;
case 3: {
last_cycle();
cpu_io();
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_bcs() {
switch(status.cycle_pos++) {
case 1: {
if(!regs.p.c)last_cycle();
rd.l = op_readpc();
if(regs.p.c) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
status.cycle_pos = 0;
}
} break;
case 2: {
cpu_c6(aa.w);
} break;
case 3: {
last_cycle();
cpu_io();
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_bne() {
switch(status.cycle_pos++) {
case 1: {
if(!!regs.p.z)last_cycle();
rd.l = op_readpc();
if(!regs.p.z) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
status.cycle_pos = 0;
}
} break;
case 2: {
cpu_c6(aa.w);
} break;
case 3: {
last_cycle();
cpu_io();
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_beq() {
switch(status.cycle_pos++) {
case 1: {
if(!regs.p.z)last_cycle();
rd.l = op_readpc();
if(regs.p.z) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
status.cycle_pos = 0;
}
} break;
case 2: {
cpu_c6(aa.w);
} break;
case 3: {
last_cycle();
cpu_io();
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_bpl() {
switch(status.cycle_pos++) {
case 1: {
if(!!regs.p.n)last_cycle();
rd.l = op_readpc();
if(!regs.p.n) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
status.cycle_pos = 0;
}
} break;
case 2: {
cpu_c6(aa.w);
} break;
case 3: {
last_cycle();
cpu_io();
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_bmi() {
switch(status.cycle_pos++) {
case 1: {
if(!regs.p.n)last_cycle();
rd.l = op_readpc();
if(regs.p.n) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
status.cycle_pos = 0;
}
} break;
case 2: {
cpu_c6(aa.w);
} break;
case 3: {
last_cycle();
cpu_io();
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_bvc() {
switch(status.cycle_pos++) {
case 1: {
if(!!regs.p.v)last_cycle();
rd.l = op_readpc();
if(!regs.p.v) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
status.cycle_pos = 0;
}
} break;
case 2: {
cpu_c6(aa.w);
} break;
case 3: {
last_cycle();
cpu_io();
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_bvs() {
switch(status.cycle_pos++) {
case 1: {
if(!regs.p.v)last_cycle();
rd.l = op_readpc();
if(regs.p.v) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
status.cycle_pos = 0;
}
} break;
case 2: {
cpu_c6(aa.w);
} break;
case 3: {
last_cycle();
cpu_io();
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_bra() {
switch(status.cycle_pos++) {
case 1: {
rd.l = op_readpc();
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} break;
case 2: {
cpu_c6(aa.w);
} break;
case 3: {
last_cycle();
cpu_io();
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_brl() {
switch(status.cycle_pos++) {
case 1: {
rd.l = op_readpc();
} break;
case 2: {
rd.h = op_readpc();
} break;
case 3: {
last_cycle();
cpu_io();
regs.pc.w = regs.pc.d + (int16)rd.w;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_jmp_addr() {
switch(status.cycle_pos++) {
case 1: {
rd.l = op_readpc();
} break;
case 2: {
last_cycle();
rd.h = op_readpc();
regs.pc.w = rd.w;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_jmp_long() {
switch(status.cycle_pos++) {
case 1: {
rd.l = op_readpc();
} break;
case 2: {
rd.h = op_readpc();
} break;
case 3: {
last_cycle();
rd.b = op_readpc();
regs.pc.d = rd.d & 0xffffff;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_jmp_iaddr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_readaddr(aa.w);
} break;
case 4: {
last_cycle();
rd.h = op_readaddr(aa.w + 1);
regs.pc.w = rd.w;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_jmp_iaddrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
} break;
case 4: {
rd.l = op_readpbr(aa.w + regs.x.w);
} break;
case 5: {
last_cycle();
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_jmp_iladdr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_readaddr(aa.w);
} break;
case 4: {
rd.h = op_readaddr(aa.w + 1);
} break;
case 5: {
last_cycle();
rd.b = op_readaddr(aa.w + 2);
regs.pc.d = rd.d & 0xffffff;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_jsr_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
} break;
case 4: {
regs.pc.w--;
op_writestack(regs.pc.h);
} break;
case 5: {
last_cycle();
op_writestack(regs.pc.l);
regs.pc.w = aa.w;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_jsr_long() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_readpc();
} break;
case 3: {
op_writestack(regs.pc.b);
} break;
case 4: {
cpu_io();
} break;
case 5: {
aa.b = op_readpc();
} break;
case 6: {
regs.pc.w--;
op_writestack(regs.pc.h);
} break;
case 7: {
last_cycle();
op_writestack(regs.pc.l);
regs.pc.d = aa.d & 0xffffff;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_jsr_iaddrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_readpc();
} break;
case 2: {
op_writestack(regs.pc.h);
} break;
case 3: {
op_writestack(regs.pc.l);
} break;
case 4: {
aa.h = op_readpc();
} break;
case 5: {
cpu_io();
} break;
case 6: {
rd.l = op_readpbr(aa.w + regs.x.w);
} break;
case 7: {
last_cycle();
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_rti() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
} break;
case 2: {
cpu_io();
} break;
case 3: {
regs.p = op_readstack();
if(regs.e)regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
} break;
case 4: {
rd.l = op_readstack();
} break;
case 5: {
if(regs.e)last_cycle();
rd.h = op_readstack();
if(regs.e) {
regs.pc.w = rd.w;
status.cycle_pos = 0;
}
} break;
case 6: {
last_cycle();
rd.b = op_readstack();
regs.pc.d = rd.d & 0xffffff;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_rts() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
} break;
case 2: {
cpu_io();
} break;
case 3: {
rd.l = op_readstack();
} break;
case 4: {
rd.h = op_readstack();
} break;
case 5: {
last_cycle();
cpu_io();
regs.pc.w = rd.w;
regs.pc.w++;
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_rtl() {
switch(status.cycle_pos++) {
case 1: {
cpu_io();
} break;
case 2: {
cpu_io();
} break;
case 3: {
rd.l = op_readstack();
} break;
case 4: {
rd.h = op_readstack();
} break;
case 5: {
last_cycle();
rd.b = op_readstack();
regs.pc.d = rd.d & 0xffffff;
regs.pc.w++;
status.cycle_pos = 0;
} break;
}
}

317
src/cpu/bcpu/core/op_read.b Normal file
View File

@@ -0,0 +1,317 @@
adc_const(0x69, adc, regs.p.m),
and_const(0x29, and, regs.p.m),
cmp_const(0xc9, cmp, regs.p.m),
cpx_const(0xe0, cpx, regs.p.x),
cpy_const(0xc0, cpy, regs.p.x),
eor_const(0x49, eor, regs.p.m),
lda_const(0xa9, lda, regs.p.m),
ldx_const(0xa2, ldx, regs.p.x),
ldy_const(0xa0, ldy, regs.p.x),
ora_const(0x09, ora, regs.p.m),
sbc_const(0xe9, sbc, regs.p.m) {
1:if($2)last_cycle();
rd.l = op_readpc();
if($2) { op_$1_b(); end; }
2:last_cycle();
rd.h = op_readpc();
op_$1_w();
}
adc_addr(0x6d, adc, regs.p.m),
and_addr(0x2d, and, regs.p.m),
bit_addr(0x2c, bit, regs.p.m),
cmp_addr(0xcd, cmp, regs.p.m),
cpx_addr(0xec, cpx, regs.p.x),
cpy_addr(0xcc, cpy, regs.p.x),
eor_addr(0x4d, eor, regs.p.m),
lda_addr(0xad, lda, regs.p.m),
ldx_addr(0xae, ldx, regs.p.x),
ldy_addr(0xac, ldy, regs.p.x),
ora_addr(0x0d, ora, regs.p.m),
sbc_addr(0xed, sbc, regs.p.m) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:if($2)last_cycle();
rd.l = op_readdbr(aa.w);
if($2) { op_$1_b(); end; }
4:last_cycle();
rd.h = op_readdbr(aa.w + 1);
op_$1_w();
}
adc_addrx(0x7d, adc, regs.p.m),
and_addrx(0x3d, and, regs.p.m),
bit_addrx(0x3c, bit, regs.p.m),
cmp_addrx(0xdd, cmp, regs.p.m),
eor_addrx(0x5d, eor, regs.p.m),
lda_addrx(0xbd, lda, regs.p.m),
ldy_addrx(0xbc, ldy, regs.p.x),
ora_addrx(0x1d, ora, regs.p.m),
sbc_addrx(0xfd, sbc, regs.p.m) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_c4(aa.w, aa.w + regs.x.w);
4:if($2)last_cycle();
rd.l = op_readdbr(aa.w + regs.x.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_$1_w();
}
adc_addry(0x79, adc, regs.p.m),
and_addry(0x39, and, regs.p.m),
cmp_addry(0xd9, cmp, regs.p.m),
eor_addry(0x59, eor, regs.p.m),
lda_addry(0xb9, lda, regs.p.m),
ldx_addry(0xbe, ldx, regs.p.x),
ora_addry(0x19, ora, regs.p.m),
sbc_addry(0xf9, sbc, regs.p.m) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_c4(aa.w, aa.w + regs.y.w);
4:if($2)last_cycle();
rd.l = op_readdbr(aa.w + regs.y.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_readdbr(aa.w + regs.y.w + 1);
op_$1_w();
}
adc_long(0x6f, adc, regs.p.m),
and_long(0x2f, and, regs.p.m),
cmp_long(0xcf, cmp, regs.p.m),
eor_long(0x4f, eor, regs.p.m),
lda_long(0xaf, lda, regs.p.m),
ora_long(0x0f, ora, regs.p.m),
sbc_long(0xef, sbc, regs.p.m) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if($2)last_cycle();
rd.l = op_readlong(aa.d);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_readlong(aa.d + 1);
op_$1_w();
}
adc_longx(0x7f, adc, regs.p.m),
and_longx(0x3f, and, regs.p.m),
cmp_longx(0xdf, cmp, regs.p.m),
eor_longx(0x5f, eor, regs.p.m),
lda_longx(0xbf, lda, regs.p.m),
ora_longx(0x1f, ora, regs.p.m),
sbc_longx(0xff, sbc, regs.p.m) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if($2)last_cycle();
rd.l = op_readlong(aa.d + regs.x.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_readlong(aa.d + regs.x.w + 1);
op_$1_w();
}
adc_dp(0x65, adc, regs.p.m),
and_dp(0x25, and, regs.p.m),
bit_dp(0x24, bit, regs.p.m),
cmp_dp(0xc5, cmp, regs.p.m),
cpx_dp(0xe4, cpx, regs.p.x),
cpy_dp(0xc4, cpy, regs.p.x),
eor_dp(0x45, eor, regs.p.m),
lda_dp(0xa5, lda, regs.p.m),
ldx_dp(0xa6, ldx, regs.p.x),
ldy_dp(0xa4, ldy, regs.p.x),
ora_dp(0x05, ora, regs.p.m),
sbc_dp(0xe5, sbc, regs.p.m) {
1:dp = op_readpc();
2:cpu_c2();
3:if($2)last_cycle();
rd.l = op_readdp(dp);
if($2) { op_$1_b(); end; }
4:last_cycle();
rd.h = op_readdp(dp + 1);
op_$1_w();
}
adc_dpx(0x75, adc, regs.p.m),
and_dpx(0x35, and, regs.p.m),
bit_dpx(0x34, bit, regs.p.m),
cmp_dpx(0xd5, cmp, regs.p.m),
eor_dpx(0x55, eor, regs.p.m),
lda_dpx(0xb5, lda, regs.p.m),
ldy_dpx(0xb4, ldy, regs.p.x),
ora_dpx(0x15, ora, regs.p.m),
sbc_dpx(0xf5, sbc, regs.p.m) {
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
4:if($2)last_cycle();
rd.l = op_readdp(dp + regs.x.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_readdp(dp + regs.x.w + 1);
op_$1_w();
}
ldx_dpy(0xb6, ldx, regs.p.x) {
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
4:if($2)last_cycle();
rd.l = op_readdp(dp + regs.y.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_readdp(dp + regs.y.w + 1);
op_$1_w();
}
adc_idp(0x72, adc, regs.p.m),
and_idp(0x32, and, regs.p.m),
cmp_idp(0xd2, cmp, regs.p.m),
eor_idp(0x52, eor, regs.p.m),
lda_idp(0xb2, lda, regs.p.m),
ora_idp(0x12, ora, regs.p.m),
sbc_idp(0xf2, sbc, regs.p.m) {
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:if($2)last_cycle();
rd.l = op_readdbr(aa.w);
if($2) { op_$1_b(); end; }
6:last_cycle();
rd.h = op_readdbr(aa.w + 1);
op_$1_w();
}
adc_idpx(0x61, adc, regs.p.m),
and_idpx(0x21, and, regs.p.m),
cmp_idpx(0xc1, cmp, regs.p.m),
eor_idpx(0x41, eor, regs.p.m),
lda_idpx(0xa1, lda, regs.p.m),
ora_idpx(0x01, ora, regs.p.m),
sbc_idpx(0xe1, sbc, regs.p.m) {
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
4:aa.l = op_readdp(dp + regs.x.w);
5:aa.h = op_readdp(dp + regs.x.w + 1);
6:if($2)last_cycle();
rd.l = op_readdbr(aa.w);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_readdbr(aa.w + 1);
op_$1_w();
}
adc_idpy(0x71, adc, regs.p.m),
and_idpy(0x31, and, regs.p.m),
cmp_idpy(0xd1, cmp, regs.p.m),
eor_idpy(0x51, eor, regs.p.m),
lda_idpy(0xb1, lda, regs.p.m),
ora_idpy(0x11, ora, regs.p.m),
sbc_idpy(0xf1, sbc, regs.p.m) {
1:dp = op_readpc();
2:cpu_c2();
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_readdbr(aa.w + regs.y.w);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_readdbr(aa.w + regs.y.w + 1);
op_$1_w();
}
adc_ildp(0x67, adc, regs.p.m),
and_ildp(0x27, and, regs.p.m),
cmp_ildp(0xc7, cmp, regs.p.m),
eor_ildp(0x47, eor, regs.p.m),
lda_ildp(0xa7, lda, regs.p.m),
ora_ildp(0x07, ora, regs.p.m),
sbc_ildp(0xe7, sbc, regs.p.m) {
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if($2)last_cycle();
rd.l = op_readlong(aa.d);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_readlong(aa.d + 1);
op_$1_w();
}
adc_ildpy(0x77, adc, regs.p.m),
and_ildpy(0x37, and, regs.p.m),
cmp_ildpy(0xd7, cmp, regs.p.m),
eor_ildpy(0x57, eor, regs.p.m),
lda_ildpy(0xb7, lda, regs.p.m),
ora_ildpy(0x17, ora, regs.p.m),
sbc_ildpy(0xf7, sbc, regs.p.m) {
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if($2)last_cycle();
rd.l = op_readlong(aa.d + regs.y.w);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_readlong(aa.d + regs.y.w + 1);
op_$1_w();
}
adc_sr(0x63, adc, regs.p.m),
and_sr(0x23, and, regs.p.m),
cmp_sr(0xc3, cmp, regs.p.m),
eor_sr(0x43, eor, regs.p.m),
lda_sr(0xa3, lda, regs.p.m),
ora_sr(0x03, ora, regs.p.m),
sbc_sr(0xe3, sbc, regs.p.m) {
1:sp = op_readpc();
2:cpu_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:cpu_io();
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_readdbr(aa.w + regs.y.w);
if(regs.p.m) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_readdbr(aa.w + regs.y.w + 1);
op_$1_w();
}
bit_const(0x89) {
1:if(regs.p.m)last_cycle();
rd.l = op_readpc();
if(regs.p.m) {
regs.p.z = ((rd.l & regs.a.l) == 0);
end;
}
2:last_cycle();
rd.h = op_readpc();
regs.p.z = ((rd.w & regs.a.w) == 0);
}

File diff suppressed because it is too large Load Diff

185
src/cpu/bcpu/core/op_rmw.b Normal file
View File

@@ -0,0 +1,185 @@
inc(0x1a, regs.p.m, a),
inx(0xe8, regs.p.x, x),
iny(0xc8, regs.p.x, y) {
1:last_cycle();
cpu_io();
if($1) {
regs.$2.l++;
regs.p.n = !!(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0);
} else {
regs.$2.w++;
regs.p.n = !!(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0);
}
}
dec(0x3a, regs.p.m, a),
dex(0xca, regs.p.x, x),
dey(0x88, regs.p.x, y) {
1:last_cycle();
cpu_io();
if($1) {
regs.$2.l--;
regs.p.n = !!(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0);
} else {
regs.$2.w--;
regs.p.n = !!(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0);
}
}
asl(0x0a) {
1:last_cycle();
cpu_io();
if(regs.p.m) {
regs.p.c = !!(regs.a.l & 0x80);
regs.a.l <<= 1;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = !!(regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
lsr(0x4a) {
1:last_cycle();
cpu_io();
if(regs.p.m) {
regs.p.c = regs.a.l & 1;
regs.a.l >>= 1;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = regs.a.w & 1;
regs.a.w >>= 1;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
rol(0x2a) {
1:last_cycle();
cpu_io();
uint16 c = regs.p.c;
if(regs.p.m) {
regs.p.c = !!(regs.a.l & 0x80);
regs.a.l <<= 1;
regs.a.l |= c;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = !!(regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.a.w |= c;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
ror(0x6a) {
1:last_cycle();
cpu_io();
uint16 c;
if(regs.p.m) {
c = (regs.p.c)?0x80:0;
regs.p.c = regs.a.l & 1;
regs.a.l >>= 1;
regs.a.l |= c;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
c = (regs.p.c)?0x8000:0;
regs.p.c = regs.a.w & 1;
regs.a.w >>= 1;
regs.a.w |= c;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
inc_addr(0xee, inc),
dec_addr(0xce, dec),
asl_addr(0x0e, asl),
lsr_addr(0x4e, lsr),
rol_addr(0x2e, rol),
ror_addr(0x6e, ror),
trb_addr(0x1c, trb),
tsb_addr(0x0c, tsb) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:rd.l = op_readdbr(aa.w);
if(regs.p.m)skip;
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_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:cpu_io();
4:rd.l = op_readdbr(aa.w + regs.x.w);
if(regs.p.m)skip;
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_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:cpu_c2();
3:rd.l = op_readdp(dp);
if(regs.p.m)skip;
4:rd.h = op_readdp(dp + 1);
5:cpu_io();
if(regs.p.m) { op_$1_b(); skip; }
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:cpu_c2();
3:cpu_io();
4:rd.l = op_readdp(dp + regs.x.w);
if(regs.p.m)skip;
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_writedp(dp + regs.x.w + 1, rd.h);
8:last_cycle();
op_writedp(dp + regs.x.w, rd.l);
}

1110
src/cpu/bcpu/core/op_rmw.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,181 @@
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_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.p.m, regs.a.w),
stz_addrx(0x9e, regs.p.m, 0x0000) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_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:cpu_io();
4:if(regs.p.m)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)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.p.m)last_cycle();
op_writelong(aa.d, regs.a.l);
if(regs.p.m)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.p.m)last_cycle();
op_writelong(aa.d + regs.x.w, regs.a.l);
if(regs.p.m)end;
5:last_cycle();
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_readpc();
2:cpu_c2();
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.p.m, regs.a.w),
sty_dpx(0x94, regs.p.x, regs.y.w),
stz_dpx(0x74, regs.p.m, 0x0000) {
1:dp = op_readpc();
2:cpu_c2();
3:cpu_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:cpu_c2();
3:cpu_io();
4:if(regs.p.x)last_cycle();
op_writedp(dp + regs.y.w, regs.x.l);
if(regs.p.x)end;
5:last_cycle();
op_writedp(dp + regs.y.w + 1, regs.x.h);
}
sta_idp(0x92) {
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:if(regs.p.m)last_cycle();
op_writedbr(aa.w, regs.a.l);
if(regs.p.m)end;
6:last_cycle();
op_writedbr(aa.w + 1, regs.a.h);
}
sta_ildp(0x87) {
1:dp = op_readpc();
2:cpu_c2();
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_writelong(aa.d, regs.a.l);
if(regs.p.m)end;
7:last_cycle();
op_writelong(aa.d + 1, regs.a.h);
}
sta_idpx(0x81) {
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
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_writedbr(aa.w, regs.a.l);
if(regs.p.m)end;
7:last_cycle();
op_writedbr(aa.w + 1, regs.a.h);
}
sta_idpy(0x91) {
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:cpu_io();
6:if(regs.p.m)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)end;
7:last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}
sta_ildpy(0x97) {
1:dp = op_readpc();
2:cpu_c2();
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_writelong(aa.d + regs.y.w, regs.a.l);
if(regs.p.m)end;
7:last_cycle();
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
}
sta_sr(0x83) {
1:sp = op_readpc();
2:cpu_io();
3:if(regs.p.m)last_cycle();
op_writesp(sp, regs.a.l);
if(regs.p.m)end;
4:last_cycle();
op_writesp(sp + 1, regs.a.h);
}
sta_isry(0x93) {
1:sp = op_readpc();
2:cpu_io();
3:aa.l = op_readsp(sp);
4:aa.h = op_readsp(sp + 1);
5:cpu_io();
6:if(regs.p.m)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)end;
7:last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}

View File

@@ -0,0 +1,582 @@
void bCPU::op_sta_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_readpc();
} break;
case 3: {
if(regs.p.m)last_cycle();
op_writedbr(aa.w, regs.a.w);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_writedbr(aa.w + 1, regs.a.w >> 8);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_stx_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_readpc();
} break;
case 3: {
if(regs.p.x)last_cycle();
op_writedbr(aa.w, regs.x.w);
if(regs.p.x)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_writedbr(aa.w + 1, regs.x.w >> 8);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sty_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_readpc();
} break;
case 3: {
if(regs.p.x)last_cycle();
op_writedbr(aa.w, regs.y.w);
if(regs.p.x)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_writedbr(aa.w + 1, regs.y.w >> 8);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_stz_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_readpc();
} break;
case 3: {
if(regs.p.m)last_cycle();
op_writedbr(aa.w, 0x0000);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_writedbr(aa.w + 1, 0x0000 >> 8);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sta_addrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_readpc();
} break;
case 2: {
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_writedbr(aa.w + regs.x.w, regs.a.w);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_writedbr(aa.w + regs.x.w + 1, regs.a.w >> 8);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_stz_addrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_readpc();
} break;
case 2: {
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_writedbr(aa.w + regs.x.w, 0x0000);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_writedbr(aa.w + regs.x.w + 1, 0x0000 >> 8);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sta_addry() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_readpc();
} break;
case 2: {
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_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sta_long() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_readpc();
} break;
case 3: {
aa.b = op_readpc();
} break;
case 4: {
if(regs.p.m)last_cycle();
op_writelong(aa.d, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_writelong(aa.d + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sta_longx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_readpc();
} break;
case 3: {
aa.b = op_readpc();
} break;
case 4: {
if(regs.p.m)last_cycle();
op_writelong(aa.d + regs.x.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sta_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
if(regs.p.m)last_cycle();
op_writedp(dp, regs.a.w);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_writedp(dp + 1, regs.a.w >> 8);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_stx_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
if(regs.p.x)last_cycle();
op_writedp(dp, regs.x.w);
if(regs.p.x)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_writedp(dp + 1, regs.x.w >> 8);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sty_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
if(regs.p.x)last_cycle();
op_writedp(dp, regs.y.w);
if(regs.p.x)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_writedp(dp + 1, regs.y.w >> 8);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_stz_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
if(regs.p.m)last_cycle();
op_writedp(dp, 0x0000);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_writedp(dp + 1, 0x0000 >> 8);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sta_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
cpu_io();
} break;
case 4: {
if(regs.p.m)last_cycle();
op_writedp(dp + regs.x.w, regs.a.w);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_writedp(dp + regs.x.w + 1, regs.a.w >> 8);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sty_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
cpu_io();
} break;
case 4: {
if(regs.p.x)last_cycle();
op_writedp(dp + regs.x.w, regs.y.w);
if(regs.p.x)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_writedp(dp + regs.x.w + 1, regs.y.w >> 8);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_stz_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
cpu_io();
} break;
case 4: {
if(regs.p.m)last_cycle();
op_writedp(dp + regs.x.w, 0x0000);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_writedp(dp + regs.x.w + 1, 0x0000 >> 8);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_stx_dpy() {
switch(status.cycle_pos++) {
case 1: {
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
cpu_io();
} break;
case 4: {
if(regs.p.x)last_cycle();
op_writedp(dp + regs.y.w, regs.x.l);
if(regs.p.x)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_writedp(dp + regs.y.w + 1, regs.x.h);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sta_idp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
aa.l = op_readdp(dp);
} break;
case 4: {
aa.h = op_readdp(dp + 1);
} break;
case 5: {
if(regs.p.m)last_cycle();
op_writedbr(aa.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 6: {
last_cycle();
op_writedbr(aa.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sta_ildp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
aa.l = op_readdp(dp);
} break;
case 4: {
aa.h = op_readdp(dp + 1);
} break;
case 5: {
aa.b = op_readdp(dp + 2);
} break;
case 6: {
if(regs.p.m)last_cycle();
op_writelong(aa.d, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 7: {
last_cycle();
op_writelong(aa.d + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sta_idpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
cpu_io();
} break;
case 4: {
aa.l = op_readdp(dp + regs.x.w);
} break;
case 5: {
aa.h = op_readdp(dp + regs.x.w + 1);
} break;
case 6: {
if(regs.p.m)last_cycle();
op_writedbr(aa.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 7: {
last_cycle();
op_writedbr(aa.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sta_idpy() {
switch(status.cycle_pos++) {
case 1: {
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
aa.l = op_readdp(dp);
} break;
case 4: {
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_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 7: {
last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sta_ildpy() {
switch(status.cycle_pos++) {
case 1: {
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
aa.l = op_readdp(dp);
} break;
case 4: {
aa.h = op_readdp(dp + 1);
} break;
case 5: {
aa.b = op_readdp(dp + 2);
} break;
case 6: {
if(regs.p.m)last_cycle();
op_writelong(aa.d + regs.y.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 7: {
last_cycle();
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sta_sr() {
switch(status.cycle_pos++) {
case 1: {
sp = op_readpc();
} break;
case 2: {
cpu_io();
} break;
case 3: {
if(regs.p.m)last_cycle();
op_writesp(sp, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_writesp(sp + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
}
void bCPU::op_sta_isry() {
switch(status.cycle_pos++) {
case 1: {
sp = op_readpc();
} break;
case 2: {
cpu_io();
} break;
case 3: {
aa.l = op_readsp(sp);
} break;
case 4: {
aa.h = op_readsp(sp + 1);
} break;
case 5: {
cpu_io();
} break;
case 6: {
if(regs.p.m)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 7: {
last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
}

377
src/cpu/bcpu/core/opfn.cpp Normal file
View File

@@ -0,0 +1,377 @@
//op_read
inline void bCPU::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 = !!(r & 0x80);
regs.p.v = !!(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
regs.p.z = ((uint8)r == 0);
regs.a.l = r;
}
inline void bCPU::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 = !!(r & 0x8000);
regs.p.v = !!(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.a.w = r;
}
inline void bCPU::op_and_b() {
regs.a.l &= rd.l;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
inline void bCPU::op_and_w() {
regs.a.w &= rd.w;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
inline void bCPU::op_bit_b() {
regs.p.n = !!(rd.l & 0x80);
regs.p.v = !!(rd.l & 0x40);
regs.p.z = ((rd.l & regs.a.l) == 0);
}
inline void bCPU::op_bit_w() {
regs.p.n = !!(rd.w & 0x8000);
regs.p.v = !!(rd.w & 0x4000);
regs.p.z = ((rd.w & regs.a.w) == 0);
}
inline void bCPU::op_cmp_b() {
int32 r = regs.a.l - rd.l;
regs.p.n = !!(r & 0x80);
regs.p.z = ((uint8)r == 0);
regs.p.c = (r >= 0);
}
inline void bCPU::op_cmp_w() {
int32 r = regs.a.w - rd.w;
regs.p.n = !!(r & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.p.c = (r >= 0);
}
inline void bCPU::op_cpx_b() {
int32 r = regs.x.l - rd.l;
regs.p.n = !!(r & 0x80);
regs.p.z = ((uint8)r == 0);
regs.p.c = (r >= 0);
}
inline void bCPU::op_cpx_w() {
int32 r = regs.x.w - rd.w;
regs.p.n = !!(r & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.p.c = (r >= 0);
}
inline void bCPU::op_cpy_b() {
int32 r = regs.y.l - rd.l;
regs.p.n = !!(r & 0x80);
regs.p.z = ((uint8)r == 0);
regs.p.c = (r >= 0);
}
inline void bCPU::op_cpy_w() {
int32 r = regs.y.w - rd.w;
regs.p.n = !!(r & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.p.c = (r >= 0);
}
inline void bCPU::op_eor_b() {
regs.a.l ^= rd.l;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
inline void bCPU::op_eor_w() {
regs.a.w ^= rd.w;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
inline void bCPU::op_lda_b() {
regs.a.l = rd.l;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
inline void bCPU::op_lda_w() {
regs.a.w = rd.w;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
inline void bCPU::op_ldx_b() {
regs.x.l = rd.l;
regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
}
inline void bCPU::op_ldx_w() {
regs.x.w = rd.w;
regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
inline void bCPU::op_ldy_b() {
regs.y.l = rd.l;
regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
}
inline void bCPU::op_ldy_w() {
regs.y.w = rd.w;
regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
}
inline void bCPU::op_ora_b() {
regs.a.l |= rd.l;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
inline void bCPU::op_ora_w() {
regs.a.w |= rd.w;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
inline void bCPU::op_sbc_b() {
int32 r;
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 = !!(r & 0x80);
regs.p.v = !!((regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
regs.p.z = ((uint8)r == 0);
regs.a.l = r;
}
inline void bCPU::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 = !!(r & 0x8000);
regs.p.v = !!((regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.a.w = r;
}
//op_rmw
inline void bCPU::op_inc_b() {
rd.l++;
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void bCPU::op_inc_w() {
rd.w++;
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void bCPU::op_dec_b() {
rd.l--;
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void bCPU::op_dec_w() {
rd.w--;
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void bCPU::op_asl_b() {
regs.p.c = !!(rd.l & 0x80);
rd.l <<= 1;
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void bCPU::op_asl_w() {
regs.p.c = !!(rd.w & 0x8000);
rd.w <<= 1;
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void bCPU::op_lsr_b() {
regs.p.c = rd.l & 1;
rd.l >>= 1;
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void bCPU::op_lsr_w() {
regs.p.c = rd.w & 1;
rd.w >>= 1;
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void bCPU::op_rol_b() {
uint16 c = regs.p.c;
regs.p.c = !!(rd.l & 0x80);
rd.l <<= 1;
rd.l |= c;
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void bCPU::op_rol_w() {
uint16 c = regs.p.c;
regs.p.c = !!(rd.w & 0x8000);
rd.w <<= 1;
rd.w |= c;
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void bCPU::op_ror_b() {
uint16 c = (regs.p.c)?0x80:0;
regs.p.c = rd.l & 1;
rd.l >>= 1;
rd.l |= c;
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void bCPU::op_ror_w() {
uint16 c = (regs.p.c)?0x8000:0;
regs.p.c = rd.w & 1;
rd.w >>= 1;
rd.w |= c;
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void bCPU::op_trb_b() {
regs.p.z = ((rd.l & regs.a.l) == 0);
rd.l &= ~regs.a.l;
}
inline void bCPU::op_trb_w() {
regs.p.z = ((rd.w & regs.a.w) == 0);
rd.w &= ~regs.a.w;
}
inline void bCPU::op_tsb_b() {
regs.p.z = ((rd.l & regs.a.l) == 0);
rd.l |= regs.a.l;
}
inline void bCPU::op_tsb_w() {
regs.p.z = ((rd.w & regs.a.w) == 0);
rd.w |= regs.a.w;
}

View File

@@ -0,0 +1,256 @@
optbl[0x69] = &bCPU::op_adc_const;
optbl[0x29] = &bCPU::op_and_const;
optbl[0xc9] = &bCPU::op_cmp_const;
optbl[0xe0] = &bCPU::op_cpx_const;
optbl[0xc0] = &bCPU::op_cpy_const;
optbl[0x49] = &bCPU::op_eor_const;
optbl[0xa9] = &bCPU::op_lda_const;
optbl[0xa2] = &bCPU::op_ldx_const;
optbl[0xa0] = &bCPU::op_ldy_const;
optbl[0x09] = &bCPU::op_ora_const;
optbl[0xe9] = &bCPU::op_sbc_const;
optbl[0x6d] = &bCPU::op_adc_addr;
optbl[0x2d] = &bCPU::op_and_addr;
optbl[0x2c] = &bCPU::op_bit_addr;
optbl[0xcd] = &bCPU::op_cmp_addr;
optbl[0xec] = &bCPU::op_cpx_addr;
optbl[0xcc] = &bCPU::op_cpy_addr;
optbl[0x4d] = &bCPU::op_eor_addr;
optbl[0xad] = &bCPU::op_lda_addr;
optbl[0xae] = &bCPU::op_ldx_addr;
optbl[0xac] = &bCPU::op_ldy_addr;
optbl[0x0d] = &bCPU::op_ora_addr;
optbl[0xed] = &bCPU::op_sbc_addr;
optbl[0x7d] = &bCPU::op_adc_addrx;
optbl[0x3d] = &bCPU::op_and_addrx;
optbl[0x3c] = &bCPU::op_bit_addrx;
optbl[0xdd] = &bCPU::op_cmp_addrx;
optbl[0x5d] = &bCPU::op_eor_addrx;
optbl[0xbd] = &bCPU::op_lda_addrx;
optbl[0xbc] = &bCPU::op_ldy_addrx;
optbl[0x1d] = &bCPU::op_ora_addrx;
optbl[0xfd] = &bCPU::op_sbc_addrx;
optbl[0x79] = &bCPU::op_adc_addry;
optbl[0x39] = &bCPU::op_and_addry;
optbl[0xd9] = &bCPU::op_cmp_addry;
optbl[0x59] = &bCPU::op_eor_addry;
optbl[0xb9] = &bCPU::op_lda_addry;
optbl[0xbe] = &bCPU::op_ldx_addry;
optbl[0x19] = &bCPU::op_ora_addry;
optbl[0xf9] = &bCPU::op_sbc_addry;
optbl[0x6f] = &bCPU::op_adc_long;
optbl[0x2f] = &bCPU::op_and_long;
optbl[0xcf] = &bCPU::op_cmp_long;
optbl[0x4f] = &bCPU::op_eor_long;
optbl[0xaf] = &bCPU::op_lda_long;
optbl[0x0f] = &bCPU::op_ora_long;
optbl[0xef] = &bCPU::op_sbc_long;
optbl[0x7f] = &bCPU::op_adc_longx;
optbl[0x3f] = &bCPU::op_and_longx;
optbl[0xdf] = &bCPU::op_cmp_longx;
optbl[0x5f] = &bCPU::op_eor_longx;
optbl[0xbf] = &bCPU::op_lda_longx;
optbl[0x1f] = &bCPU::op_ora_longx;
optbl[0xff] = &bCPU::op_sbc_longx;
optbl[0x65] = &bCPU::op_adc_dp;
optbl[0x25] = &bCPU::op_and_dp;
optbl[0x24] = &bCPU::op_bit_dp;
optbl[0xc5] = &bCPU::op_cmp_dp;
optbl[0xe4] = &bCPU::op_cpx_dp;
optbl[0xc4] = &bCPU::op_cpy_dp;
optbl[0x45] = &bCPU::op_eor_dp;
optbl[0xa5] = &bCPU::op_lda_dp;
optbl[0xa6] = &bCPU::op_ldx_dp;
optbl[0xa4] = &bCPU::op_ldy_dp;
optbl[0x05] = &bCPU::op_ora_dp;
optbl[0xe5] = &bCPU::op_sbc_dp;
optbl[0x75] = &bCPU::op_adc_dpx;
optbl[0x35] = &bCPU::op_and_dpx;
optbl[0x34] = &bCPU::op_bit_dpx;
optbl[0xd5] = &bCPU::op_cmp_dpx;
optbl[0x55] = &bCPU::op_eor_dpx;
optbl[0xb5] = &bCPU::op_lda_dpx;
optbl[0xb4] = &bCPU::op_ldy_dpx;
optbl[0x15] = &bCPU::op_ora_dpx;
optbl[0xf5] = &bCPU::op_sbc_dpx;
optbl[0xb6] = &bCPU::op_ldx_dpy;
optbl[0x72] = &bCPU::op_adc_idp;
optbl[0x32] = &bCPU::op_and_idp;
optbl[0xd2] = &bCPU::op_cmp_idp;
optbl[0x52] = &bCPU::op_eor_idp;
optbl[0xb2] = &bCPU::op_lda_idp;
optbl[0x12] = &bCPU::op_ora_idp;
optbl[0xf2] = &bCPU::op_sbc_idp;
optbl[0x61] = &bCPU::op_adc_idpx;
optbl[0x21] = &bCPU::op_and_idpx;
optbl[0xc1] = &bCPU::op_cmp_idpx;
optbl[0x41] = &bCPU::op_eor_idpx;
optbl[0xa1] = &bCPU::op_lda_idpx;
optbl[0x01] = &bCPU::op_ora_idpx;
optbl[0xe1] = &bCPU::op_sbc_idpx;
optbl[0x71] = &bCPU::op_adc_idpy;
optbl[0x31] = &bCPU::op_and_idpy;
optbl[0xd1] = &bCPU::op_cmp_idpy;
optbl[0x51] = &bCPU::op_eor_idpy;
optbl[0xb1] = &bCPU::op_lda_idpy;
optbl[0x11] = &bCPU::op_ora_idpy;
optbl[0xf1] = &bCPU::op_sbc_idpy;
optbl[0x67] = &bCPU::op_adc_ildp;
optbl[0x27] = &bCPU::op_and_ildp;
optbl[0xc7] = &bCPU::op_cmp_ildp;
optbl[0x47] = &bCPU::op_eor_ildp;
optbl[0xa7] = &bCPU::op_lda_ildp;
optbl[0x07] = &bCPU::op_ora_ildp;
optbl[0xe7] = &bCPU::op_sbc_ildp;
optbl[0x77] = &bCPU::op_adc_ildpy;
optbl[0x37] = &bCPU::op_and_ildpy;
optbl[0xd7] = &bCPU::op_cmp_ildpy;
optbl[0x57] = &bCPU::op_eor_ildpy;
optbl[0xb7] = &bCPU::op_lda_ildpy;
optbl[0x17] = &bCPU::op_ora_ildpy;
optbl[0xf7] = &bCPU::op_sbc_ildpy;
optbl[0x63] = &bCPU::op_adc_sr;
optbl[0x23] = &bCPU::op_and_sr;
optbl[0xc3] = &bCPU::op_cmp_sr;
optbl[0x43] = &bCPU::op_eor_sr;
optbl[0xa3] = &bCPU::op_lda_sr;
optbl[0x03] = &bCPU::op_ora_sr;
optbl[0xe3] = &bCPU::op_sbc_sr;
optbl[0x73] = &bCPU::op_adc_isry;
optbl[0x33] = &bCPU::op_and_isry;
optbl[0xd3] = &bCPU::op_cmp_isry;
optbl[0x53] = &bCPU::op_eor_isry;
optbl[0xb3] = &bCPU::op_lda_isry;
optbl[0x13] = &bCPU::op_ora_isry;
optbl[0xf3] = &bCPU::op_sbc_isry;
optbl[0x89] = &bCPU::op_bit_const;
optbl[0x1a] = &bCPU::op_inc;
optbl[0xe8] = &bCPU::op_inx;
optbl[0xc8] = &bCPU::op_iny;
optbl[0x3a] = &bCPU::op_dec;
optbl[0xca] = &bCPU::op_dex;
optbl[0x88] = &bCPU::op_dey;
optbl[0x0a] = &bCPU::op_asl;
optbl[0x4a] = &bCPU::op_lsr;
optbl[0x2a] = &bCPU::op_rol;
optbl[0x6a] = &bCPU::op_ror;
optbl[0xee] = &bCPU::op_inc_addr;
optbl[0xce] = &bCPU::op_dec_addr;
optbl[0x0e] = &bCPU::op_asl_addr;
optbl[0x4e] = &bCPU::op_lsr_addr;
optbl[0x2e] = &bCPU::op_rol_addr;
optbl[0x6e] = &bCPU::op_ror_addr;
optbl[0x1c] = &bCPU::op_trb_addr;
optbl[0x0c] = &bCPU::op_tsb_addr;
optbl[0xfe] = &bCPU::op_inc_addrx;
optbl[0xde] = &bCPU::op_dec_addrx;
optbl[0x1e] = &bCPU::op_asl_addrx;
optbl[0x5e] = &bCPU::op_lsr_addrx;
optbl[0x3e] = &bCPU::op_rol_addrx;
optbl[0x7e] = &bCPU::op_ror_addrx;
optbl[0xe6] = &bCPU::op_inc_dp;
optbl[0xc6] = &bCPU::op_dec_dp;
optbl[0x06] = &bCPU::op_asl_dp;
optbl[0x46] = &bCPU::op_lsr_dp;
optbl[0x26] = &bCPU::op_rol_dp;
optbl[0x66] = &bCPU::op_ror_dp;
optbl[0x14] = &bCPU::op_trb_dp;
optbl[0x04] = &bCPU::op_tsb_dp;
optbl[0xf6] = &bCPU::op_inc_dpx;
optbl[0xd6] = &bCPU::op_dec_dpx;
optbl[0x16] = &bCPU::op_asl_dpx;
optbl[0x56] = &bCPU::op_lsr_dpx;
optbl[0x36] = &bCPU::op_rol_dpx;
optbl[0x76] = &bCPU::op_ror_dpx;
optbl[0x8d] = &bCPU::op_sta_addr;
optbl[0x8e] = &bCPU::op_stx_addr;
optbl[0x8c] = &bCPU::op_sty_addr;
optbl[0x9c] = &bCPU::op_stz_addr;
optbl[0x9d] = &bCPU::op_sta_addrx;
optbl[0x9e] = &bCPU::op_stz_addrx;
optbl[0x99] = &bCPU::op_sta_addry;
optbl[0x8f] = &bCPU::op_sta_long;
optbl[0x9f] = &bCPU::op_sta_longx;
optbl[0x85] = &bCPU::op_sta_dp;
optbl[0x86] = &bCPU::op_stx_dp;
optbl[0x84] = &bCPU::op_sty_dp;
optbl[0x64] = &bCPU::op_stz_dp;
optbl[0x95] = &bCPU::op_sta_dpx;
optbl[0x94] = &bCPU::op_sty_dpx;
optbl[0x74] = &bCPU::op_stz_dpx;
optbl[0x96] = &bCPU::op_stx_dpy;
optbl[0x92] = &bCPU::op_sta_idp;
optbl[0x87] = &bCPU::op_sta_ildp;
optbl[0x81] = &bCPU::op_sta_idpx;
optbl[0x91] = &bCPU::op_sta_idpy;
optbl[0x97] = &bCPU::op_sta_ildpy;
optbl[0x83] = &bCPU::op_sta_sr;
optbl[0x93] = &bCPU::op_sta_isry;
optbl[0x90] = &bCPU::op_bcc;
optbl[0xb0] = &bCPU::op_bcs;
optbl[0xd0] = &bCPU::op_bne;
optbl[0xf0] = &bCPU::op_beq;
optbl[0x10] = &bCPU::op_bpl;
optbl[0x30] = &bCPU::op_bmi;
optbl[0x50] = &bCPU::op_bvc;
optbl[0x70] = &bCPU::op_bvs;
optbl[0x80] = &bCPU::op_bra;
optbl[0x82] = &bCPU::op_brl;
optbl[0x4c] = &bCPU::op_jmp_addr;
optbl[0x5c] = &bCPU::op_jmp_long;
optbl[0x6c] = &bCPU::op_jmp_iaddr;
optbl[0x7c] = &bCPU::op_jmp_iaddrx;
optbl[0xdc] = &bCPU::op_jmp_iladdr;
optbl[0x20] = &bCPU::op_jsr_addr;
optbl[0x22] = &bCPU::op_jsr_long;
optbl[0xfc] = &bCPU::op_jsr_iaddrx;
optbl[0x40] = &bCPU::op_rti;
optbl[0x60] = &bCPU::op_rts;
optbl[0x6b] = &bCPU::op_rtl;
optbl[0xea] = &bCPU::op_nop;
optbl[0x42] = &bCPU::op_wdm;
optbl[0xeb] = &bCPU::op_xba;
optbl[0x54] = &bCPU::op_mvn;
optbl[0x44] = &bCPU::op_mvp;
optbl[0x00] = &bCPU::op_brk;
optbl[0x02] = &bCPU::op_cop;
optbl[0xdb] = &bCPU::op_stp;
optbl[0xcb] = &bCPU::op_wai;
optbl[0xfb] = &bCPU::op_xce;
optbl[0x18] = &bCPU::op_clc;
optbl[0xd8] = &bCPU::op_cld;
optbl[0x58] = &bCPU::op_cli;
optbl[0xb8] = &bCPU::op_clv;
optbl[0x38] = &bCPU::op_sec;
optbl[0xf8] = &bCPU::op_sed;
optbl[0x78] = &bCPU::op_sei;
optbl[0xc2] = &bCPU::op_rep;
optbl[0xe2] = &bCPU::op_sep;
optbl[0xaa] = &bCPU::op_tax;
optbl[0xa8] = &bCPU::op_tay;
optbl[0x8a] = &bCPU::op_txa;
optbl[0x9b] = &bCPU::op_txy;
optbl[0x98] = &bCPU::op_tya;
optbl[0xbb] = &bCPU::op_tyx;
optbl[0x5b] = &bCPU::op_tcd;
optbl[0x1b] = &bCPU::op_tcs;
optbl[0x7b] = &bCPU::op_tdc;
optbl[0x3b] = &bCPU::op_tsc;
optbl[0xba] = &bCPU::op_tsx;
optbl[0x9a] = &bCPU::op_txs;
optbl[0x48] = &bCPU::op_pha;
optbl[0xda] = &bCPU::op_phx;
optbl[0x5a] = &bCPU::op_phy;
optbl[0x0b] = &bCPU::op_phd;
optbl[0x8b] = &bCPU::op_phb;
optbl[0x4b] = &bCPU::op_phk;
optbl[0x08] = &bCPU::op_php;
optbl[0x68] = &bCPU::op_pla;
optbl[0xfa] = &bCPU::op_plx;
optbl[0x7a] = &bCPU::op_ply;
optbl[0x2b] = &bCPU::op_pld;
optbl[0xab] = &bCPU::op_plb;
optbl[0x28] = &bCPU::op_plp;
optbl[0xf4] = &bCPU::op_pea;
optbl[0xd4] = &bCPU::op_pei;
optbl[0x62] = &bCPU::op_per;

260
src/cpu/bcpu/dma/dma.cpp Normal file
View File

@@ -0,0 +1,260 @@
/* used by both DMA and HDMA
* prevents transfer across same bus (a->a or b->b)
*/
void bCPU::dma_transfer_byte(bool direction, uint8 bbus, uint32 abus) {
uint8 r;
if(direction == 0) {
//read from address bus a, write to address bus b
//DMA address bus a cannot read from or write to the following addresses:
//$[00-3f|80-bf]:21[00-ff] <address bus b>
//$[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>
if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300 ||
(abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c) {
//these invalid reads will return open bus
r = r_cpu->regs.mdr;
} else {
r = r_mem->read(abus);
}
r_mem->write(0x2100 | bbus, r);
} else {
//read from address bus b, write to address bus a
//block invalid writes, see comments above
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;
}
void bCPU::hdma_add_cycles(uint32 cycles) {
if(run_state.dma) {
status.dma_cycle_count += cycles;
}
status.hdma_cycle_count += cycles;
}
uint32 bCPU::dma_addr(uint8 i) {
uint32 r;
r = (channel[i].srcbank << 16) | (channel[i].srcaddr);
if(channel[i].fixedxfer == false) {
channel[i].srcaddr += channel[i].incmode;
}
return r;
}
void bCPU::dma_cputommio(uint8 i, uint8 bbus) {
if(cartridge.info.sdd1 == true && sdd1->dma_active() == true) {
r_mem->write(0x2100 | bbus, sdd1->dma_read());
} else {
dma_transfer_byte(0, bbus, dma_addr(i));
}
add_cycles(8);
channel[i].xfersize--;
}
void bCPU::dma_mmiotocpu(uint8 i, uint8 bbus) {
dma_transfer_byte(1, bbus, dma_addr(i));
add_cycles(8);
channel[i].xfersize--;
}
void bCPU::dma_write(uint8 i, uint8 index) {
if(channel[i].direction == 0) {
dma_cputommio(i, index);
} else {
dma_mmiotocpu(i, index);
}
}
void bCPU::dma_run() {
for(int i = 0; i < 8; i++) {
if(channel[i].dma_enabled == false)continue;
//first byte transferred?
if(cartridge.info.sdd1 == true && channel[i].read_index == 0) {
sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr),
channel[i].xfersize);
}
dma_write(i, dma_bbus(i, channel[i].read_index++));
dma_add_cycles(8);
if(channel[i].xfersize == 0) {
channel[i].dma_enabled = false;
}
return;
}
status.dma_state = DMASTATE_CPUSYNC;
}
uint32 bCPU::hdma_addr(uint8 i) {
return (channel[i].srcbank << 16) | (channel[i].hdma_addr++);
}
uint32 bCPU::hdma_iaddr(uint8 i) {
return (channel[i].hdma_ibank << 16) | (channel[i].hdma_iaddr++);
}
void bCPU::hdma_update(uint8 i) {
channel[i].hdma_line_counter = r_mem->read(hdma_addr(i));
add_cycles(8);
hdma_add_cycles(8);
if(channel[i].hdma_indirect) {
channel[i].hdma_iaddr = r_mem->read(hdma_addr(i)) << 8;
add_cycles(8);
hdma_add_cycles(8);
}
if(channel[i].hdma_line_counter == 0) {
channel[i].hdma_completed = true;
channel[i].hdma_do_transfer = false;
return;
}
channel[i].hdma_do_transfer = true;
if(channel[i].hdma_indirect) {
channel[i].hdma_iaddr >>= 8;
channel[i].hdma_iaddr |= r_mem->read(hdma_addr(i)) << 8;
add_cycles(8);
hdma_add_cycles(8);
}
}
void bCPU::hdma_run() {
static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
for(int i = 0; i < 8; i++) {
if(!channel[i].hdma_enabled || channel[i].hdma_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, dma_bbus(i, channel[i].read_index),
channel[i].hdma_indirect ? hdma_iaddr(i) : hdma_addr(i));
}
add_cycles(8);
hdma_add_cycles(8);
}
}
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);
}
}
}
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++) {
if(channel[i].hdma_enabled)r++;
}
return r;
}
uint8 bCPU::hdma_active_channels() {
int r = 0;
for(int i = 0; i < 8; i++) {
if(channel[i].hdma_enabled && !channel[i].hdma_completed)r++;
}
return r;
}
/* hdmainit_activate()
* hdma_activate()
*
* Functions are called by CPU timing routine
* when an HDMA event (init or run) occurs.
*/
void bCPU::hdmainit_activate() {
for(int i = 0; i < 8; i++) {
channel[i].hdma_completed = false;
channel[i].hdma_do_transfer = false;
}
if(hdma_enabled_channels() != 0) {
status.hdma_state = HDMASTATE_IDMASYNC;
run_state.hdma = true;
}
}
void bCPU::hdma_activate() {
if(hdma_active_channels() != 0) {
status.hdma_state = HDMASTATE_DMASYNC;
run_state.hdma = true;
}
}
void bCPU::dma_reset() {
status.dma_state = DMASTATE_CPUSYNC;
status.hdma_state = HDMASTATE_CPUSYNC;
status.dma_cycle_count = 0;
status.hdma_cycle_count = 0;
for(int i = 0; i < 8; i++) {
channel[i].read_index = 0;
channel[i].dma_enabled = false;
channel[i].hdma_enabled = false;
channel[i].dmap = 0xff;
channel[i].direction = 1;
channel[i].hdma_indirect = 1;
channel[i].incmode = -1;
channel[i].fixedxfer = 1;
channel[i].xfermode = 7;
channel[i].destaddr = 0xff;
channel[i].srcaddr = 0xffff;
channel[i].srcbank = 0xff;
channel[i].xfersize = 0xffff;
//xfersize and hdma_iaddr are of union { uint16 };
//channel[i].hdma_iaddr = 0xffff;
channel[i].hdma_ibank = 0xff;
channel[i].hdma_addr = 0xffff;
channel[i].hdma_line_counter = 0xff;
channel[i].hdma_unknown = 0xff;
channel[i].hdma_completed = false;
channel[i].hdma_do_transfer = false;
}
}

61
src/cpu/bcpu/dma/dma.h Normal file
View File

@@ -0,0 +1,61 @@
struct {
uint32 read_index; //set to 0 at beginning of DMA/HDMA
//$420b
bool dma_enabled;
//$420c
bool hdma_enabled;
//$43x0
uint8 dmap;
bool direction;
bool hdma_indirect;
int8 incmode;
bool fixedxfer;
uint8 xfermode;
//$43x1
uint8 destaddr;
//$43x2-$43x3
uint16 srcaddr;
//$43x4
uint8 srcbank;
//$43x5-$43x6
union {
uint16 xfersize;
uint16 hdma_iaddr;
};
//$43x7
uint8 hdma_ibank;
//$43x8-$43x9
uint16 hdma_addr;
//$43xa
uint8 hdma_line_counter;
//$43xb/$43xf
uint8 hdma_unknown;
//hdma-specific
bool hdma_completed; //for this frame
bool hdma_do_transfer;
uint8 hdma_current_channel;
uint8 hdma_current_pos;
} 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();
inline void hdmainit_activate();
inline void hdma_activate();
inline void dma_cputommio(uint8 i, uint8 index);
inline void dma_mmiotocpu(uint8 i, uint8 index);
inline void dma_write(uint8 i, uint8 index);
inline uint32 dma_addr(uint8 i);
inline uint32 hdma_addr(uint8 i);
inline uint32 hdma_iaddr(uint8 i);
inline void dma_reset();

View File

@@ -0,0 +1,40 @@
uint8 bCPU::port_read(uint8 port) {
return apu_port[port & 3];
}
void bCPU::port_write(uint8 port, uint8 value) {
apu_port[port & 3] = value;
}
/* The next 3 functions control bus timing for the CPU.
* cpu_io is an I/O cycle, and always 6 clock cycles long.
* mem_read / mem_write indicate memory access bus cycle,
* they are either 6, 8, or 12 bus cycles long, depending
* both on location and the $420d.d0 FastROM enable bit.
*/
void bCPU::cpu_io() {
status.cycle_count = 6;
pre_exec_cycle();
add_cycles(6);
cycle_edge();
}
uint8 bCPU::mem_read(uint32 addr) {
status.cycle_count = r_mem->speed(addr);
pre_exec_cycle();
add_cycles(status.cycle_count - 4);
regs.mdr = r_mem->read(addr);
add_cycles(4);
cycle_edge();
return regs.mdr;
}
void bCPU::mem_write(uint32 addr, uint8 value) {
status.cycle_count = r_mem->speed(addr);
pre_exec_cycle();
add_cycles(status.cycle_count);
regs.mdr = value;
r_mem->write(addr, value);
cycle_edge();
}

View File

@@ -0,0 +1,27 @@
uint8 apu_port[4];
inline uint8 port_read (uint8 port);
inline void port_write(uint8 port, uint8 value);
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); }

View File

@@ -0,0 +1,338 @@
/* Notes about PAL timing:
* As I do not have PAL hardware to run timing tests on, I've
* had to guess on a lot of things. Below is how I've arrived
* at various calculations:
*
* NTSC timing crystal: ~21477272hz
* PAL timing crystal: ~21281370hz
* NTSC ~60fps, PAL ~50fps
* NTSC ~262 lines/frame, PAL ~312 lines/frame
* NTSC 21477272 / (262 * 60) = ~1366 cycles/line
* PAL 21281370 / (312 * 50) = ~1364 cycles/line
*
* As the cycles/line are very close between the two systems,
* I have left the known NTSC anomalies intact for PAL timing.
* In reality, some of these may not exist, and some may be
* slightly different.
*
* [known]
* - DRAM refresh occurs at about the same time every
* scanline on PAL units (per Overload).
* [unknown]
* - Are dots 323/327 still 2 cycles longer than the
* other dots?
* - Is scanline 240 on non-interlace odd frames still
* 4 cycles short?
*/
uint16 bCPU::vcounter() { return time.v; }
uint16 bCPU::hclock() { return time.hc; }
bool bCPU::interlace() { return time.interlace; }
bool bCPU::interlace_field() { return time.interlace_field; }
bool bCPU::overscan() { return time.overscan; }
uint16 bCPU::region_scanlines() { return time.region_scanlines; }
void bCPU::set_interlace(bool r) { time.interlace = r; update_interrupts(); }
void bCPU::set_overscan (bool r) { time.overscan = r; update_interrupts(); }
uint8 bCPU::dma_counter() { return (time.dma_counter + time.hc) & 6; }
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;
return (time.v == v && time.hc == hc);
}
bool bCPU::irq_trigger_pos_match(uint32 offset) {
uint16 v = status.virq_pos;
uint16 hc = (status.hirq_enabled) ? status.hirq_pos : 0;
uint16 vlimit = region_scanlines() >> 1;
//positions that can never be latched
//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 == (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;
hc += offset;
if(hc >= time.line_cycles) {
hc -= time.line_cycles;
if(++v >= time.frame_lines) {
v = 0;
}
}
if((status.virq_enabled == true && time.v == v) || status.virq_enabled == false) {
return (time.hc == hc);
}
return false;
}
void bCPU::update_nmi() {
if(time.v == (overscan() ? 240 : 225)) {
time.nmi_read_trigger_pos = 2;
time.nmi_line_trigger_pos = 6;
} else {
time.nmi_read_trigger_pos = -64;
time.nmi_line_trigger_pos = -64;
}
}
void bCPU::update_irq() {
int vpos = status.virq_pos;
int hpos = (status.hirq_enabled) ? status.hirq_pos : 0;
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 == (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;
if(hpos >= time.line_cycles) {
hpos -= time.line_cycles;
if(++vpos >= time.frame_lines) {
vpos = 0;
}
}
if((status.virq_enabled == true && time.v == vpos) || status.virq_enabled == false) {
time.irq_read_trigger_pos = hpos;
} else {
time.irq_read_trigger_pos = -64;
}
hpos += 4;
if(hpos >= time.line_cycles) {
hpos -= time.line_cycles;
if(++vpos >= time.frame_lines) {
vpos = 0;
}
}
if((status.virq_enabled == true && time.v == vpos) || status.virq_enabled == false) {
time.irq_line_trigger_pos = hpos;
} else {
time.irq_line_trigger_pos = -64;
}
return;
_nolatch:
time.irq_read_trigger_pos = -64;
time.irq_line_trigger_pos = -64;
}
void bCPU::update_interrupts() {
update_nmi();
update_irq();
}
void bCPU::poll_interrupts(int cycles) {
int16 hc, hc_end;
if(time.hc == 0) {
hc = -1;
hc_end = cycles;
} else {
hc = time.hc;
hc_end = time.hc + cycles;
}
if(hc < time.nmi_read_trigger_pos && time.nmi_read_trigger_pos <= hc_end) {
//nmi_read can go low even with NMI interrupts disabled in $4200.d7
time.nmi_read = 0;
}
if(hc < time.nmi_line_trigger_pos && time.nmi_line_trigger_pos <= hc_end) {
if(status.nmi_enabled == true) {
if(time.nmi_line == 1) {
time.nmi_transition = 1;
}
time.nmi_line = 0;
}
}
if(hc < time.irq_read_trigger_pos && time.irq_read_trigger_pos <= hc_end) {
if(status.virq_enabled == true || status.hirq_enabled == true) {
time.irq_read = 0;
}
}
if(hc < time.irq_line_trigger_pos && time.irq_line_trigger_pos <= hc_end) {
if(status.virq_enabled == true || status.hirq_enabled == true) {
time.irq_line = 0;
time.irq_transition = 1;
}
}
}
uint32 bCPU::clocks_executed() {
uint32 r = status.cycles_executed;
status.cycles_executed = 0;
return r;
}
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;
} else {
time.line_cycles = 1364;
}
time.dram_refreshed = false;
time.line_rendered =
time.hdma_triggered = (time.v <= (!overscan() ? 224 : 239)) ? false : true;
r_ppu->scanline();
snes->scanline();
update_interrupts();
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::frame() {
time.nmi_read = 1;
time.nmi_line = 1;
time.nmi_transition = 0;
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(cpu_version == 2) {
time.hdmainit_trigger_pos = 12 + dma_counter();
} else {
time.hdmainit_trigger_pos = 12 + 8 - dma_counter();
}
time.hdmainit_triggered = false;
r_ppu->frame();
snes->frame();
}
void bCPU::time_reset() {
time.v = 0;
time.hc = 0;
//upon SNES reset, start at scanline 0 non-interlace
time.interlace = 0;
time.interlace_field = 0;
time.overscan = false;
time.line_cycles = 1364;
time.dram_refreshed = false;
time.dram_refresh_pos = (cpu_version == 2) ? 538 : 530;
time.dma_counter = 0;
//set at V=0,H=0
time.hdmainit_trigger_pos = 0;
time.hdmainit_triggered = true;
time.hdma_triggered = false;
time.nmi_pending = false;
time.irq_pending = false;
time.nmi_line = time.nmi_read = 1;
time.irq_line = time.irq_read = 1;
time.nmi_transition = 0;
time.irq_transition = 0;
update_interrupts();
switch(region) {
case NTSC:
time.region_scanlines = 525;
break;
case PAL:
time.region_scanlines = 625;
break;
}
time.frame_lines = time.region_scanlines >> 1;
}

View File

@@ -0,0 +1,74 @@
struct {
uint16 v, hc;
bool interlace, interlace_field, overscan;
uint16 line_cycles, frame_lines;
bool line_rendered;
bool dram_refreshed;
uint16 dram_refresh_pos;
uint8 dma_counter;
uint16 hdmainit_trigger_pos;
bool hdmainit_triggered;
bool hdma_triggered;
uint16 region_scanlines;
//nmi_pending, irq_pending are used by last_cycle()
//nmi_line = /NMI, nmi_read = $4210.7
//irq_line = /IRQ, irq_read = $4211.7
bool nmi_pending, nmi_line, nmi_read;
bool irq_pending, irq_line, irq_read;
//NMI is edge-sensitive, meaning it triggers when /NMI
//transitions from high to low. This value is set to 1
//when that happens, and cleared after the nmi_test()
//routine acknowledges it and invokes the NMI interrupt
bool nmi_transition;
//IRQ is level-sensitive, so it does not need to keep
//track of transitions from high to low. IRQs will
//continue to fire as long as /IRQ stays low.
//However, if a write to $4200 forces IRQs high at the
//exact same clock cycle that /IRQ goes low, the /IRQ
//will still occur. Hence the need for this variable.
bool irq_transition;
//position is relative to time.hc, set at start of each scanline
//-64 means no trigger point on this scanline
//$4210/$4211 status bits get set before /NMI and /IRQ go low,
//hence the need for two variables for each.
int32 nmi_read_trigger_pos, nmi_line_trigger_pos;
int32 irq_read_trigger_pos, irq_line_trigger_pos;
} time;
inline uint16 vcounter();
inline uint16 hcounter();
inline uint16 hclock();
inline bool interlace();
inline bool interlace_field();
inline bool overscan();
inline uint16 region_scanlines();
inline bool nmi_trigger_pos_match(uint32 offset);
inline bool irq_trigger_pos_match(uint32 offset);
inline void update_nmi();
inline void update_irq();
inline void update_interrupts();
inline void poll_interrupts(int cycles);
inline void set_interlace(bool r);
inline void set_overscan (bool r);
inline uint8 dma_counter();
inline void cycle_edge();
inline void add_cycles(int cycles);
inline void scanline();
inline void frame();
inline void time_reset();

View File

@@ -2,5 +2,8 @@
#include "dcpu.cpp"
CPU::CPU() {
mmio = &mmio_unmapped;
cpu_version = 1;
}
CPU::~CPU() {
}

View File

@@ -1,49 +1,92 @@
#include "cpuregs.h"
class CPU {
class CPU : public MMIO {
public:
MMIO *mmio;
//CPU version number
//* 1 and 2 are known
//* reported by $4210
//* affects DRAM refresh behavior
uint8 cpu_version;
//timing
virtual uint16 vcounter() = 0;
virtual uint16 hcounter() = 0;
virtual uint16 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;
CPURegs regs;
virtual uint8 port_read (uint8 port) = 0;
virtual void port_write(uint8 port, uint8 value) = 0;
enum {
FLAG_N = 0x80, FLAG_V = 0x40,
FLAG_M = 0x20, FLAG_X = 0x10,
FLAG_D = 0x08, FLAG_I = 0x04,
FLAG_Z = 0x02, FLAG_C = 0x01
};
virtual uint8 pio_status() = 0;
virtual void run() = 0;
virtual void scanline() = 0;
virtual void frame() = 0;
virtual void power() = 0;
virtual void reset() = 0;
virtual uint8 pio_status() = 0;
virtual void main() {}
virtual void run() = 0;
virtual uint32 clocks_executed() = 0;
virtual void scanline() = 0;
virtual void frame() = 0;
virtual void power() = 0;
virtual void reset() = 0;
/*****
* 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
OPTYPE_DPY, //dp,y
OPTYPE_IDP, //(dp)
OPTYPE_IDPX, //(dp,x)
OPTYPE_IDPY, //(dp),y
OPTYPE_ILDP, //[dp]
OPTYPE_ILDPY, //[dp],y
OPTYPE_ADDR, //addr
OPTYPE_ADDRX, //addr,x
OPTYPE_ADDRY, //addr,y
OPTYPE_IADDRX, //(addr,x)
OPTYPE_ILADDR, //[addr]
OPTYPE_LONG, //long
OPTYPE_LONGX, //long, x
OPTYPE_SR, //sr,s
OPTYPE_ISRY, //(sr,s),y
OPTYPE_ADDR_PC, //pbr:addr
OPTYPE_IADDR_PC, //pbr:(addr)
OPTYPE_RELB, //relb
OPTYPE_RELW, //relw
};
//opcode disassembler
enum {
OPTYPE_DP = 0, //dp
OPTYPE_DPX, //dp,x
OPTYPE_DPY, //dp,y
OPTYPE_IDP, //(dp)
OPTYPE_IDPX, //(dp,x)
OPTYPE_IDPY, //(dp),y
OPTYPE_ILDP, //[dp]
OPTYPE_ILDPY, //[dp],y
OPTYPE_ADDR, //addr
OPTYPE_ADDRX, //addr,x
OPTYPE_ADDRY, //addr,y
OPTYPE_IADDRX, //(addr,x)
OPTYPE_ILADDR, //[addr]
OPTYPE_LONG, //long
OPTYPE_LONGX, //long, x
OPTYPE_SR, //sr,s
OPTYPE_ISRY, //(sr,s),y
OPTYPE_ADDR_PC, //pbr:addr
OPTYPE_IADDR_PC //pbr:(addr)
};
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();
};

View File

@@ -1,76 +1,66 @@
class CPURegFlags {
private:
template <uint8 B> class bit {
public:
uint8 b;
inline operator bool() { return (b & B); }
inline operator = (bool i) { (i) ? b |= B : b &= ~B; return (b & B); }
inline operator & (bool i) { if(i)b &= ~B; return (b & B); }
inline operator | (bool i) { if(i)b |= B; return (b & B); }
inline operator ^ (bool i) { if(i)b ^= B; return (b & B); }
};
public:
union {
uint8 b;
bit<0x80> n;
bit<0x40> v;
bit<0x20> m;
bit<0x10> x;
bit<0x08> d;
bit<0x04> i;
bit<0x02> z;
bit<0x01> c;
union {
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 {
union {
uint16 w;
struct { uint8 l, h; };
};
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 {
uint16 w;
union {
uint32 d;
struct { uint8 l, h, b; };
};
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 {
@@ -79,6 +69,8 @@ CPUReg24 pc;
CPUReg16 a, x, y, s, d;
CPURegFlags p;
uint8 db;
uint8 mdr;
bool e;
CPURegs() { db = 0; e = false; }
bool acc_8b, idx_8b;
CPURegs() : db(0), mdr(0x00), e(false), acc_8b(true), idx_8b(true) {}
};

View File

@@ -1,16 +1,28 @@
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:
@@ -24,23 +36,23 @@ uint32 r = 0;
break;
case OPTYPE_IDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + mem_bus->read_word(addr);
r = (regs.db << 16) + dreadw(addr);
break;
case OPTYPE_IDPX:
addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + mem_bus->read_word(addr);
r = (regs.db << 16) + dreadw(addr);
break;
case OPTYPE_IDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + mem_bus->read_word(addr) + regs.y;
r = (regs.db << 16) + dreadw(addr) + regs.y;
break;
case OPTYPE_ILDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = mem_bus->read_long(addr);
r = dreadl(addr);
break;
case OPTYPE_ILDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = mem_bus->read_long(addr) + regs.y;
r = dreadl(addr) + regs.y;
break;
case OPTYPE_ADDR:
r = (regs.db << 16) + (addr & 0xffff);
@@ -61,356 +73,376 @@ uint32 r = 0;
r = (regs.pc.b << 16) + ((addr + regs.x) & 0xffff);
break;
case OPTYPE_ILADDR:
r = addr & 0xffffff;
r = addr;
break;
case OPTYPE_LONG:
r = addr & 0xffffff;
r = addr;
break;
case OPTYPE_LONGX:
r = (addr + regs.x) & 0xffffff;
r = (addr + regs.x);
break;
case OPTYPE_SR:
r = (regs.s + (addr & 0xff)) & 0xffff;
break;
case OPTYPE_ISRY:
addr = (regs.s + (addr & 0xff)) & 0xffff;
r = (regs.db << 16) + mem_bus->read_word(addr) + regs.y;
r = (regs.db << 16) + dreadw(addr) + regs.y;
break;
case OPTYPE_RELB:
r = (regs.pc.b << 16) + ((regs.pc.w + 2) & 0xffff);
r += int8(addr);
break;
case OPTYPE_RELW:
r = (regs.pc.b << 16) + ((regs.pc.w + 3) & 0xffff);
r += int16(addr);
break;
}
return r;
return(r & 0xffffff);
}
void CPU::disassemble_opcode(char *output) {
char *s = output;
static CPUReg24 pc;
char t[256];
uint8 op, op0, op1, op2;
sprintf(s, "%0.6x ", regs.pc.d);
char *s = output;
//TODO: This should wrap around the bank byte
op = mem_bus->read(regs.pc.d);
op0 = mem_bus->read(regs.pc.d + 1);
op1 = mem_bus->read(regs.pc.d + 2);
op2 = mem_bus->read(regs.pc.d + 3);
switch(op) {
case 0x00:sprintf(t, "brk #$%0.2x ", op0);break;
case 0x01:sprintf(t, "ora ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0x02:sprintf(t, "cop #$%0.2x ", op0);break;
case 0x03:sprintf(t, "ora $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0x04:sprintf(t, "tsb $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x05:sprintf(t, "ora $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x06:sprintf(t, "asl $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x07:sprintf(t, "ora [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0x08:sprintf(t, "php ");break;
case 0x09:
if(regs.p.m)sprintf(t, "ora #$%0.2x ", op0);
else sprintf(t, "ora #$%0.4x ", op0|op1<<8);break;
case 0x0a:sprintf(t, "asl a ");break;
case 0x0b:sprintf(t, "phd ");break;
case 0x0c:sprintf(t, "tsb $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x0d:sprintf(t, "ora $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x0e:sprintf(t, "asl $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x0f:sprintf(t, "ora $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x10:sprintf(t, "bpl $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0x11:sprintf(t, "ora ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0x12:sprintf(t, "ora ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0x13:sprintf(t, "ora ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0x14:sprintf(t, "trb $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x15:sprintf(t, "ora $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x16:sprintf(t, "asl $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x17:sprintf(t, "ora [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0x18:sprintf(t, "clc ");break;
case 0x19:sprintf(t, "ora $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0x1a:sprintf(t, "inc ");break;
case 0x1b:sprintf(t, "tcs ");break;
case 0x1c:sprintf(t, "trb $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x1d:sprintf(t, "ora $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x1e:sprintf(t, "asl $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x1f:sprintf(t, "ora $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0x20:sprintf(t, "jsr $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR_PC, (op0|op1<<8)));break;
case 0x21:sprintf(t, "and ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0x22:sprintf(t, "jsl $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x23:sprintf(t, "and $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0x24:sprintf(t, "bit $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x25:sprintf(t, "and $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x26:sprintf(t, "rol $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x27:sprintf(t, "and [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0x28:sprintf(t, "plp ");break;
case 0x29:
if(regs.p.m)sprintf(t, "and #$%0.2x ", op0);
else sprintf(t, "and #$%0.4x ", op0|op1<<8);break;
case 0x2a:sprintf(t, "rol a ");break;
case 0x2b:sprintf(t, "pld ");break;
case 0x2c:sprintf(t, "bit $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x2d:sprintf(t, "and $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x2e:sprintf(t, "rol $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x2f:sprintf(t, "and $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x30:sprintf(t, "bmi $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0x31:sprintf(t, "and ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0x32:sprintf(t, "and ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0x33:sprintf(t, "and ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0x34:sprintf(t, "bit $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x35:sprintf(t, "and $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x36:sprintf(t, "rol $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x37:sprintf(t, "and [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0x38:sprintf(t, "sec ");break;
case 0x39:sprintf(t, "and $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0x3a:sprintf(t, "dec ");break;
case 0x3b:sprintf(t, "tsc ");break;
case 0x3c:sprintf(t, "bit $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x3d:sprintf(t, "and $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x3e:sprintf(t, "rol $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x3f:sprintf(t, "and $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0x40:sprintf(t, "rti ");break;
case 0x41:sprintf(t, "eor ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0x42:sprintf(t, "wdm ");break;
case 0x43:sprintf(t, "eor $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0x44:sprintf(t, "mvp $%0.2x,$%0.2x ", op1, op0);break;
case 0x45:sprintf(t, "eor $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x46:sprintf(t, "lsr $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x47:sprintf(t, "eor [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0x48:sprintf(t, "pha ");break;
case 0x49:
if(regs.p.m)sprintf(t, "eor #$%0.2x ", op0);
else sprintf(t, "eor #$%0.4x ", op0|op1<<8);break;
case 0x4a:sprintf(t, "lsr a ");break;
case 0x4b:sprintf(t, "phk ");break;
case 0x4c:sprintf(t, "jmp $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR_PC, (op0|op1<<8)));break;
case 0x4d:sprintf(t, "eor $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x4e:sprintf(t, "lsr $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x4f:sprintf(t, "eor $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x50:sprintf(t, "bvc $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0x51:sprintf(t, "eor ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0x52:sprintf(t, "eor ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0x53:sprintf(t, "eor ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0x54:sprintf(t, "mvn $%0.2x,$%0.2x ", op1, op0);break;
case 0x55:sprintf(t, "eor $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x56:sprintf(t, "lsr $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x57:sprintf(t, "eor [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0x58:sprintf(t, "cli ");break;
case 0x59:sprintf(t, "eor $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0x5a:sprintf(t, "phy ");break;
case 0x5b:sprintf(t, "tcd ");break;
case 0x5c:sprintf(t, "jml $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x5d:sprintf(t, "eor $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x5e:sprintf(t, "lsr $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x5f:sprintf(t, "eor $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0x60:sprintf(t, "rts ");break;
case 0x61:sprintf(t, "adc ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0x62:sprintf(t, "per $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x63:sprintf(t, "adc $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0x64:sprintf(t, "stz $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x65:sprintf(t, "adc $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x66:sprintf(t, "ror $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x67:sprintf(t, "adc [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0x68:sprintf(t, "pla ");break;
case 0x69:
if(regs.p.m)sprintf(t, "adc #$%0.2x ", op0);
else sprintf(t, "adc #$%0.4x ", op0|op1<<8);break;
case 0x6a:sprintf(t, "ror a ");break;
case 0x6b:sprintf(t, "rtl ");break;
case 0x6c:sprintf(t, "jmp ($%0.4x) [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_IADDR_PC, (op0|op1<<8)));break;
case 0x6d:sprintf(t, "adc $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x6e:sprintf(t, "ror $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x6f:sprintf(t, "adc $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x70:sprintf(t, "bvs $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0x71:sprintf(t, "adc ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0x72:sprintf(t, "adc ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0x73:sprintf(t, "adc ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0x74:sprintf(t, "stz $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x75:sprintf(t, "adc $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x76:sprintf(t, "ror $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x77:sprintf(t, "adc [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0x78:sprintf(t, "sei ");break;
case 0x79:sprintf(t, "adc $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0x7a:sprintf(t, "ply ");break;
case 0x7b:sprintf(t, "tdc ");break;
case 0x7c:sprintf(t, "jmp ($%0.4x,x) [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_IADDRX, (op0|op1<<8)));break;
case 0x7d:sprintf(t, "adc $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x7e:sprintf(t, "ror $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x7f:sprintf(t, "adc $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0x80:sprintf(t, "bra $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0x81:sprintf(t, "sta ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0x82:sprintf(t, "brl $%0.4x [$%0.6x]", __relw(op0|op1<<8)&0xffff, __relw(op0|op1<<8)&0xffffff);break;
case 0x83:sprintf(t, "sta $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0x84:sprintf(t, "sty $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x85:sprintf(t, "sta $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x86:sprintf(t, "stx $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x87:sprintf(t, "sta [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0x88:sprintf(t, "dey ");break;
case 0x89:
if(regs.p.m)sprintf(t, "bit #$%0.2x ", op0);
else sprintf(t, "bit #$%0.4x ", op0|op1<<8);break;
case 0x8a:sprintf(t, "txa ");break;
case 0x8b:sprintf(t, "phb ");break;
case 0x8c:sprintf(t, "sty $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x8d:sprintf(t, "sta $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x8e:sprintf(t, "stx $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x8f:sprintf(t, "sta $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x90:sprintf(t, "bcc $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0x91:sprintf(t, "sta ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0x92:sprintf(t, "sta ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0x93:sprintf(t, "sta ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0x94:sprintf(t, "sty $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x95:sprintf(t, "sta $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x96:sprintf(t, "stx $%0.2x,y [$%0.6x]", op0, resolve_offset(OPTYPE_DPY, op0));break;
case 0x97:sprintf(t, "sta [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0x98:sprintf(t, "tya ");break;
case 0x99:sprintf(t, "sta $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0x9a:sprintf(t, "txs ");break;
case 0x9b:sprintf(t, "txy ");break;
case 0x9c:sprintf(t, "stz $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x9d:sprintf(t, "sta $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x9e:sprintf(t, "stz $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x9f:sprintf(t, "sta $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0xa0:
if(regs.p.x)sprintf(t, "ldy #$%0.2x ", op0);
else sprintf(t, "ldy #$%0.4x ", op0|op1<<8);break;
case 0xa1:sprintf(t, "lda ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0xa2:
if(regs.p.x)sprintf(t, "ldx #$%0.2x ", op0);
else sprintf(t, "ldx #$%0.4x ", op0|op1<<8);break;
case 0xa3:sprintf(t, "lda $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0xa4:sprintf(t, "ldy $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xa5:sprintf(t, "lda $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xa6:sprintf(t, "ldx $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xa7:sprintf(t, "lda [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0xa8:sprintf(t, "tay ");break;
case 0xa9:
if(regs.p.m)sprintf(t, "lda #$%0.2x ", op0);
else sprintf(t, "lda #$%0.4x ", op0|op1<<8);break;
case 0xaa:sprintf(t, "tax ");break;
case 0xab:sprintf(t, "plb ");break;
case 0xac:sprintf(t, "ldy $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xad:sprintf(t, "lda $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xae:sprintf(t, "ldx $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xaf:sprintf(t, "lda $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0xb0:sprintf(t, "bcs $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0xb1:sprintf(t, "lda ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0xb2:sprintf(t, "lda ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0xb3:sprintf(t, "lda ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0xb4:sprintf(t, "ldy $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0xb5:sprintf(t, "lda $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0xb6:sprintf(t, "ldx $%0.2x,y [$%0.6x]", op0, resolve_offset(OPTYPE_DPY, op0));break;
case 0xb7:sprintf(t, "lda [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0xb8:sprintf(t, "clv ");break;
case 0xb9:sprintf(t, "lda $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0xba:sprintf(t, "tsx ");break;
case 0xbb:sprintf(t, "tyx ");break;
case 0xbc:sprintf(t, "ldy $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0xbd:sprintf(t, "lda $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0xbe:sprintf(t, "ldx $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0xbf:sprintf(t, "lda $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0xc0:
if(regs.p.x)sprintf(t, "cpy #$%0.2x ", op0);
else sprintf(t, "cpy #$%0.4x ", op0|op1<<8);break;
case 0xc1:sprintf(t, "cmp ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0xc2:sprintf(t, "rep #$%0.2x ", op0);break;
case 0xc3:sprintf(t, "cmp $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0xc4:sprintf(t, "cpy $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xc5:sprintf(t, "cmp $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xc6:sprintf(t, "dec $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xc7:sprintf(t, "cmp [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0xc8:sprintf(t, "iny ");break;
case 0xc9:
if(regs.p.m)sprintf(t, "cmp #$%0.2x ", op0);
else sprintf(t, "cmp #$%0.4x ", op0|op1<<8);break;
case 0xca:sprintf(t, "dex ");break;
case 0xcb:sprintf(t, "wai ");break;
case 0xcc:sprintf(t, "cpy $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xcd:sprintf(t, "cmp $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xce:sprintf(t, "dec $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xcf:sprintf(t, "cmp $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0xd0:sprintf(t, "bne $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0xd1:sprintf(t, "cmp ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0xd2:sprintf(t, "cmp ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0xd3:sprintf(t, "cmp ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0xd4:sprintf(t, "pei ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0xd5:sprintf(t, "cmp $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0xd6:sprintf(t, "dec $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0xd7:sprintf(t, "cmp [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0xd8:sprintf(t, "cld ");break;
case 0xd9:sprintf(t, "cmp $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0xda:sprintf(t, "phx ");break;
case 0xdb:sprintf(t, "stp ");break;
case 0xdc:sprintf(t, "jmp [$%0.4x] [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ILADDR, (op0|op1<<8)));break;
case 0xdd:sprintf(t, "cmp $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0xde:sprintf(t, "dec $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0xdf:sprintf(t, "cmp $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0xe0:
if(regs.p.x)sprintf(t, "cpx #$%0.2x ", op0);
else sprintf(t, "cpx #$%0.4x ", op0|op1<<8);break;
case 0xe1:sprintf(t, "sbc ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0xe2:sprintf(t, "sep #$%0.2x ", op0);break;
case 0xe3:sprintf(t, "sbc $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0xe4:sprintf(t, "cpx $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xe5:sprintf(t, "sbc $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xe6:sprintf(t, "inc $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xe7:sprintf(t, "sbc [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0xe8:sprintf(t, "inx ");break;
case 0xe9:
if(regs.p.m)sprintf(t, "sbc #$%0.2x ", op0);
else sprintf(t, "sbc #$%0.4x ", op0|op1<<8);break;
case 0xea:sprintf(t, "nop ");break;
case 0xeb:sprintf(t, "xba ");break;
case 0xec:sprintf(t, "cpx $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xed:sprintf(t, "sbc $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xee:sprintf(t, "inc $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xef:sprintf(t, "sbc $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0xf0:sprintf(t, "beq $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0xf1:sprintf(t, "sbc ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0xf2:sprintf(t, "sbc ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0xf3:sprintf(t, "sbc ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0xf4:sprintf(t, "pea $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xf5:sprintf(t, "sbc $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0xf6:sprintf(t, "inc $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0xf7:sprintf(t, "sbc [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0xf8:sprintf(t, "sed ");break;
case 0xf9:sprintf(t, "sbc $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0xfa:sprintf(t, "plx ");break;
case 0xfb:sprintf(t, "xce ");break;
case 0xfc:sprintf(t, "jsr ($%0.4x,x) [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_IADDRX, (op0|op1<<8)));break;
case 0xfd:sprintf(t, "sbc $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0xfe:sprintf(t, "inc $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0xff:sprintf(t, "sbc $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
if(in_opcode() == true) {
strcpy(s, "?????? <CPU within opcode>");
return;
}
pc.d = regs.pc.d;
sprintf(s, "%0.6x ", uint32(pc.d));
uint8 op = dreadb(pc.d); pc.w++;
uint8 op0 = dreadb(pc.d); pc.w++;
uint8 op1 = dreadb(pc.d); pc.w++;
uint8 op2 = dreadb(pc.d);
#define op8 ((op0))
#define op16 ((op0) | (op1 << 8))
#define op24 ((op0) | (op1 << 8) | (op2 << 16))
#define a8 (regs.e || regs.p.m)
#define x8 (regs.e || regs.p.x)
switch(op) {
case 0x00: sprintf(t, "brk #$%0.2x ", op8); break;
case 0x01: sprintf(t, "ora ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x02: sprintf(t, "cop #$%0.2x ", op8); break;
case 0x03: sprintf(t, "ora $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x04: sprintf(t, "tsb $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x05: sprintf(t, "ora $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x06: sprintf(t, "asl $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x07: sprintf(t, "ora [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x08: sprintf(t, "php "); break;
case 0x09: if(a8)sprintf(t, "ora #$%0.2x ", op8);
else sprintf(t, "ora #$%0.4x ", op16); break;
case 0x0a: sprintf(t, "asl a "); break;
case 0x0b: sprintf(t, "phd "); break;
case 0x0c: sprintf(t, "tsb $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0d: sprintf(t, "ora $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0e: sprintf(t, "asl $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0f: sprintf(t, "ora $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x10: sprintf(t, "bpl $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x11: sprintf(t, "ora ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x12: sprintf(t, "ora ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x13: sprintf(t, "ora ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x14: sprintf(t, "trb $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x15: sprintf(t, "ora $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x16: sprintf(t, "asl $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x17: sprintf(t, "ora [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x18: sprintf(t, "clc "); break;
case 0x19: sprintf(t, "ora $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x1a: sprintf(t, "inc "); break;
case 0x1b: sprintf(t, "tcs "); break;
case 0x1c: sprintf(t, "trb $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x1d: sprintf(t, "ora $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x1e: sprintf(t, "asl $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x1f: sprintf(t, "ora $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x20: sprintf(t, "jsr $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break;
case 0x21: sprintf(t, "and ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x22: sprintf(t, "jsl $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x23: sprintf(t, "and $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x24: sprintf(t, "bit $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x25: sprintf(t, "and $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x26: sprintf(t, "rol $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x27: sprintf(t, "and [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x28: sprintf(t, "plp "); break;
case 0x29: if(a8)sprintf(t, "and #$%0.2x ", op8);
else sprintf(t, "and #$%0.4x ", op16); break;
case 0x2a: sprintf(t, "rol a "); break;
case 0x2b: sprintf(t, "pld "); break;
case 0x2c: sprintf(t, "bit $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2d: sprintf(t, "and $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2e: sprintf(t, "rol $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2f: sprintf(t, "and $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x30: sprintf(t, "bmi $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x31: sprintf(t, "and ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x32: sprintf(t, "and ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x33: sprintf(t, "and ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x34: sprintf(t, "bit $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x35: sprintf(t, "and $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x36: sprintf(t, "rol $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x37: sprintf(t, "and [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x38: sprintf(t, "sec "); break;
case 0x39: sprintf(t, "and $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x3a: sprintf(t, "dec "); break;
case 0x3b: sprintf(t, "tsc "); break;
case 0x3c: sprintf(t, "bit $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3d: sprintf(t, "and $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3e: sprintf(t, "rol $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3f: sprintf(t, "and $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x40: sprintf(t, "rti "); break;
case 0x41: sprintf(t, "eor ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x42: sprintf(t, "wdm "); break;
case 0x43: sprintf(t, "eor $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x44: sprintf(t, "mvp $%0.2x,$%0.2x ", op1, op8); break;
case 0x45: sprintf(t, "eor $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x46: sprintf(t, "lsr $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x47: sprintf(t, "eor [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x48: sprintf(t, "pha "); break;
case 0x49: if(a8)sprintf(t, "eor #$%0.2x ", op8);
else sprintf(t, "eor #$%0.4x ", op16); break;
case 0x4a: sprintf(t, "lsr a "); break;
case 0x4b: sprintf(t, "phk "); break;
case 0x4c: sprintf(t, "jmp $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break;
case 0x4d: sprintf(t, "eor $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x4e: sprintf(t, "lsr $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x4f: sprintf(t, "eor $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x50: sprintf(t, "bvc $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x51: sprintf(t, "eor ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x52: sprintf(t, "eor ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x53: sprintf(t, "eor ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x54: sprintf(t, "mvn $%0.2x,$%0.2x ", op1, op8); break;
case 0x55: sprintf(t, "eor $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x56: sprintf(t, "lsr $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x57: sprintf(t, "eor [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x58: sprintf(t, "cli "); break;
case 0x59: sprintf(t, "eor $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x5a: sprintf(t, "phy "); break;
case 0x5b: sprintf(t, "tcd "); break;
case 0x5c: sprintf(t, "jml $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x5d: sprintf(t, "eor $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x5e: sprintf(t, "lsr $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x5f: sprintf(t, "eor $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x60: sprintf(t, "rts "); break;
case 0x61: sprintf(t, "adc ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x62: sprintf(t, "per $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x63: sprintf(t, "adc $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x64: sprintf(t, "stz $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x65: sprintf(t, "adc $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x66: sprintf(t, "ror $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x67: sprintf(t, "adc [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x68: sprintf(t, "pla "); break;
case 0x69: if(a8)sprintf(t, "adc #$%0.2x ", op8);
else sprintf(t, "adc #$%0.4x ", op16); break;
case 0x6a: sprintf(t, "ror a "); break;
case 0x6b: sprintf(t, "rtl "); break;
case 0x6c: sprintf(t, "jmp ($%0.4x) [$%0.6x]", op16, decode(OPTYPE_IADDR_PC, op16)); break;
case 0x6d: sprintf(t, "adc $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x6e: sprintf(t, "ror $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x6f: sprintf(t, "adc $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x70: sprintf(t, "bvs $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x71: sprintf(t, "adc ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x72: sprintf(t, "adc ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x73: sprintf(t, "adc ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x74: sprintf(t, "stz $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x75: sprintf(t, "adc $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x76: sprintf(t, "ror $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x77: sprintf(t, "adc [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x78: sprintf(t, "sei "); break;
case 0x79: sprintf(t, "adc $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x7a: sprintf(t, "ply "); break;
case 0x7b: sprintf(t, "tdc "); break;
case 0x7c: sprintf(t, "jmp ($%0.4x,x) [$%0.6x]", op16, decode(OPTYPE_IADDRX, op16)); break;
case 0x7d: sprintf(t, "adc $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x7e: sprintf(t, "ror $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x7f: sprintf(t, "adc $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x80: sprintf(t, "bra $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x81: sprintf(t, "sta ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x82: sprintf(t, "brl $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELW, op16)), decode(OPTYPE_RELW, op16)); break;
case 0x83: sprintf(t, "sta $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x84: sprintf(t, "sty $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x85: sprintf(t, "sta $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x86: sprintf(t, "stx $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x87: sprintf(t, "sta [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x88: sprintf(t, "dey "); break;
case 0x89: if(a8)sprintf(t, "bit #$%0.2x ", op8);
else sprintf(t, "bit #$%0.4x ", op16); break;
case 0x8a: sprintf(t, "txa "); break;
case 0x8b: sprintf(t, "phb "); break;
case 0x8c: sprintf(t, "sty $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8d: sprintf(t, "sta $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8e: sprintf(t, "stx $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8f: sprintf(t, "sta $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x90: sprintf(t, "bcc $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x91: sprintf(t, "sta ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x92: sprintf(t, "sta ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x93: sprintf(t, "sta ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x94: sprintf(t, "sty $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x95: sprintf(t, "sta $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x96: sprintf(t, "stx $%0.2x,y [$%0.6x]", op8, decode(OPTYPE_DPY, op8)); break;
case 0x97: sprintf(t, "sta [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x98: sprintf(t, "tya "); break;
case 0x99: sprintf(t, "sta $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x9a: sprintf(t, "txs "); break;
case 0x9b: sprintf(t, "txy "); break;
case 0x9c: sprintf(t, "stz $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x9d: sprintf(t, "sta $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x9e: sprintf(t, "stz $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x9f: sprintf(t, "sta $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xa0: if(x8)sprintf(t, "ldy #$%0.2x ", op8);
else sprintf(t, "ldy #$%0.4x ", op16); break;
case 0xa1: sprintf(t, "lda ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xa2: if(x8)sprintf(t, "ldx #$%0.2x ", op8);
else sprintf(t, "ldx #$%0.4x ", op16); break;
case 0xa3: sprintf(t, "lda $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xa4: sprintf(t, "ldy $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa5: sprintf(t, "lda $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa6: sprintf(t, "ldx $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa7: sprintf(t, "lda [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xa8: sprintf(t, "tay "); break;
case 0xa9: if(a8)sprintf(t, "lda #$%0.2x ", op8);
else sprintf(t, "lda #$%0.4x ", op16); break;
case 0xaa: sprintf(t, "tax "); break;
case 0xab: sprintf(t, "plb "); break;
case 0xac: sprintf(t, "ldy $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xad: sprintf(t, "lda $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xae: sprintf(t, "ldx $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xaf: sprintf(t, "lda $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xb0: sprintf(t, "bcs $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xb1: sprintf(t, "lda ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xb2: sprintf(t, "lda ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xb3: sprintf(t, "lda ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xb4: sprintf(t, "ldy $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xb5: sprintf(t, "lda $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xb6: sprintf(t, "ldx $%0.2x,y [$%0.6x]", op8, decode(OPTYPE_DPY, op8)); break;
case 0xb7: sprintf(t, "lda [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xb8: sprintf(t, "clv "); break;
case 0xb9: sprintf(t, "lda $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xba: sprintf(t, "tsx "); break;
case 0xbb: sprintf(t, "tyx "); break;
case 0xbc: sprintf(t, "ldy $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xbd: sprintf(t, "lda $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xbe: sprintf(t, "ldx $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xbf: sprintf(t, "lda $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xc0: if(x8)sprintf(t, "cpy #$%0.2x ", op8);
else sprintf(t, "cpy #$%0.4x ", op16); break;
case 0xc1: sprintf(t, "cmp ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xc2: sprintf(t, "rep #$%0.2x ", op8); break;
case 0xc3: sprintf(t, "cmp $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xc4: sprintf(t, "cpy $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc5: sprintf(t, "cmp $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc6: sprintf(t, "dec $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc7: sprintf(t, "cmp [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xc8: sprintf(t, "iny "); break;
case 0xc9: if(a8)sprintf(t, "cmp #$%0.2x ", op8);
else sprintf(t, "cmp #$%0.4x ", op16); break;
case 0xca: sprintf(t, "dex "); break;
case 0xcb: sprintf(t, "wai "); break;
case 0xcc: sprintf(t, "cpy $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xcd: sprintf(t, "cmp $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xce: sprintf(t, "dec $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xcf: sprintf(t, "cmp $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xd0: sprintf(t, "bne $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xd1: sprintf(t, "cmp ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xd2: sprintf(t, "cmp ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xd3: sprintf(t, "cmp ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xd4: sprintf(t, "pei ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xd5: sprintf(t, "cmp $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xd6: sprintf(t, "dec $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xd7: sprintf(t, "cmp [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xd8: sprintf(t, "cld "); break;
case 0xd9: sprintf(t, "cmp $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xda: sprintf(t, "phx "); break;
case 0xdb: sprintf(t, "stp "); break;
case 0xdc: sprintf(t, "jmp [$%0.4x] [$%0.6x]", op16, decode(OPTYPE_ILADDR, op16)); break;
case 0xdd: sprintf(t, "cmp $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xde: sprintf(t, "dec $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xdf: sprintf(t, "cmp $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xe0: if(x8)sprintf(t, "cpx #$%0.2x ", op8);
else sprintf(t, "cpx #$%0.4x ", op16); break;
case 0xe1: sprintf(t, "sbc ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xe2: sprintf(t, "sep #$%0.2x ", op8); break;
case 0xe3: sprintf(t, "sbc $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xe4: sprintf(t, "cpx $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe5: sprintf(t, "sbc $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe6: sprintf(t, "inc $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe7: sprintf(t, "sbc [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xe8: sprintf(t, "inx "); break;
case 0xe9: if(a8)sprintf(t, "sbc #$%0.2x ", op8);
else sprintf(t, "sbc #$%0.4x ", op16); break;
case 0xea: sprintf(t, "nop "); break;
case 0xeb: sprintf(t, "xba "); break;
case 0xec: sprintf(t, "cpx $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xed: sprintf(t, "sbc $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xee: sprintf(t, "inc $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xef: sprintf(t, "sbc $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xf0: sprintf(t, "beq $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xf1: sprintf(t, "sbc ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xf2: sprintf(t, "sbc ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xf3: sprintf(t, "sbc ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xf4: sprintf(t, "pea $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xf5: sprintf(t, "sbc $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xf6: sprintf(t, "inc $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xf7: sprintf(t, "sbc [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xf8: sprintf(t, "sed "); break;
case 0xf9: sprintf(t, "sbc $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xfa: sprintf(t, "plx "); break;
case 0xfb: sprintf(t, "xce "); break;
case 0xfc: sprintf(t, "jsr ($%0.4x,x) [$%0.6x]", op16, decode(OPTYPE_IADDRX, op16)); break;
case 0xfd: sprintf(t, "sbc $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xfe: sprintf(t, "inc $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xff: sprintf(t, "sbc $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
}
#undef op8
#undef op16
#undef op24
#undef a8
#undef x8
strcat(s, t);
strcat(s, " ");
sprintf(t, "A:%0.4x X:%0.4x Y:%0.4x S:%0.4x D:%0.4x DB:%0.2x ",
regs.a.w, regs.x.w, regs.y.w, regs.s.w, regs.d, regs.db);
regs.a.w, regs.x.w, regs.y.w, regs.s.w, regs.d.w, regs.db);
strcat(s, t);
if(regs.e) {
sprintf(t, "%c%c%c%c%c%c%c%c",
(regs.p.n)?'N':'n', (regs.p.v)?'V':'v',
(regs.p.m)?'1':'0', (regs.p.x)?'B':'b',
(regs.p.d)?'D':'d', (regs.p.i)?'I':'i',
(regs.p.z)?'Z':'z', (regs.p.c)?'C':'c');
(regs.p.n) ? 'N' : 'n', (regs.p.v) ? 'V' : 'v',
(regs.p.m) ? '1' : '0', (regs.p.x) ? 'B' : 'b',
(regs.p.d) ? 'D' : 'd', (regs.p.i) ? 'I' : 'i',
(regs.p.z) ? 'Z' : 'z', (regs.p.c) ? 'C' : 'c');
} else {
sprintf(t, "%c%c%c%c%c%c%c%c",
(regs.p.n)?'N':'n', (regs.p.v)?'V':'v',
(regs.p.m)?'M':'m', (regs.p.x)?'X':'x',
(regs.p.d)?'D':'d', (regs.p.i)?'I':'i',
(regs.p.z)?'Z':'z', (regs.p.c)?'C':'c');
(regs.p.n) ? 'N' : 'n', (regs.p.v) ? 'V' : 'v',
(regs.p.m) ? 'M' : 'm', (regs.p.x) ? 'X' : 'x',
(regs.p.d) ? 'D' : 'd', (regs.p.i) ? 'I' : 'i',
(regs.p.z) ? 'Z' : 'z', (regs.p.c) ? 'C' : 'c');
}
strcat(s, t);
strcat(s, " ");
sprintf(t, "V:%3d H:%4d", vcounter(), 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
@@ -431,9 +463,13 @@ static uint8 op_len_tbl[256] = {
6,2,2,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0xen
2,2,2,2, 3,2,2,2, 1,3,1,1, 3,3,3,4 //0xfn
};
op = mem_bus->read(regs.pc.d);
if(in_opcode() == true) {
return 0;
}
op = dreadb(regs.pc.d);
len = op_len_tbl[op];
if(len == 5)return (regs.p.m)?2:3;
if(len == 6)return (regs.p.x)?2:3;
if(len == 5)return (regs.e || regs.p.m) ? 2 : 3;
if(len == 6)return (regs.e || regs.p.x) ? 2 : 3;
return len;
}

3
src/cpu/scpu/core/cc.bat Normal file
View File

@@ -0,0 +1,3 @@
cl /nologo /O2 scpugen.cpp
@pause
@del *.obj

View File

@@ -0,0 +1 @@
@del *.exe

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
src/cpu/scpu/core/core.h Normal file
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
src/cpu/scpu/core/op_misc.b Normal file
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);
}

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
src/cpu/scpu/core/op_pc.b Normal file
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
src/cpu/scpu/core/op_pc.cpp Normal file
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
src/cpu/scpu/core/op_read.b Normal file
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
src/cpu/scpu/core/op_rmw.b Normal file
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);
}

Some files were not shown because too many files have changed in this diff Show More