Compare commits

...

8 Commits
v016 ... v017

Author SHA1 Message Date
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
264 changed files with 20073 additions and 6248 deletions

BIN
cart.db Normal file

Binary file not shown.

View File

@@ -4,9 +4,10 @@ You are free to redistribute this software, and its source code; provided
there is no charge for the software, nor any charge for the medium used to
distribute the software. You are also free to use and modify the source code
as you desire for personal use only. No publically-released derivative works
of this source code are permitted without my permission, though I will likely
grant you permission if you ask me. You must also abide by the terms of any
additional source code licenses contained within this program.
of this program nor its source code are permitted without my permission,
though I will likely grant you permission if you ask me. You must also abide
by the terms of any additional source code licenses contained within this
program.
Simple DirectMedia Layer License:
---------------------------------
@@ -20,7 +21,15 @@ http://www.libsdl.org/
This library is distributed under the terms of the GNU LGPL:
http://www.gnu.org/copyleft/lesser.html
JMA License:
------------
JMA is licensed under the GNU GPL. I have received special exemption from
Nach to use this library in bsnes.
Licensing Exemptions:
---------------------
libco is public domain. You may obtain the latest version at:
http://byuu.org/
Richard Bannister has asked for and received my permission to distribute
a binary-only port of bsnes on the Mac OS X platform.

108
readme.txt Normal file
View File

@@ -0,0 +1,108 @@
bsnes
Version 0.017
Author: byuu
General
-------
bsnes is a Super Nintendo / Super Famicom emulator that began on
October 14th, 2004.
The latest version can be downloaded from:
http://byuu.org/
Please see license.txt for important licensing information.
Known Bug(s)
------------
Uniracers / Unirally
- 2-player mode sprite issues (mid-frame OAM writes not supported)
Known Limitations
-----------------
S-CPU
- Invalid DMA / HDMA transfers (eg WRAM<>WRAM) not fully emulated
- DMA / HDMA bus synchronization timing not supported
- Multiply / Divide register delays not implemented
S-SMP
- Cycle breakdown of opcodes is theoretical, but mostly correct
S-PPU
- Uses scanline-based renderer. This is very inaccurate, but very
few games rely on mid-scanline writes to function correctly
- Does not support FirstSprite+Y priority
- OAM / CGRAM accesses during active display not supported correctly
- RTO flags are not calculated on frames that are skipped when frameskipping
is enabled. This provides a major speedup, however it will cause in issues
in games that test these flags, eg the SNES Test Program Electronics Test.
Turning frameskipping off will allow RTO flag calculation on every frame
S-DSP
- Runs at 32khz. Hardware S-DSP likely runs at 1.024mhz to perform
multiple reads / writes per sample. Sound is still output at 32khz,
of course
Hardware Bugs
- CPUr1 HDMA crashing bug not emulated
- CPU<>APU communication bus conflicts not emulated
Unsupported Hardware
--------------------
SA-1
Coprocessor used in many popular games, including:
- Dragon Ball Z Hyper Dimension
- Kirby Super Star
- Kirby's Dreamland 3
- Marvelous
- SD Gundam G-NEXT
- Super Mario RPG
Super FX
Coprocessor used in many popular games, including:
- Doom
- Star Fox
- Star Fox 2 (unreleased beta)
- Super Mario World 2: Yoshi's Island
SPC7110
Coprocessor used only by the following games:
- Far East of Eden Zero
- Far East of Eden Zero: Shounen Jump no Shou
- Momotarou Densetsu Happy
- Super Power League 4
DSP-3
Coprocessor used only by SD Gundam GX
DSP-4
Coprocessor used only by Top Gear 3000
ST010 / ST011 / ST018
SETA coprocessors used by very few games
BS-X (Broadcast Satellite)
Add-on unit sold only in Japan that played specially-made games that
were downloaded via satellite
BS-X Flashcart
Flash cartridge used by BS-X, as well as some standalone games by
Asciisoft
Bandai Sufami Turbo
Special cartloader to play some Bandai games
Super Gameboy
Cartridge passthrough used for playing Gameboy games
Unsupported controllers
-----------------------
Mouse
Super Scope
Justifier
Multitap (4-port)
Multitap (5-port)

View File

@@ -3,12 +3,11 @@
class APU {
public:
APURegs regs;
uint8 spcram[65536];
static const uint8 iplrom[64];
enum {
FLAG_N = 0x80, FLAG_V = 0x40,
FLAG_P = 0x20, FLAG_B = 0x10,
FLAG_H = 0x08, FLAG_I = 0x04,
FLAG_Z = 0x02, FLAG_C = 0x01
FLAG_N = 0x80, FLAG_V = 0x40, FLAG_P = 0x20, FLAG_B = 0x10,
FLAG_H = 0x08, FLAG_I = 0x04, FLAG_Z = 0x02, FLAG_C = 0x01
};
virtual uint8 spcram_read (uint16 addr) = 0;
@@ -17,9 +16,10 @@ static const uint8 iplrom[64];
virtual uint8 port_read (uint8 port) = 0;
virtual void port_write(uint8 port, uint8 value) = 0;
virtual uint8 *get_spcram_handle() = 0;
virtual uint8 *get_spcram_handle() { return spcram; }
virtual void main() {}
virtual void run() = 0;
virtual uint32 cycles_executed() = 0;
virtual uint32 clocks_executed() = 0;
virtual void power() = 0;
virtual void reset() = 0;
@@ -28,6 +28,6 @@ static const uint8 iplrom[64];
void disassemble_opcode(char *output);
inline uint16 __relb(int8 offset, int op_len);
APU() {}
APU() { memset(spcram, 0, 65536); }
virtual ~APU() {}
};

View File

@@ -1,20 +1,18 @@
class APURegFlags {
private:
template <uint8 B> class bit {
template<uint mask> class bit {
public:
uint8 _b;
inline operator bool() { return (_b & B); }
inline bool operator = (bool i) { (i) ? _b |= B : _b &= ~B; return (_b & B); }
inline bool operator & (bool i) { if(i)_b &= ~B; return (_b & B); }
inline bool operator &= (bool i) { if(i)_b &= ~B; return (_b & B); }
inline bool operator | (bool i) { if(i)_b |= B; return (_b & B); }
inline bool operator |= (bool i) { if(i)_b |= B; return (_b & B); }
inline bool operator ^ (bool i) { if(i)_b ^= B; return (_b & B); }
inline bool operator ^= (bool i) { if(i)_b ^= B; return (_b & B); }
uint data;
inline operator bool() { return bool(data & mask); }
inline bool operator = (const bool i) { (i) ? data |= mask : data &= ~mask; return bool(data & mask); }
inline bool operator |= (const bool i) { if(i)data |= mask; return bool(data & mask); }
inline bool operator ^= (const bool i) { if(i)data ^= mask; return bool(data & mask); }
inline bool operator &= (const bool i) { if(i)data &= mask; return bool(data & mask); }
};
public:
union {
uint8 _b;
uint8 data;
bit<0x80> n;
bit<0x40> v;
bit<0x20> p;
@@ -25,12 +23,13 @@ union {
bit<0x01> c;
};
APURegFlags() { _b = 0; }
inline operator uint8() { return _b; }
inline unsigned operator = (uint8 i) { _b = i; return _b; }
inline unsigned operator &= (uint8 i) { _b &= i; return _b; }
inline unsigned operator |= (uint8 i) { _b |= i; return _b; }
inline unsigned operator ^= (uint8 i) { _b ^= i; return _b; }
inline operator unsigned() const { return data; }
inline unsigned operator = (const uint8 i) { data = i; return data; }
inline unsigned operator |= (const uint8 i) { data |= i; return data; }
inline unsigned operator ^= (const uint8 i) { data ^= i; return data; }
inline unsigned operator &= (const uint8 i) { data &= i; return data; }
APURegFlags() : data(0) {}
};
class APURegs {
@@ -38,11 +37,7 @@ public:
uint16 pc;
union {
uint16 ya;
#ifdef ARCH_LSB
struct { uint8 a, y; };
#else
struct { uint8 y, a; };
#endif
struct { uint8 order_lsb2(a, y); };
};
uint8 x, sp;
APURegFlags p;

View File

@@ -22,7 +22,7 @@ void bAPU::reset() {
regs.p = 0x02;
status.cycle_pos = 0;
status.cycles_executed = 0;
status.clocks_executed = 0;
//$f1
status.iplrom_enabled = true;
@@ -47,8 +47,6 @@ void bAPU::reset() {
bAPU::bAPU() {
init_op_table();
spcram = (uint8*)malloc(65536);
t0.cycle_frequency = 128; //1.024mhz / 8khz = 128
t1.cycle_frequency = 128; //1.024mhz / 8khz = 128
t2.cycle_frequency = 16; //1.024mhz / 64khz = 16
@@ -59,6 +57,4 @@ bAPU::bAPU() {
t2.target = 0;
}
bAPU::~bAPU() {
if(spcram)free(spcram);
}
bAPU::~bAPU() {}

View File

@@ -6,7 +6,7 @@ public:
struct {
uint8 cycle_pos, opcode;
uint32 cycles_executed;
uint32 clocks_executed;
//$f1
bool iplrom_enabled;

View File

@@ -1,8 +1 @@
@del *.exe
@del op.h
@del optable.cpp
@del op_mov.cpp
@del op_pc.cpp
@del op_read.cpp
@del op_rmw.cpp
@del op_misc.cpp

View File

@@ -2,13 +2,16 @@ mov_a_x(0x7d, a, x),
mov_a_y(0xdd, a, y),
mov_x_a(0x5d, x, a),
mov_y_a(0xfd, y, a),
mov_x_sp(0x9d, x, sp),
mov_sp_x(0xbd, sp, x) {
mov_x_sp(0x9d, x, sp) {
1:regs.$1 = regs.$2;
regs.p.n = !!(regs.$1 & 0x80);
regs.p.z = (regs.$1 == 0);
}
mov_sp_x(0xbd, sp, x) {
1:regs.$1 = regs.$2;
}
mov_a_const(0xe8, a),
mov_x_const(0xcd, x),
mov_y_const(0x8d, y) {

View File

@@ -57,8 +57,6 @@ void bAPU::op_mov_sp_x() {
switch(status.cycle_pos++) {
case 1: {
regs.sp = regs.x;
regs.p.n = !!(regs.sp & 0x80);
regs.p.z = (regs.sp == 0);
status.cycle_pos = 0;
} break;
}

View File

@@ -189,11 +189,3 @@ void bAPU::stack_write(uint8 value) {
spcram_write(0x0100 | regs.sp, value);
regs.sp--;
}
uint8 *bAPU::get_spcram_handle() {
if(!spcram) {
alert("bAPU::get_spcram_handle() -- spcram uninitialized");
}
return spcram;
}

View File

@@ -1,12 +1,9 @@
enum { OPMODE_ADDR, OPMODE_DP };
uint8 *spcram;
inline uint8 spcram_read (uint16 addr);
inline void spcram_write(uint16 addr, uint8 value);
inline uint8 port_read (uint8 port);
inline void port_write(uint8 port, uint8 value);
inline uint8 *get_spcram_handle();
inline uint8 op_read();
inline uint8 op_read (uint8 mode, uint16 addr);
inline void op_write(uint8 mode, uint16 addr, uint8 value);

View File

@@ -1,14 +1,14 @@
void bAPU::add_cycles(int cycles) {
status.cycles_executed += cycles;
status.clocks_executed += cycles;
t0.add_cycles(cycles);
t1.add_cycles(cycles);
t2.add_cycles(cycles);
}
uint32 bAPU::cycles_executed() {
uint32 r = status.cycles_executed;
status.cycles_executed = 0;
uint32 bAPU::clocks_executed() {
uint32 r = status.clocks_executed;
status.clocks_executed = 0;
return (r << 4) + (r << 3);
}

View File

@@ -6,4 +6,4 @@ bool enabled;
inline void add_cycles(int cycles);
} t0, t1, t2;
inline void add_cycles(int cycles);
inline uint32 cycles_executed();
inline uint32 clocks_executed();

3
src/apu/sapu/core/cc.bat Normal file
View File

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

View File

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

View File

@@ -0,0 +1,21 @@
#include "opfn.cpp"
void sAPU::main() {
for(;;) {
status.in_opcode = true;
switch(op_readpc()) {
#include "op_mov.cpp"
#include "op_pc.cpp"
#include "op_read.cpp"
#include "op_rmw.cpp"
#include "op_misc.cpp"
}
status.in_opcode = false;
#ifdef FAVOR_SPEED
co_return();
#endif
}
}

24
src/apu/sapu/core/core.h Normal file
View File

@@ -0,0 +1,24 @@
//void (sAPU::*optbl[256])();
uint16 dp, sp, rd, wr, bit, ya;
bool in_opcode() { return status.in_opcode; }
uint8 op_adc (uint8 x, uint8 y);
uint16 op_addw(uint16 x, uint16 y);
uint8 op_and (uint8 x, uint8 y);
uint8 op_cmp (uint8 x, uint8 y);
uint16 op_cmpw(uint16 x, uint16 y);
uint8 op_eor (uint8 x, uint8 y);
uint8 op_inc (uint8 x);
uint16 op_incw(uint16 x);
uint8 op_dec (uint8 x);
uint16 op_decw(uint16 x);
uint8 op_or (uint8 x, uint8 y);
uint8 op_sbc (uint8 x, uint8 y);
uint16 op_subw(uint16 x, uint16 y);
uint8 op_asl (uint8 x);
uint8 op_lsr (uint8 x);
uint8 op_rol (uint8 x);
uint8 op_ror (uint8 x);
//#include "op.h"

175
src/apu/sapu/core/op_misc.b Normal file
View File

@@ -0,0 +1,175 @@
nop(0x00) {
1:op_io();
}
sleep(0xef),
stop(0xff) {
1:op_io();
2:op_io();
regs.pc--;
}
xcn(0x9f) {
1:op_io();
2:op_io();
3:op_io();
4:op_io();
regs.a = (regs.a >> 4) | (regs.a << 4);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
daa(0xdf) {
1:op_io();
2:op_io();
if(regs.p.c || (regs.a) > 0x99) {
regs.a += 0x60;
regs.p.c = 1;
}
if(regs.p.h || (regs.a & 15) > 0x09) {
regs.a += 0x06;
}
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
das(0xbe) {
1:op_io();
2:op_io();
if(!regs.p.c || (regs.a) > 0x99) {
regs.a -= 0x60;
regs.p.c = 0;
}
if(!regs.p.h || (regs.a & 15) > 0x09) {
regs.a -= 0x06;
}
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
clrc(0x60, regs.p.c = 0),
clrp(0x20, regs.p.p = 0),
setc(0x80, regs.p.c = 1),
setp(0x40, regs.p.p = 1) {
1:op_io();
$1;
}
clrv(0xe0) {
1:op_io();
regs.p.v = 0;
regs.p.h = 0;
}
notc(0xed) {
1:op_io();
2:op_io();
regs.p.c ^= 1;
}
ei(0xa0, 1),
di(0xc0, 0) {
1:op_io();
2:op_io();
regs.p.i = $1;
}
set0_dp(0x02, rd |= 0x01),
clr0_dp(0x12, rd &= ~0x01),
set1_dp(0x22, rd |= 0x02),
clr1_dp(0x32, rd &= ~0x02),
set2_dp(0x42, rd |= 0x04),
clr2_dp(0x52, rd &= ~0x04),
set3_dp(0x62, rd |= 0x08),
clr3_dp(0x72, rd &= ~0x08),
set4_dp(0x82, rd |= 0x10),
clr4_dp(0x92, rd &= ~0x10),
set5_dp(0xa2, rd |= 0x20),
clr5_dp(0xb2, rd &= ~0x20),
set6_dp(0xc2, rd |= 0x40),
clr6_dp(0xd2, rd &= ~0x40),
set7_dp(0xe2, rd |= 0x80),
clr7_dp(0xf2, rd &= ~0x80) {
1:dp = op_readpc();
2:rd = op_readdp(dp);
3:$1;
op_writedp(dp, rd);
}
tset_addr_a(0x0e, |=),
tclr_addr_a(0x4e, &=~) {
1:dp = op_readpc();
2:dp |= op_readpc() << 8;
3:rd = op_readaddr(dp);
4:op_io();
regs.p.n = !!((rd & regs.a) & 0x80);
regs.p.z = ((rd & regs.a) == 0);
rd $1 regs.a;
5:op_writeaddr(dp, rd);
}
push_a(0x2d, a),
push_x(0x4d, x),
push_y(0x6d, y),
push_p(0x0d, p) {
1:op_io();
2:op_io();
3:op_writestack(regs.$1);
}
pop_a(0xae, a),
pop_x(0xce, x),
pop_y(0xee, y),
pop_p(0x8e, p) {
1:op_io();
2:op_io();
3:regs.$1 = op_readstack();
}
mul_ya(0xcf) {
1:op_io();
2:op_io();
3:op_io();
4:op_io();
5:op_io();
6:op_io();
7:op_io();
8:op_io();
ya = regs.y * regs.a;
regs.a = ya;
regs.y = ya >> 8;
//result is set based on y (high-byte) only
regs.p.n = !!(regs.y & 0x80);
regs.p.z = (regs.y == 0);
}
div_ya_x(0x9e) {
1:op_io();
2:op_io();
3:op_io();
4:op_io();
5:op_io();
6:op_io();
7:op_io();
8:op_io();
9:op_io();
10:op_io();
11:op_io();
ya = regs.ya;
//overflow set if quotient >= 256
regs.p.v = !!(regs.y >= regs.x);
regs.p.h = !!((regs.y & 15) >= (regs.x & 15));
if(regs.y < (regs.x << 1)) {
//if quotient is <= 511 (will fit into 9-bit result)
regs.a = ya / regs.x;
regs.y = ya % regs.x;
} else {
//otherwise, the quotient won't fit into regs.p.v + regs.a
//this emulates the odd behavior of the SPC700 in this case
regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x);
regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x);
}
//result is set based on a (quotient) only
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
}

View File

@@ -0,0 +1,370 @@
//nop
case 0x00: {
op_io();
} break;
//sleep
case 0xef: {
op_io();
op_io();
regs.pc--;
} break;
//stop
case 0xff: {
op_io();
op_io();
regs.pc--;
} break;
//xcn
case 0x9f: {
op_io();
op_io();
op_io();
op_io();
regs.a = (regs.a >> 4) | (regs.a << 4);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
} break;
//daa
case 0xdf: {
op_io();
op_io();
if(regs.p.c || (regs.a) > 0x99) {
regs.a += 0x60;
regs.p.c = 1;
}
if(regs.p.h || (regs.a & 15) > 0x09) {
regs.a += 0x06;
}
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
} break;
//das
case 0xbe: {
op_io();
op_io();
if(!regs.p.c || (regs.a) > 0x99) {
regs.a -= 0x60;
regs.p.c = 0;
}
if(!regs.p.h || (regs.a & 15) > 0x09) {
regs.a -= 0x06;
}
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
} break;
//clrc
case 0x60: {
op_io();
regs.p.c = 0;
} break;
//clrp
case 0x20: {
op_io();
regs.p.p = 0;
} break;
//setc
case 0x80: {
op_io();
regs.p.c = 1;
} break;
//setp
case 0x40: {
op_io();
regs.p.p = 1;
} break;
//clrv
case 0xe0: {
op_io();
regs.p.v = 0;
regs.p.h = 0;
} break;
//notc
case 0xed: {
op_io();
op_io();
regs.p.c ^= 1;
} break;
//ei
case 0xa0: {
op_io();
op_io();
regs.p.i = 1;
} break;
//di
case 0xc0: {
op_io();
op_io();
regs.p.i = 0;
} break;
//set0_dp
case 0x02: {
dp = op_readpc();
rd = op_readdp(dp);
rd |= 0x01;
op_writedp(dp, rd);
} break;
//clr0_dp
case 0x12: {
dp = op_readpc();
rd = op_readdp(dp);
rd &= ~0x01;
op_writedp(dp, rd);
} break;
//set1_dp
case 0x22: {
dp = op_readpc();
rd = op_readdp(dp);
rd |= 0x02;
op_writedp(dp, rd);
} break;
//clr1_dp
case 0x32: {
dp = op_readpc();
rd = op_readdp(dp);
rd &= ~0x02;
op_writedp(dp, rd);
} break;
//set2_dp
case 0x42: {
dp = op_readpc();
rd = op_readdp(dp);
rd |= 0x04;
op_writedp(dp, rd);
} break;
//clr2_dp
case 0x52: {
dp = op_readpc();
rd = op_readdp(dp);
rd &= ~0x04;
op_writedp(dp, rd);
} break;
//set3_dp
case 0x62: {
dp = op_readpc();
rd = op_readdp(dp);
rd |= 0x08;
op_writedp(dp, rd);
} break;
//clr3_dp
case 0x72: {
dp = op_readpc();
rd = op_readdp(dp);
rd &= ~0x08;
op_writedp(dp, rd);
} break;
//set4_dp
case 0x82: {
dp = op_readpc();
rd = op_readdp(dp);
rd |= 0x10;
op_writedp(dp, rd);
} break;
//clr4_dp
case 0x92: {
dp = op_readpc();
rd = op_readdp(dp);
rd &= ~0x10;
op_writedp(dp, rd);
} break;
//set5_dp
case 0xa2: {
dp = op_readpc();
rd = op_readdp(dp);
rd |= 0x20;
op_writedp(dp, rd);
} break;
//clr5_dp
case 0xb2: {
dp = op_readpc();
rd = op_readdp(dp);
rd &= ~0x20;
op_writedp(dp, rd);
} break;
//set6_dp
case 0xc2: {
dp = op_readpc();
rd = op_readdp(dp);
rd |= 0x40;
op_writedp(dp, rd);
} break;
//clr6_dp
case 0xd2: {
dp = op_readpc();
rd = op_readdp(dp);
rd &= ~0x40;
op_writedp(dp, rd);
} break;
//set7_dp
case 0xe2: {
dp = op_readpc();
rd = op_readdp(dp);
rd |= 0x80;
op_writedp(dp, rd);
} break;
//clr7_dp
case 0xf2: {
dp = op_readpc();
rd = op_readdp(dp);
rd &= ~0x80;
op_writedp(dp, rd);
} break;
//tset_addr_a
case 0x0e: {
dp = op_readpc();
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
op_io();
regs.p.n = !!((rd & regs.a) & 0x80);
regs.p.z = ((rd & regs.a) == 0);
rd |= regs.a;
op_writeaddr(dp, rd);
} break;
//tclr_addr_a
case 0x4e: {
dp = op_readpc();
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
op_io();
regs.p.n = !!((rd & regs.a) & 0x80);
regs.p.z = ((rd & regs.a) == 0);
rd &=~ regs.a;
op_writeaddr(dp, rd);
} break;
//push_a
case 0x2d: {
op_io();
op_io();
op_writestack(regs.a);
} break;
//push_x
case 0x4d: {
op_io();
op_io();
op_writestack(regs.x);
} break;
//push_y
case 0x6d: {
op_io();
op_io();
op_writestack(regs.y);
} break;
//push_p
case 0x0d: {
op_io();
op_io();
op_writestack(regs.p);
} break;
//pop_a
case 0xae: {
op_io();
op_io();
regs.a = op_readstack();
} break;
//pop_x
case 0xce: {
op_io();
op_io();
regs.x = op_readstack();
} break;
//pop_y
case 0xee: {
op_io();
op_io();
regs.y = op_readstack();
} break;
//pop_p
case 0x8e: {
op_io();
op_io();
regs.p = op_readstack();
} break;
//mul_ya
case 0xcf: {
op_io();
op_io();
op_io();
op_io();
op_io();
op_io();
op_io();
op_io();
ya = regs.y * regs.a;
regs.a = ya;
regs.y = ya >> 8;
//result is set based on y (high-byte) only
regs.p.n = !!(regs.y & 0x80);
regs.p.z = (regs.y == 0);
} break;
//div_ya_x
case 0x9e: {
op_io();
op_io();
op_io();
op_io();
op_io();
op_io();
op_io();
op_io();
op_io();
op_io();
op_io();
ya = regs.ya;
//overflow set if quotient >= 256
regs.p.v = !!(regs.y >= regs.x);
regs.p.h = !!((regs.y & 15) >= (regs.x & 15));
if(regs.y < (regs.x << 1)) {
//if quotient is <= 511 (will fit into 9-bit result)
regs.a = ya / regs.x;
regs.y = ya % regs.x;
} else {
//otherwise, the quotient won't fit into regs.p.v + regs.a
//this emulates the odd behavior of the SPC700 in this case
regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x);
regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x);
}
//result is set based on a (quotient) only
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
} break;

212
src/apu/sapu/core/op_mov.b Normal file
View File

@@ -0,0 +1,212 @@
mov_a_x(0x7d, a, x),
mov_a_y(0xdd, a, y),
mov_x_a(0x5d, x, a),
mov_y_a(0xfd, y, a),
mov_x_sp(0x9d, x, sp) {
1:op_io();
regs.$1 = regs.$2;
regs.p.n = !!(regs.$1 & 0x80);
regs.p.z = (regs.$1 == 0);
}
mov_sp_x(0xbd, sp, x) {
1:op_io();
regs.$1 = regs.$2;
}
mov_a_const(0xe8, a),
mov_x_const(0xcd, x),
mov_y_const(0x8d, y) {
1:regs.$1 = op_readpc();
regs.p.n = !!(regs.$1 & 0x80);
regs.p.z = (regs.$1 == 0);
}
mov_a_ix(0xe6) {
1:op_io();
2:regs.a = op_readdp(regs.x);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
mov_a_ixinc(0xbf) {
1:op_io();
2:op_io();
3:regs.a = op_readdp(regs.x++);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
mov_a_dp(0xe4, a),
mov_x_dp(0xf8, x),
mov_y_dp(0xeb, y) {
1:sp = op_readpc();
2:regs.$1 = op_readdp(sp);
regs.p.n = !!(regs.$1 & 0x80);
regs.p.z = (regs.$1 == 0);
}
mov_a_dpx(0xf4, a, x),
mov_x_dpy(0xf9, x, y),
mov_y_dpx(0xfb, y, x) {
1:sp = op_readpc();
2:op_io();
3:regs.$1 = op_readdp(sp + regs.$2);
regs.p.n = !!(regs.$1 & 0x80);
regs.p.z = (regs.$1 == 0);
}
mov_a_addr(0xe5, a),
mov_x_addr(0xe9, x),
mov_y_addr(0xec, y) {
1:sp = op_readpc();
2:sp |= op_readpc() << 8;
3:regs.$1 = op_readaddr(sp);
regs.p.n = !!(regs.$1 & 0x80);
regs.p.z = (regs.$1 == 0);
}
mov_a_addrx(0xf5, x),
mov_a_addry(0xf6, y) {
1:sp = op_readpc();
2:sp |= op_readpc() << 8;
3:op_io();
4:regs.a = op_readaddr(sp + regs.$1);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
mov_a_idpx(0xe7) {
1:dp = op_readpc() + regs.x;
2:op_io();
3:sp = op_readdp(dp);
4:sp |= op_readdp(dp + 1) << 8;
5:regs.a = op_readaddr(sp);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
mov_a_idpy(0xf7) {
1:dp = op_readpc();
2:op_io();
3:sp = op_readdp(dp);
4:sp |= op_readdp(dp + 1) << 8;
5:regs.a = op_readaddr(sp + regs.y);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
mov_dp_dp(0xfa) {
1:sp = op_readpc();
2:dp = op_readpc();
3:rd = op_readdp(sp);
4:op_writedp(dp, rd);
}
mov_dp_const(0x8f) {
1:rd = op_readpc();
2:dp = op_readpc();
3:op_io();
4:op_writedp(dp, rd);
}
mov_ix_a(0xc6) {
1:op_io();
2:op_io();
3:op_writedp(regs.x, regs.a);
}
mov_ixinc_a(0xaf) {
1:op_io();
2:op_io();
3:op_writedp(regs.x++, regs.a);
}
mov_dp_a(0xc4, a),
mov_dp_x(0xd8, x),
mov_dp_y(0xcb, y) {
1:dp = op_readpc();
2:op_io();
3:op_writedp(dp, regs.$1);
}
mov_dpx_a(0xd4, x, a),
mov_dpy_x(0xd9, y, x),
mov_dpx_y(0xdb, x, y) {
1:dp = op_readpc();
2:op_io();
3:op_io();
4:op_writedp(dp + regs.$1, regs.$2);
}
mov_addr_a(0xc5, a),
mov_addr_x(0xc9, x),
mov_addr_y(0xcc, y) {
1:dp = op_readpc();
2:dp |= op_readpc() << 8;
3:op_io();
4:op_writeaddr(dp, regs.$1);
}
mov_addrx_a(0xd5, x),
mov_addry_a(0xd6, y) {
1:dp = op_readpc();
2:dp |= op_readpc() << 8;
3:op_io();
4:op_io();
5:op_writeaddr(dp + regs.$1, regs.a);
}
mov_idpx_a(0xc7) {
1:sp = op_readpc() + regs.x;
2:op_io();
3:dp = op_readdp(sp);
4:dp |= op_readdp(sp + 1) << 8;
5:op_io();
6:op_writeaddr(dp, regs.a);
}
mov_idpy_a(0xd7) {
1:sp = op_readpc();
2:op_io();
3:dp = op_readdp(sp);
4:dp |= op_readdp(sp + 1) << 8;
5:op_io();
6:op_writeaddr(dp + regs.y, regs.a);
}
movw_ya_dp(0xba) {
1:sp = op_readpc();
2:op_io();
3:regs.a = op_readdp(sp);
4:regs.y = op_readdp(sp + 1);
regs.p.n = !!(regs.ya & 0x8000);
regs.p.z = (regs.ya == 0);
}
movw_dp_ya(0xda) {
1:dp = op_readpc();
2:op_io();
3:op_writedp(dp, regs.a);
4:op_writedp(dp + 1, regs.y);
}
mov1_c_bit(0xaa) {
1:sp = op_readpc();
2:sp |= op_readpc() << 8;
3:bit = sp >> 13;
sp &= 0x1fff;
rd = op_readaddr(sp);
regs.p.c = !!(rd & (1 << bit));
}
mov1_bit_c(0xca) {
1:dp = op_readpc();
2:dp |= op_readpc() << 8;
3:bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
if(regs.p.c)rd |= (1 << bit);
else rd &= ~(1 << bit);
4:op_writeaddr(dp, rd);
}

View File

@@ -0,0 +1,381 @@
//mov_a_x
case 0x7d: {
op_io();
regs.a = regs.x;
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
} break;
//mov_a_y
case 0xdd: {
op_io();
regs.a = regs.y;
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
} break;
//mov_x_a
case 0x5d: {
op_io();
regs.x = regs.a;
regs.p.n = !!(regs.x & 0x80);
regs.p.z = (regs.x == 0);
} break;
//mov_y_a
case 0xfd: {
op_io();
regs.y = regs.a;
regs.p.n = !!(regs.y & 0x80);
regs.p.z = (regs.y == 0);
} break;
//mov_x_sp
case 0x9d: {
op_io();
regs.x = regs.sp;
regs.p.n = !!(regs.x & 0x80);
regs.p.z = (regs.x == 0);
} break;
//mov_sp_x
case 0xbd: {
op_io();
regs.sp = regs.x;
} break;
//mov_a_const
case 0xe8: {
regs.a = op_readpc();
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
} break;
//mov_x_const
case 0xcd: {
regs.x = op_readpc();
regs.p.n = !!(regs.x & 0x80);
regs.p.z = (regs.x == 0);
} break;
//mov_y_const
case 0x8d: {
regs.y = op_readpc();
regs.p.n = !!(regs.y & 0x80);
regs.p.z = (regs.y == 0);
} break;
//mov_a_ix
case 0xe6: {
op_io();
regs.a = op_readdp(regs.x);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
} break;
//mov_a_ixinc
case 0xbf: {
op_io();
op_io();
regs.a = op_readdp(regs.x++);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
} break;
//mov_a_dp
case 0xe4: {
sp = op_readpc();
regs.a = op_readdp(sp);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
} break;
//mov_x_dp
case 0xf8: {
sp = op_readpc();
regs.x = op_readdp(sp);
regs.p.n = !!(regs.x & 0x80);
regs.p.z = (regs.x == 0);
} break;
//mov_y_dp
case 0xeb: {
sp = op_readpc();
regs.y = op_readdp(sp);
regs.p.n = !!(regs.y & 0x80);
regs.p.z = (regs.y == 0);
} break;
//mov_a_dpx
case 0xf4: {
sp = op_readpc();
op_io();
regs.a = op_readdp(sp + regs.x);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
} break;
//mov_x_dpy
case 0xf9: {
sp = op_readpc();
op_io();
regs.x = op_readdp(sp + regs.y);
regs.p.n = !!(regs.x & 0x80);
regs.p.z = (regs.x == 0);
} break;
//mov_y_dpx
case 0xfb: {
sp = op_readpc();
op_io();
regs.y = op_readdp(sp + regs.x);
regs.p.n = !!(regs.y & 0x80);
regs.p.z = (regs.y == 0);
} break;
//mov_a_addr
case 0xe5: {
sp = op_readpc();
sp |= op_readpc() << 8;
regs.a = op_readaddr(sp);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
} break;
//mov_x_addr
case 0xe9: {
sp = op_readpc();
sp |= op_readpc() << 8;
regs.x = op_readaddr(sp);
regs.p.n = !!(regs.x & 0x80);
regs.p.z = (regs.x == 0);
} break;
//mov_y_addr
case 0xec: {
sp = op_readpc();
sp |= op_readpc() << 8;
regs.y = op_readaddr(sp);
regs.p.n = !!(regs.y & 0x80);
regs.p.z = (regs.y == 0);
} break;
//mov_a_addrx
case 0xf5: {
sp = op_readpc();
sp |= op_readpc() << 8;
op_io();
regs.a = op_readaddr(sp + regs.x);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
} break;
//mov_a_addry
case 0xf6: {
sp = op_readpc();
sp |= op_readpc() << 8;
op_io();
regs.a = op_readaddr(sp + regs.y);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
} break;
//mov_a_idpx
case 0xe7: {
dp = op_readpc() + regs.x;
op_io();
sp = op_readdp(dp);
sp |= op_readdp(dp + 1) << 8;
regs.a = op_readaddr(sp);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
} break;
//mov_a_idpy
case 0xf7: {
dp = op_readpc();
op_io();
sp = op_readdp(dp);
sp |= op_readdp(dp + 1) << 8;
regs.a = op_readaddr(sp + regs.y);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
} break;
//mov_dp_dp
case 0xfa: {
sp = op_readpc();
dp = op_readpc();
rd = op_readdp(sp);
op_writedp(dp, rd);
} break;
//mov_dp_const
case 0x8f: {
rd = op_readpc();
dp = op_readpc();
op_io();
op_writedp(dp, rd);
} break;
//mov_ix_a
case 0xc6: {
op_io();
op_io();
op_writedp(regs.x, regs.a);
} break;
//mov_ixinc_a
case 0xaf: {
op_io();
op_io();
op_writedp(regs.x++, regs.a);
} break;
//mov_dp_a
case 0xc4: {
dp = op_readpc();
op_io();
op_writedp(dp, regs.a);
} break;
//mov_dp_x
case 0xd8: {
dp = op_readpc();
op_io();
op_writedp(dp, regs.x);
} break;
//mov_dp_y
case 0xcb: {
dp = op_readpc();
op_io();
op_writedp(dp, regs.y);
} break;
//mov_dpx_a
case 0xd4: {
dp = op_readpc();
op_io();
op_io();
op_writedp(dp + regs.x, regs.a);
} break;
//mov_dpy_x
case 0xd9: {
dp = op_readpc();
op_io();
op_io();
op_writedp(dp + regs.y, regs.x);
} break;
//mov_dpx_y
case 0xdb: {
dp = op_readpc();
op_io();
op_io();
op_writedp(dp + regs.x, regs.y);
} break;
//mov_addr_a
case 0xc5: {
dp = op_readpc();
dp |= op_readpc() << 8;
op_io();
op_writeaddr(dp, regs.a);
} break;
//mov_addr_x
case 0xc9: {
dp = op_readpc();
dp |= op_readpc() << 8;
op_io();
op_writeaddr(dp, regs.x);
} break;
//mov_addr_y
case 0xcc: {
dp = op_readpc();
dp |= op_readpc() << 8;
op_io();
op_writeaddr(dp, regs.y);
} break;
//mov_addrx_a
case 0xd5: {
dp = op_readpc();
dp |= op_readpc() << 8;
op_io();
op_io();
op_writeaddr(dp + regs.x, regs.a);
} break;
//mov_addry_a
case 0xd6: {
dp = op_readpc();
dp |= op_readpc() << 8;
op_io();
op_io();
op_writeaddr(dp + regs.y, regs.a);
} break;
//mov_idpx_a
case 0xc7: {
sp = op_readpc() + regs.x;
op_io();
dp = op_readdp(sp);
dp |= op_readdp(sp + 1) << 8;
op_io();
op_writeaddr(dp, regs.a);
} break;
//mov_idpy_a
case 0xd7: {
sp = op_readpc();
op_io();
dp = op_readdp(sp);
dp |= op_readdp(sp + 1) << 8;
op_io();
op_writeaddr(dp + regs.y, regs.a);
} break;
//movw_ya_dp
case 0xba: {
sp = op_readpc();
op_io();
regs.a = op_readdp(sp);
regs.y = op_readdp(sp + 1);
regs.p.n = !!(regs.ya & 0x8000);
regs.p.z = (regs.ya == 0);
} break;
//movw_dp_ya
case 0xda: {
dp = op_readpc();
op_io();
op_writedp(dp, regs.a);
op_writedp(dp + 1, regs.y);
} break;
//mov1_c_bit
case 0xaa: {
sp = op_readpc();
sp |= op_readpc() << 8;
bit = sp >> 13;
sp &= 0x1fff;
rd = op_readaddr(sp);
regs.p.c = !!(rd & (1 << bit));
} break;
//mov1_bit_c
case 0xca: {
dp = op_readpc();
dp |= op_readpc() << 8;
bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
if(regs.p.c)rd |= (1 << bit);
else rd &= ~(1 << bit);
op_writeaddr(dp, rd);
} break;

180
src/apu/sapu/core/op_pc.b Normal file
View File

@@ -0,0 +1,180 @@
bra(0x2f, 0),
beq(0xf0, !regs.p.z),
bne(0xd0, regs.p.z),
bcs(0xb0, !regs.p.c),
bcc(0x90, regs.p.c),
bvs(0x70, !regs.p.v),
bvc(0x50, regs.p.v),
bmi(0x30, !regs.p.n),
bpl(0x10, regs.p.n) {
1:rd = op_readpc();
if($1)end;
2:op_io();
3:op_io();
regs.pc += (int8)rd;
}
bbs0(0x03, 0x01, !=),
bbc0(0x13, 0x01, ==),
bbs1(0x23, 0x02, !=),
bbc1(0x33, 0x02, ==),
bbs2(0x43, 0x04, !=),
bbc2(0x53, 0x04, ==),
bbs3(0x63, 0x08, !=),
bbc3(0x73, 0x08, ==),
bbs4(0x83, 0x10, !=),
bbc4(0x93, 0x10, ==),
bbs5(0xa3, 0x20, !=),
bbc5(0xb3, 0x20, ==),
bbs6(0xc3, 0x40, !=),
bbc6(0xd3, 0x40, ==),
bbs7(0xe3, 0x80, !=),
bbc7(0xf3, 0x80, ==) {
1:dp = op_readpc();
2:rd = op_readpc();
3:sp = op_readdp(dp);
4:op_io();
if((sp & $1) $2 $1)end;
5:op_io();
6:op_io();
regs.pc += (int8)rd;
}
cbne_dp(0x2e) {
1:dp = op_readpc();
2:rd = op_readpc();
3:sp = op_readdp(dp);
4:op_io();
if(regs.a == sp)end;
5:op_io();
6:op_io();
regs.pc += (int8)rd;
}
cbne_dpx(0xde) {
1:dp = op_readpc();
2:rd = op_readpc();
3:op_io();
4:sp = op_readdp(dp + regs.x);
5:op_io();
if(regs.a == sp)end;
6:op_io();
7:op_io();
regs.pc += (int8)rd;
}
dbnz_dp(0x6e) {
1:dp = op_readpc();
2:rd = op_readpc();
3:wr = op_readdp(dp);
wr--;
4:op_writedp(dp, wr);
if(wr == 0x00)end;
5:op_io();
6:op_io();
regs.pc += (int8)rd;
}
dbnz_y(0xfe) {
1:rd = op_readpc();
2:op_io();
regs.y--;
3:op_io();
if(regs.y == 0x00)end;
4:op_io();
5:op_io();
regs.pc += (int8)rd;
}
jmp_addr(0x5f) {
1:rd = op_readpc();
2:rd |= op_readpc() << 8;
regs.pc = rd;
}
jmp_iaddrx(0x1f) {
1:dp = op_readpc();
2:dp |= op_readpc() << 8;
3:op_io();
dp += regs.x;
4:rd = op_readaddr(dp);
5:rd |= op_readaddr(dp + 1) << 8;
regs.pc = rd;
}
call(0x3f) {
1:rd = op_readpc();
2:rd |= op_readpc() << 8;
3:op_io();
4:op_io();
5:op_io();
6:op_writestack(regs.pc >> 8);
7:op_writestack(regs.pc);
regs.pc = rd;
}
pcall(0x4f) {
1:rd = op_readpc();
2:op_io();
3:op_io();
4:op_writestack(regs.pc >> 8);
5:op_writestack(regs.pc);
regs.pc = 0xff00 | rd;
}
tcall_0(0x01, 0),
tcall_1(0x11, 1),
tcall_2(0x21, 2),
tcall_3(0x31, 3),
tcall_4(0x41, 4),
tcall_5(0x51, 5),
tcall_6(0x61, 6),
tcall_7(0x71, 7),
tcall_8(0x81, 8),
tcall_9(0x91, 9),
tcall_10(0xa1, 10),
tcall_11(0xb1, 11),
tcall_12(0xc1, 12),
tcall_13(0xd1, 13),
tcall_14(0xe1, 14),
tcall_15(0xf1, 15) {
1:dp = 0xffde - ($1 << 1);
rd = op_readaddr(dp);
2:rd |= op_readaddr(dp + 1) << 8;
3:op_io();
4:op_io();
5:op_io();
6:op_writestack(regs.pc >> 8);
7:op_writestack(regs.pc);
regs.pc = rd;
}
brk(0x0f) {
1:rd = op_readaddr(0xffde);
2:rd |= op_readaddr(0xffdf) << 8;
3:op_io();
4:op_io();
5:op_writestack(regs.pc >> 8);
6:op_writestack(regs.pc);
7:op_writestack(regs.p);
regs.pc = rd;
regs.p.b = 1;
regs.p.i = 0;
}
ret(0x6f) {
1:rd = op_readstack();
2:rd |= op_readstack() << 8;
3:op_io();
4:op_io();
regs.pc = rd;
}
reti(0x7f) {
1:regs.p = op_readstack();
2:rd = op_readstack();
3:rd |= op_readstack() << 8;
4:op_io();
5:op_io();
regs.pc = rd;
}

604
src/apu/sapu/core/op_pc.cpp Normal file
View File

@@ -0,0 +1,604 @@
//bra
case 0x2f: {
rd = op_readpc();
if(0)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//beq
case 0xf0: {
rd = op_readpc();
if(!regs.p.z)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bne
case 0xd0: {
rd = op_readpc();
if(regs.p.z)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bcs
case 0xb0: {
rd = op_readpc();
if(!regs.p.c)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bcc
case 0x90: {
rd = op_readpc();
if(regs.p.c)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bvs
case 0x70: {
rd = op_readpc();
if(!regs.p.v)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bvc
case 0x50: {
rd = op_readpc();
if(regs.p.v)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bmi
case 0x30: {
rd = op_readpc();
if(!regs.p.n)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bpl
case 0x10: {
rd = op_readpc();
if(regs.p.n)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bbs0
case 0x03: {
dp = op_readpc();
rd = op_readpc();
sp = op_readdp(dp);
op_io();
if((sp & 0x01) != 0x01)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bbc0
case 0x13: {
dp = op_readpc();
rd = op_readpc();
sp = op_readdp(dp);
op_io();
if((sp & 0x01) == 0x01)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bbs1
case 0x23: {
dp = op_readpc();
rd = op_readpc();
sp = op_readdp(dp);
op_io();
if((sp & 0x02) != 0x02)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bbc1
case 0x33: {
dp = op_readpc();
rd = op_readpc();
sp = op_readdp(dp);
op_io();
if((sp & 0x02) == 0x02)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bbs2
case 0x43: {
dp = op_readpc();
rd = op_readpc();
sp = op_readdp(dp);
op_io();
if((sp & 0x04) != 0x04)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bbc2
case 0x53: {
dp = op_readpc();
rd = op_readpc();
sp = op_readdp(dp);
op_io();
if((sp & 0x04) == 0x04)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bbs3
case 0x63: {
dp = op_readpc();
rd = op_readpc();
sp = op_readdp(dp);
op_io();
if((sp & 0x08) != 0x08)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bbc3
case 0x73: {
dp = op_readpc();
rd = op_readpc();
sp = op_readdp(dp);
op_io();
if((sp & 0x08) == 0x08)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bbs4
case 0x83: {
dp = op_readpc();
rd = op_readpc();
sp = op_readdp(dp);
op_io();
if((sp & 0x10) != 0x10)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bbc4
case 0x93: {
dp = op_readpc();
rd = op_readpc();
sp = op_readdp(dp);
op_io();
if((sp & 0x10) == 0x10)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bbs5
case 0xa3: {
dp = op_readpc();
rd = op_readpc();
sp = op_readdp(dp);
op_io();
if((sp & 0x20) != 0x20)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bbc5
case 0xb3: {
dp = op_readpc();
rd = op_readpc();
sp = op_readdp(dp);
op_io();
if((sp & 0x20) == 0x20)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bbs6
case 0xc3: {
dp = op_readpc();
rd = op_readpc();
sp = op_readdp(dp);
op_io();
if((sp & 0x40) != 0x40)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bbc6
case 0xd3: {
dp = op_readpc();
rd = op_readpc();
sp = op_readdp(dp);
op_io();
if((sp & 0x40) == 0x40)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bbs7
case 0xe3: {
dp = op_readpc();
rd = op_readpc();
sp = op_readdp(dp);
op_io();
if((sp & 0x80) != 0x80)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//bbc7
case 0xf3: {
dp = op_readpc();
rd = op_readpc();
sp = op_readdp(dp);
op_io();
if((sp & 0x80) == 0x80)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//cbne_dp
case 0x2e: {
dp = op_readpc();
rd = op_readpc();
sp = op_readdp(dp);
op_io();
if(regs.a == sp)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//cbne_dpx
case 0xde: {
dp = op_readpc();
rd = op_readpc();
op_io();
sp = op_readdp(dp + regs.x);
op_io();
if(regs.a == sp)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//dbnz_dp
case 0x6e: {
dp = op_readpc();
rd = op_readpc();
wr = op_readdp(dp);
wr--;
op_writedp(dp, wr);
if(wr == 0x00)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//dbnz_y
case 0xfe: {
rd = op_readpc();
op_io();
regs.y--;
op_io();
if(regs.y == 0x00)break;
op_io();
op_io();
regs.pc += (int8)rd;
} break;
//jmp_addr
case 0x5f: {
rd = op_readpc();
rd |= op_readpc() << 8;
regs.pc = rd;
} break;
//jmp_iaddrx
case 0x1f: {
dp = op_readpc();
dp |= op_readpc() << 8;
op_io();
dp += regs.x;
rd = op_readaddr(dp);
rd |= op_readaddr(dp + 1) << 8;
regs.pc = rd;
} break;
//call
case 0x3f: {
rd = op_readpc();
rd |= op_readpc() << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
regs.pc = rd;
} break;
//pcall
case 0x4f: {
rd = op_readpc();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
regs.pc = 0xff00 | rd;
} break;
//tcall_0
case 0x01: {
dp = 0xffde - (0 << 1);
rd = op_readaddr(dp);
rd |= op_readaddr(dp + 1) << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
regs.pc = rd;
} break;
//tcall_1
case 0x11: {
dp = 0xffde - (1 << 1);
rd = op_readaddr(dp);
rd |= op_readaddr(dp + 1) << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
regs.pc = rd;
} break;
//tcall_2
case 0x21: {
dp = 0xffde - (2 << 1);
rd = op_readaddr(dp);
rd |= op_readaddr(dp + 1) << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
regs.pc = rd;
} break;
//tcall_3
case 0x31: {
dp = 0xffde - (3 << 1);
rd = op_readaddr(dp);
rd |= op_readaddr(dp + 1) << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
regs.pc = rd;
} break;
//tcall_4
case 0x41: {
dp = 0xffde - (4 << 1);
rd = op_readaddr(dp);
rd |= op_readaddr(dp + 1) << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
regs.pc = rd;
} break;
//tcall_5
case 0x51: {
dp = 0xffde - (5 << 1);
rd = op_readaddr(dp);
rd |= op_readaddr(dp + 1) << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
regs.pc = rd;
} break;
//tcall_6
case 0x61: {
dp = 0xffde - (6 << 1);
rd = op_readaddr(dp);
rd |= op_readaddr(dp + 1) << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
regs.pc = rd;
} break;
//tcall_7
case 0x71: {
dp = 0xffde - (7 << 1);
rd = op_readaddr(dp);
rd |= op_readaddr(dp + 1) << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
regs.pc = rd;
} break;
//tcall_8
case 0x81: {
dp = 0xffde - (8 << 1);
rd = op_readaddr(dp);
rd |= op_readaddr(dp + 1) << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
regs.pc = rd;
} break;
//tcall_9
case 0x91: {
dp = 0xffde - (9 << 1);
rd = op_readaddr(dp);
rd |= op_readaddr(dp + 1) << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
regs.pc = rd;
} break;
//tcall_10
case 0xa1: {
dp = 0xffde - (10 << 1);
rd = op_readaddr(dp);
rd |= op_readaddr(dp + 1) << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
regs.pc = rd;
} break;
//tcall_11
case 0xb1: {
dp = 0xffde - (11 << 1);
rd = op_readaddr(dp);
rd |= op_readaddr(dp + 1) << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
regs.pc = rd;
} break;
//tcall_12
case 0xc1: {
dp = 0xffde - (12 << 1);
rd = op_readaddr(dp);
rd |= op_readaddr(dp + 1) << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
regs.pc = rd;
} break;
//tcall_13
case 0xd1: {
dp = 0xffde - (13 << 1);
rd = op_readaddr(dp);
rd |= op_readaddr(dp + 1) << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
regs.pc = rd;
} break;
//tcall_14
case 0xe1: {
dp = 0xffde - (14 << 1);
rd = op_readaddr(dp);
rd |= op_readaddr(dp + 1) << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
regs.pc = rd;
} break;
//tcall_15
case 0xf1: {
dp = 0xffde - (15 << 1);
rd = op_readaddr(dp);
rd |= op_readaddr(dp + 1) << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
regs.pc = rd;
} break;
//brk
case 0x0f: {
rd = op_readaddr(0xffde);
rd |= op_readaddr(0xffdf) << 8;
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc);
op_writestack(regs.p);
regs.pc = rd;
regs.p.b = 1;
regs.p.i = 0;
} break;
//ret
case 0x6f: {
rd = op_readstack();
rd |= op_readstack() << 8;
op_io();
op_io();
regs.pc = rd;
} break;
//reti
case 0x7f: {
regs.p = op_readstack();
rd = op_readstack();
rd |= op_readstack() << 8;
op_io();
op_io();
regs.pc = rd;
} break;

199
src/apu/sapu/core/op_read.b Normal file
View File

@@ -0,0 +1,199 @@
adc_a_const(0x88, adc, a),
and_a_const(0x28, and, a),
cmp_a_const(0x68, cmp, a),
cmp_x_const(0xc8, cmp, x),
cmp_y_const(0xad, cmp, y),
eor_a_const(0x48, eor, a),
or_a_const(0x08, or, a),
sbc_a_const(0xa8, sbc, a) {
1:rd = op_readpc();
regs.$2 = op_$1(regs.$2, rd);
}
adc_a_ix(0x86, adc),
and_a_ix(0x26, and),
cmp_a_ix(0x66, cmp),
eor_a_ix(0x46, eor),
or_a_ix(0x06, or),
sbc_a_ix(0xa6, sbc) {
1:rd = op_readdp(regs.x);
2:op_io();
regs.a = op_$1(regs.a, rd);
}
adc_a_dp(0x84, adc, a),
and_a_dp(0x24, and, a),
cmp_a_dp(0x64, cmp, a),
cmp_x_dp(0x3e, cmp, x),
cmp_y_dp(0x7e, cmp, y),
eor_a_dp(0x44, eor, a),
or_a_dp(0x04, or, a),
sbc_a_dp(0xa4, sbc, a) {
1:dp = op_readpc();
2:rd = op_readdp(dp);
regs.$2 = op_$1(regs.$2, rd);
}
adc_a_dpx(0x94, adc),
and_a_dpx(0x34, and),
cmp_a_dpx(0x74, cmp),
eor_a_dpx(0x54, eor),
or_a_dpx(0x14, or),
sbc_a_dpx(0xb4, sbc) {
1:dp = op_readpc();
2:op_io();
3:rd = op_readdp(dp + regs.x);
regs.a = op_$1(regs.a, rd);
}
adc_a_addr(0x85, adc, a),
and_a_addr(0x25, and, a),
cmp_a_addr(0x65, cmp, a),
cmp_x_addr(0x1e, cmp, x),
cmp_y_addr(0x5e, cmp, y),
eor_a_addr(0x45, eor, a),
or_a_addr(0x05, or, a),
sbc_a_addr(0xa5, sbc, a) {
1:dp = op_readpc();
2:dp |= op_readpc() << 8;
3:rd = op_readaddr(dp);
regs.$2 = op_$1(regs.$2, rd);
}
adc_a_addrx(0x95, adc, x),
adc_a_addry(0x96, adc, y),
and_a_addrx(0x35, and, x),
and_a_addry(0x36, and, y),
cmp_a_addrx(0x75, cmp, x),
cmp_a_addry(0x76, cmp, y),
eor_a_addrx(0x55, eor, x),
eor_a_addry(0x56, eor, y),
or_a_addrx(0x15, or, x),
or_a_addry(0x16, or, y),
sbc_a_addrx(0xb5, sbc, x),
sbc_a_addry(0xb6, sbc, y) {
1:dp = op_readpc();
2:dp |= op_readpc() << 8;
3:op_io();
4:rd = op_readaddr(dp + regs.$2);
regs.a = op_$1(regs.a, rd);
}
adc_a_idpx(0x87, adc),
and_a_idpx(0x27, and),
cmp_a_idpx(0x67, cmp),
eor_a_idpx(0x47, eor),
or_a_idpx(0x07, or),
sbc_a_idpx(0xa7, sbc) {
1:dp = op_readpc() + regs.x;
2:op_io();
3:sp = op_readdp(dp);
4:sp |= op_readdp(dp + 1) << 8;
5:rd = op_readaddr(sp);
regs.a = op_$1(regs.a, rd);
}
adc_a_idpy(0x97, adc),
and_a_idpy(0x37, and),
cmp_a_idpy(0x77, cmp),
eor_a_idpy(0x57, eor),
or_a_idpy(0x17, or),
sbc_a_idpy(0xb7, sbc) {
1:dp = op_readpc();
2:op_io();
3:sp = op_readdp(dp);
4:sp |= op_readdp(dp + 1) << 8;
5:rd = op_readaddr(sp + regs.y);
regs.a = op_$1(regs.a, rd);
}
adc_ix_iy(0x99, adc, 1),
and_ix_iy(0x39, and, 1),
cmp_ix_iy(0x79, cmp, 0),
eor_ix_iy(0x59, eor, 1),
or_ix_iy(0x19, or, 1),
sbc_ix_iy(0xb9, sbc, 1) {
1:wr = op_readdp(regs.x);
2:rd = op_readdp(regs.y);
3:op_io();
wr = op_$1(wr, rd);
4:($2) ? op_writedp(regs.x, wr) : op_io();
}
adc_dp_dp(0x89, adc, 1),
and_dp_dp(0x29, and, 1),
cmp_dp_dp(0x69, cmp, 0),
eor_dp_dp(0x49, eor, 1),
or_dp_dp(0x09, or, 1),
sbc_dp_dp(0xa9, sbc, 1) {
1:sp = op_readpc();
2:dp = op_readpc();
3:wr = op_readdp(dp);
4:rd = op_readdp(sp);
5:wr = op_$1(wr, rd);
($2) ? op_writedp(dp, wr) : op_io();
}
adc_dp_const(0x98, adc, 1),
and_dp_const(0x38, and, 1),
cmp_dp_const(0x78, cmp, 0),
eor_dp_const(0x58, eor, 1),
or_dp_const(0x18, or, 1),
sbc_dp_const(0xb8, sbc, 1) {
1:rd = op_readpc();
2:dp = op_readpc();
3:wr = op_readdp(dp);
4:wr = op_$1(wr, rd);
($2) ? op_writedp(dp, wr) : op_io();
}
addw_ya_dp(0x7a, addw),
cmpw_ya_dp(0x5a, cmpw),
subw_ya_dp(0x9a, subw) {
1:dp = op_readpc();
2:rd = op_readdp(dp);
3:rd |= op_readdp(dp + 1) << 8;
4:op_io();
regs.ya = op_$1(regs.ya, rd);
}
and1_bit(0x4a, !!),
and1_notbit(0x6a, !) {
1:dp = op_readpc();
2:dp |= op_readpc() << 8;
3:bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
regs.p.c = regs.p.c & $1(rd & (1 << bit));
}
eor1_bit(0x8a) {
1:dp = op_readpc();
2:dp |= op_readpc() << 8;
3:bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
4:op_io();
regs.p.c = regs.p.c ^ !!(rd & (1 << bit));
}
not1_bit(0xea) {
1:dp = op_readpc();
2:dp |= op_readpc() << 8;
3:bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
rd ^= (1 << bit);
4:op_writeaddr(dp, rd);
}
or1_bit(0x0a, !!),
or1_notbit(0x2a, !) {
1:dp = op_readpc();
2:dp |= op_readpc() << 8;
3:bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
4:op_io();
regs.p.c = regs.p.c | $1(rd & (1 << bit));
}

View File

@@ -0,0 +1,745 @@
//adc_a_const
case 0x88: {
rd = op_readpc();
regs.a = op_adc(regs.a, rd);
} break;
//and_a_const
case 0x28: {
rd = op_readpc();
regs.a = op_and(regs.a, rd);
} break;
//cmp_a_const
case 0x68: {
rd = op_readpc();
regs.a = op_cmp(regs.a, rd);
} break;
//cmp_x_const
case 0xc8: {
rd = op_readpc();
regs.x = op_cmp(regs.x, rd);
} break;
//cmp_y_const
case 0xad: {
rd = op_readpc();
regs.y = op_cmp(regs.y, rd);
} break;
//eor_a_const
case 0x48: {
rd = op_readpc();
regs.a = op_eor(regs.a, rd);
} break;
//or_a_const
case 0x08: {
rd = op_readpc();
regs.a = op_or(regs.a, rd);
} break;
//sbc_a_const
case 0xa8: {
rd = op_readpc();
regs.a = op_sbc(regs.a, rd);
} break;
//adc_a_ix
case 0x86: {
rd = op_readdp(regs.x);
op_io();
regs.a = op_adc(regs.a, rd);
} break;
//and_a_ix
case 0x26: {
rd = op_readdp(regs.x);
op_io();
regs.a = op_and(regs.a, rd);
} break;
//cmp_a_ix
case 0x66: {
rd = op_readdp(regs.x);
op_io();
regs.a = op_cmp(regs.a, rd);
} break;
//eor_a_ix
case 0x46: {
rd = op_readdp(regs.x);
op_io();
regs.a = op_eor(regs.a, rd);
} break;
//or_a_ix
case 0x06: {
rd = op_readdp(regs.x);
op_io();
regs.a = op_or(regs.a, rd);
} break;
//sbc_a_ix
case 0xa6: {
rd = op_readdp(regs.x);
op_io();
regs.a = op_sbc(regs.a, rd);
} break;
//adc_a_dp
case 0x84: {
dp = op_readpc();
rd = op_readdp(dp);
regs.a = op_adc(regs.a, rd);
} break;
//and_a_dp
case 0x24: {
dp = op_readpc();
rd = op_readdp(dp);
regs.a = op_and(regs.a, rd);
} break;
//cmp_a_dp
case 0x64: {
dp = op_readpc();
rd = op_readdp(dp);
regs.a = op_cmp(regs.a, rd);
} break;
//cmp_x_dp
case 0x3e: {
dp = op_readpc();
rd = op_readdp(dp);
regs.x = op_cmp(regs.x, rd);
} break;
//cmp_y_dp
case 0x7e: {
dp = op_readpc();
rd = op_readdp(dp);
regs.y = op_cmp(regs.y, rd);
} break;
//eor_a_dp
case 0x44: {
dp = op_readpc();
rd = op_readdp(dp);
regs.a = op_eor(regs.a, rd);
} break;
//or_a_dp
case 0x04: {
dp = op_readpc();
rd = op_readdp(dp);
regs.a = op_or(regs.a, rd);
} break;
//sbc_a_dp
case 0xa4: {
dp = op_readpc();
rd = op_readdp(dp);
regs.a = op_sbc(regs.a, rd);
} break;
//adc_a_dpx
case 0x94: {
dp = op_readpc();
op_io();
rd = op_readdp(dp + regs.x);
regs.a = op_adc(regs.a, rd);
} break;
//and_a_dpx
case 0x34: {
dp = op_readpc();
op_io();
rd = op_readdp(dp + regs.x);
regs.a = op_and(regs.a, rd);
} break;
//cmp_a_dpx
case 0x74: {
dp = op_readpc();
op_io();
rd = op_readdp(dp + regs.x);
regs.a = op_cmp(regs.a, rd);
} break;
//eor_a_dpx
case 0x54: {
dp = op_readpc();
op_io();
rd = op_readdp(dp + regs.x);
regs.a = op_eor(regs.a, rd);
} break;
//or_a_dpx
case 0x14: {
dp = op_readpc();
op_io();
rd = op_readdp(dp + regs.x);
regs.a = op_or(regs.a, rd);
} break;
//sbc_a_dpx
case 0xb4: {
dp = op_readpc();
op_io();
rd = op_readdp(dp + regs.x);
regs.a = op_sbc(regs.a, rd);
} break;
//adc_a_addr
case 0x85: {
dp = op_readpc();
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
regs.a = op_adc(regs.a, rd);
} break;
//and_a_addr
case 0x25: {
dp = op_readpc();
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
regs.a = op_and(regs.a, rd);
} break;
//cmp_a_addr
case 0x65: {
dp = op_readpc();
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
regs.a = op_cmp(regs.a, rd);
} break;
//cmp_x_addr
case 0x1e: {
dp = op_readpc();
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
regs.x = op_cmp(regs.x, rd);
} break;
//cmp_y_addr
case 0x5e: {
dp = op_readpc();
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
regs.y = op_cmp(regs.y, rd);
} break;
//eor_a_addr
case 0x45: {
dp = op_readpc();
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
regs.a = op_eor(regs.a, rd);
} break;
//or_a_addr
case 0x05: {
dp = op_readpc();
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
regs.a = op_or(regs.a, rd);
} break;
//sbc_a_addr
case 0xa5: {
dp = op_readpc();
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
regs.a = op_sbc(regs.a, rd);
} break;
//adc_a_addrx
case 0x95: {
dp = op_readpc();
dp |= op_readpc() << 8;
op_io();
rd = op_readaddr(dp + regs.x);
regs.a = op_adc(regs.a, rd);
} break;
//adc_a_addry
case 0x96: {
dp = op_readpc();
dp |= op_readpc() << 8;
op_io();
rd = op_readaddr(dp + regs.y);
regs.a = op_adc(regs.a, rd);
} break;
//and_a_addrx
case 0x35: {
dp = op_readpc();
dp |= op_readpc() << 8;
op_io();
rd = op_readaddr(dp + regs.x);
regs.a = op_and(regs.a, rd);
} break;
//and_a_addry
case 0x36: {
dp = op_readpc();
dp |= op_readpc() << 8;
op_io();
rd = op_readaddr(dp + regs.y);
regs.a = op_and(regs.a, rd);
} break;
//cmp_a_addrx
case 0x75: {
dp = op_readpc();
dp |= op_readpc() << 8;
op_io();
rd = op_readaddr(dp + regs.x);
regs.a = op_cmp(regs.a, rd);
} break;
//cmp_a_addry
case 0x76: {
dp = op_readpc();
dp |= op_readpc() << 8;
op_io();
rd = op_readaddr(dp + regs.y);
regs.a = op_cmp(regs.a, rd);
} break;
//eor_a_addrx
case 0x55: {
dp = op_readpc();
dp |= op_readpc() << 8;
op_io();
rd = op_readaddr(dp + regs.x);
regs.a = op_eor(regs.a, rd);
} break;
//eor_a_addry
case 0x56: {
dp = op_readpc();
dp |= op_readpc() << 8;
op_io();
rd = op_readaddr(dp + regs.y);
regs.a = op_eor(regs.a, rd);
} break;
//or_a_addrx
case 0x15: {
dp = op_readpc();
dp |= op_readpc() << 8;
op_io();
rd = op_readaddr(dp + regs.x);
regs.a = op_or(regs.a, rd);
} break;
//or_a_addry
case 0x16: {
dp = op_readpc();
dp |= op_readpc() << 8;
op_io();
rd = op_readaddr(dp + regs.y);
regs.a = op_or(regs.a, rd);
} break;
//sbc_a_addrx
case 0xb5: {
dp = op_readpc();
dp |= op_readpc() << 8;
op_io();
rd = op_readaddr(dp + regs.x);
regs.a = op_sbc(regs.a, rd);
} break;
//sbc_a_addry
case 0xb6: {
dp = op_readpc();
dp |= op_readpc() << 8;
op_io();
rd = op_readaddr(dp + regs.y);
regs.a = op_sbc(regs.a, rd);
} break;
//adc_a_idpx
case 0x87: {
dp = op_readpc() + regs.x;
op_io();
sp = op_readdp(dp);
sp |= op_readdp(dp + 1) << 8;
rd = op_readaddr(sp);
regs.a = op_adc(regs.a, rd);
} break;
//and_a_idpx
case 0x27: {
dp = op_readpc() + regs.x;
op_io();
sp = op_readdp(dp);
sp |= op_readdp(dp + 1) << 8;
rd = op_readaddr(sp);
regs.a = op_and(regs.a, rd);
} break;
//cmp_a_idpx
case 0x67: {
dp = op_readpc() + regs.x;
op_io();
sp = op_readdp(dp);
sp |= op_readdp(dp + 1) << 8;
rd = op_readaddr(sp);
regs.a = op_cmp(regs.a, rd);
} break;
//eor_a_idpx
case 0x47: {
dp = op_readpc() + regs.x;
op_io();
sp = op_readdp(dp);
sp |= op_readdp(dp + 1) << 8;
rd = op_readaddr(sp);
regs.a = op_eor(regs.a, rd);
} break;
//or_a_idpx
case 0x07: {
dp = op_readpc() + regs.x;
op_io();
sp = op_readdp(dp);
sp |= op_readdp(dp + 1) << 8;
rd = op_readaddr(sp);
regs.a = op_or(regs.a, rd);
} break;
//sbc_a_idpx
case 0xa7: {
dp = op_readpc() + regs.x;
op_io();
sp = op_readdp(dp);
sp |= op_readdp(dp + 1) << 8;
rd = op_readaddr(sp);
regs.a = op_sbc(regs.a, rd);
} break;
//adc_a_idpy
case 0x97: {
dp = op_readpc();
op_io();
sp = op_readdp(dp);
sp |= op_readdp(dp + 1) << 8;
rd = op_readaddr(sp + regs.y);
regs.a = op_adc(regs.a, rd);
} break;
//and_a_idpy
case 0x37: {
dp = op_readpc();
op_io();
sp = op_readdp(dp);
sp |= op_readdp(dp + 1) << 8;
rd = op_readaddr(sp + regs.y);
regs.a = op_and(regs.a, rd);
} break;
//cmp_a_idpy
case 0x77: {
dp = op_readpc();
op_io();
sp = op_readdp(dp);
sp |= op_readdp(dp + 1) << 8;
rd = op_readaddr(sp + regs.y);
regs.a = op_cmp(regs.a, rd);
} break;
//eor_a_idpy
case 0x57: {
dp = op_readpc();
op_io();
sp = op_readdp(dp);
sp |= op_readdp(dp + 1) << 8;
rd = op_readaddr(sp + regs.y);
regs.a = op_eor(regs.a, rd);
} break;
//or_a_idpy
case 0x17: {
dp = op_readpc();
op_io();
sp = op_readdp(dp);
sp |= op_readdp(dp + 1) << 8;
rd = op_readaddr(sp + regs.y);
regs.a = op_or(regs.a, rd);
} break;
//sbc_a_idpy
case 0xb7: {
dp = op_readpc();
op_io();
sp = op_readdp(dp);
sp |= op_readdp(dp + 1) << 8;
rd = op_readaddr(sp + regs.y);
regs.a = op_sbc(regs.a, rd);
} break;
//adc_ix_iy
case 0x99: {
wr = op_readdp(regs.x);
rd = op_readdp(regs.y);
op_io();
wr = op_adc(wr, rd);
(1) ? op_writedp(regs.x, wr) : op_io();
} break;
//and_ix_iy
case 0x39: {
wr = op_readdp(regs.x);
rd = op_readdp(regs.y);
op_io();
wr = op_and(wr, rd);
(1) ? op_writedp(regs.x, wr) : op_io();
} break;
//cmp_ix_iy
case 0x79: {
wr = op_readdp(regs.x);
rd = op_readdp(regs.y);
op_io();
wr = op_cmp(wr, rd);
(0) ? op_writedp(regs.x, wr) : op_io();
} break;
//eor_ix_iy
case 0x59: {
wr = op_readdp(regs.x);
rd = op_readdp(regs.y);
op_io();
wr = op_eor(wr, rd);
(1) ? op_writedp(regs.x, wr) : op_io();
} break;
//or_ix_iy
case 0x19: {
wr = op_readdp(regs.x);
rd = op_readdp(regs.y);
op_io();
wr = op_or(wr, rd);
(1) ? op_writedp(regs.x, wr) : op_io();
} break;
//sbc_ix_iy
case 0xb9: {
wr = op_readdp(regs.x);
rd = op_readdp(regs.y);
op_io();
wr = op_sbc(wr, rd);
(1) ? op_writedp(regs.x, wr) : op_io();
} break;
//adc_dp_dp
case 0x89: {
sp = op_readpc();
dp = op_readpc();
wr = op_readdp(dp);
rd = op_readdp(sp);
wr = op_adc(wr, rd);
(1) ? op_writedp(dp, wr) : op_io();
} break;
//and_dp_dp
case 0x29: {
sp = op_readpc();
dp = op_readpc();
wr = op_readdp(dp);
rd = op_readdp(sp);
wr = op_and(wr, rd);
(1) ? op_writedp(dp, wr) : op_io();
} break;
//cmp_dp_dp
case 0x69: {
sp = op_readpc();
dp = op_readpc();
wr = op_readdp(dp);
rd = op_readdp(sp);
wr = op_cmp(wr, rd);
(0) ? op_writedp(dp, wr) : op_io();
} break;
//eor_dp_dp
case 0x49: {
sp = op_readpc();
dp = op_readpc();
wr = op_readdp(dp);
rd = op_readdp(sp);
wr = op_eor(wr, rd);
(1) ? op_writedp(dp, wr) : op_io();
} break;
//or_dp_dp
case 0x09: {
sp = op_readpc();
dp = op_readpc();
wr = op_readdp(dp);
rd = op_readdp(sp);
wr = op_or(wr, rd);
(1) ? op_writedp(dp, wr) : op_io();
} break;
//sbc_dp_dp
case 0xa9: {
sp = op_readpc();
dp = op_readpc();
wr = op_readdp(dp);
rd = op_readdp(sp);
wr = op_sbc(wr, rd);
(1) ? op_writedp(dp, wr) : op_io();
} break;
//adc_dp_const
case 0x98: {
rd = op_readpc();
dp = op_readpc();
wr = op_readdp(dp);
wr = op_adc(wr, rd);
(1) ? op_writedp(dp, wr) : op_io();
} break;
//and_dp_const
case 0x38: {
rd = op_readpc();
dp = op_readpc();
wr = op_readdp(dp);
wr = op_and(wr, rd);
(1) ? op_writedp(dp, wr) : op_io();
} break;
//cmp_dp_const
case 0x78: {
rd = op_readpc();
dp = op_readpc();
wr = op_readdp(dp);
wr = op_cmp(wr, rd);
(0) ? op_writedp(dp, wr) : op_io();
} break;
//eor_dp_const
case 0x58: {
rd = op_readpc();
dp = op_readpc();
wr = op_readdp(dp);
wr = op_eor(wr, rd);
(1) ? op_writedp(dp, wr) : op_io();
} break;
//or_dp_const
case 0x18: {
rd = op_readpc();
dp = op_readpc();
wr = op_readdp(dp);
wr = op_or(wr, rd);
(1) ? op_writedp(dp, wr) : op_io();
} break;
//sbc_dp_const
case 0xb8: {
rd = op_readpc();
dp = op_readpc();
wr = op_readdp(dp);
wr = op_sbc(wr, rd);
(1) ? op_writedp(dp, wr) : op_io();
} break;
//addw_ya_dp
case 0x7a: {
dp = op_readpc();
rd = op_readdp(dp);
rd |= op_readdp(dp + 1) << 8;
op_io();
regs.ya = op_addw(regs.ya, rd);
} break;
//cmpw_ya_dp
case 0x5a: {
dp = op_readpc();
rd = op_readdp(dp);
rd |= op_readdp(dp + 1) << 8;
op_io();
regs.ya = op_cmpw(regs.ya, rd);
} break;
//subw_ya_dp
case 0x9a: {
dp = op_readpc();
rd = op_readdp(dp);
rd |= op_readdp(dp + 1) << 8;
op_io();
regs.ya = op_subw(regs.ya, rd);
} break;
//and1_bit
case 0x4a: {
dp = op_readpc();
dp |= op_readpc() << 8;
bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
regs.p.c = regs.p.c & !!(rd & (1 << bit));
} break;
//and1_notbit
case 0x6a: {
dp = op_readpc();
dp |= op_readpc() << 8;
bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
regs.p.c = regs.p.c & !(rd & (1 << bit));
} break;
//eor1_bit
case 0x8a: {
dp = op_readpc();
dp |= op_readpc() << 8;
bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
op_io();
regs.p.c = regs.p.c ^ !!(rd & (1 << bit));
} break;
//not1_bit
case 0xea: {
dp = op_readpc();
dp |= op_readpc() << 8;
bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
rd ^= (1 << bit);
op_writeaddr(dp, rd);
} break;
//or1_bit
case 0x0a: {
dp = op_readpc();
dp |= op_readpc() << 8;
bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
op_io();
regs.p.c = regs.p.c | !!(rd & (1 << bit));
} break;
//or1_notbit
case 0x2a: {
dp = op_readpc();
dp |= op_readpc() << 8;
bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
op_io();
regs.p.c = regs.p.c | !(rd & (1 << bit));
} break;

View File

@@ -0,0 +1,61 @@
inc_a(0xbc, inc, a),
inc_x(0x3d, inc, x),
inc_y(0xfc, inc, y),
dec_a(0x9c, dec, a),
dec_x(0x1d, dec, x),
dec_y(0xdc, dec, y),
asl_a(0x1c, asl, a),
lsr_a(0x5c, lsr, a),
rol_a(0x3c, rol, a),
ror_a(0x7c, ror, a) {
1:op_io();
regs.$2 = op_$1(regs.$2);
}
inc_dp(0xab, inc),
dec_dp(0x8b, dec),
asl_dp(0x0b, asl),
lsr_dp(0x4b, lsr),
rol_dp(0x2b, rol),
ror_dp(0x6b, ror) {
1:dp = op_readpc();
2:rd = op_readdp(dp);
3:rd = op_$1(rd);
op_writedp(dp, rd);
}
inc_dpx(0xbb, inc),
dec_dpx(0x9b, dec),
asl_dpx(0x1b, asl),
lsr_dpx(0x5b, lsr),
rol_dpx(0x3b, rol),
ror_dpx(0x7b, ror) {
1:dp = op_readpc();
2:op_io();
3:rd = op_readdp(dp + regs.x);
4:rd = op_$1(rd);
op_writedp(dp + regs.x, rd);
}
inc_addr(0xac, inc),
dec_addr(0x8c, dec),
asl_addr(0x0c, asl),
lsr_addr(0x4c, lsr),
rol_addr(0x2c, rol),
ror_addr(0x6c, ror) {
1:dp = op_readpc();
2:dp |= op_readpc() << 8;
3:rd = op_readaddr(dp);
4:rd = op_$1(rd);
op_writeaddr(dp, rd);
}
incw_dp(0x3a, incw),
decw_dp(0x1a, decw) {
1:dp = op_readpc();
2:rd = op_readdp(dp);
3:rd |= op_readdp(dp + 1) << 8;
4:rd = op_$1(rd);
op_writedp(dp + 1, rd >> 8);
5:op_writedp(dp, rd);
}

View File

@@ -0,0 +1,236 @@
//inc_a
case 0xbc: {
op_io();
regs.a = op_inc(regs.a);
} break;
//inc_x
case 0x3d: {
op_io();
regs.x = op_inc(regs.x);
} break;
//inc_y
case 0xfc: {
op_io();
regs.y = op_inc(regs.y);
} break;
//dec_a
case 0x9c: {
op_io();
regs.a = op_dec(regs.a);
} break;
//dec_x
case 0x1d: {
op_io();
regs.x = op_dec(regs.x);
} break;
//dec_y
case 0xdc: {
op_io();
regs.y = op_dec(regs.y);
} break;
//asl_a
case 0x1c: {
op_io();
regs.a = op_asl(regs.a);
} break;
//lsr_a
case 0x5c: {
op_io();
regs.a = op_lsr(regs.a);
} break;
//rol_a
case 0x3c: {
op_io();
regs.a = op_rol(regs.a);
} break;
//ror_a
case 0x7c: {
op_io();
regs.a = op_ror(regs.a);
} break;
//inc_dp
case 0xab: {
dp = op_readpc();
rd = op_readdp(dp);
rd = op_inc(rd);
op_writedp(dp, rd);
} break;
//dec_dp
case 0x8b: {
dp = op_readpc();
rd = op_readdp(dp);
rd = op_dec(rd);
op_writedp(dp, rd);
} break;
//asl_dp
case 0x0b: {
dp = op_readpc();
rd = op_readdp(dp);
rd = op_asl(rd);
op_writedp(dp, rd);
} break;
//lsr_dp
case 0x4b: {
dp = op_readpc();
rd = op_readdp(dp);
rd = op_lsr(rd);
op_writedp(dp, rd);
} break;
//rol_dp
case 0x2b: {
dp = op_readpc();
rd = op_readdp(dp);
rd = op_rol(rd);
op_writedp(dp, rd);
} break;
//ror_dp
case 0x6b: {
dp = op_readpc();
rd = op_readdp(dp);
rd = op_ror(rd);
op_writedp(dp, rd);
} break;
//inc_dpx
case 0xbb: {
dp = op_readpc();
op_io();
rd = op_readdp(dp + regs.x);
rd = op_inc(rd);
op_writedp(dp + regs.x, rd);
} break;
//dec_dpx
case 0x9b: {
dp = op_readpc();
op_io();
rd = op_readdp(dp + regs.x);
rd = op_dec(rd);
op_writedp(dp + regs.x, rd);
} break;
//asl_dpx
case 0x1b: {
dp = op_readpc();
op_io();
rd = op_readdp(dp + regs.x);
rd = op_asl(rd);
op_writedp(dp + regs.x, rd);
} break;
//lsr_dpx
case 0x5b: {
dp = op_readpc();
op_io();
rd = op_readdp(dp + regs.x);
rd = op_lsr(rd);
op_writedp(dp + regs.x, rd);
} break;
//rol_dpx
case 0x3b: {
dp = op_readpc();
op_io();
rd = op_readdp(dp + regs.x);
rd = op_rol(rd);
op_writedp(dp + regs.x, rd);
} break;
//ror_dpx
case 0x7b: {
dp = op_readpc();
op_io();
rd = op_readdp(dp + regs.x);
rd = op_ror(rd);
op_writedp(dp + regs.x, rd);
} break;
//inc_addr
case 0xac: {
dp = op_readpc();
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
rd = op_inc(rd);
op_writeaddr(dp, rd);
} break;
//dec_addr
case 0x8c: {
dp = op_readpc();
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
rd = op_dec(rd);
op_writeaddr(dp, rd);
} break;
//asl_addr
case 0x0c: {
dp = op_readpc();
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
rd = op_asl(rd);
op_writeaddr(dp, rd);
} break;
//lsr_addr
case 0x4c: {
dp = op_readpc();
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
rd = op_lsr(rd);
op_writeaddr(dp, rd);
} break;
//rol_addr
case 0x2c: {
dp = op_readpc();
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
rd = op_rol(rd);
op_writeaddr(dp, rd);
} break;
//ror_addr
case 0x6c: {
dp = op_readpc();
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
rd = op_ror(rd);
op_writeaddr(dp, rd);
} break;
//incw_dp
case 0x3a: {
dp = op_readpc();
rd = op_readdp(dp);
rd |= op_readdp(dp + 1) << 8;
rd = op_incw(rd);
op_writedp(dp + 1, rd >> 8);
op_writedp(dp, rd);
} break;
//decw_dp
case 0x1a: {
dp = op_readpc();
rd = op_readdp(dp);
rd |= op_readdp(dp + 1) << 8;
rd = op_decw(rd);
op_writedp(dp + 1, rd >> 8);
op_writedp(dp, rd);
} break;

138
src/apu/sapu/core/opfn.cpp Normal file
View File

@@ -0,0 +1,138 @@
uint8 sAPU::op_adc(uint8 x, uint8 y) {
int16 r = x + y + regs.p.c;
regs.p.n = bool(r & 0x80);
regs.p.v = bool(~(x ^ y) & (y ^ (uint8)r) & 0x80);
regs.p.h = bool((x ^ y ^ (uint8)r) & 0x10);
regs.p.z = ((uint8)r == 0);
regs.p.c = (r > 0xff);
return r;
}
uint16 sAPU::op_addw(uint16 x, uint16 y) {
int16 r;
regs.p.c = 0;
r = op_adc(x, y);
r |= op_adc(x >> 8, y >> 8) << 8;
regs.p.z = ((uint16)r == 0);
return r;
}
uint8 sAPU::op_and(uint8 x, uint8 y) {
x &= y;
regs.p.n = bool(x & 0x80);
regs.p.z = (x == 0);
return x;
}
uint8 sAPU::op_cmp(uint8 x, uint8 y) {
int16 r = x - y;
regs.p.n = bool(r & 0x80);
regs.p.z = ((uint8)r == 0);
regs.p.c = (r >= 0);
return x;
}
uint16 sAPU::op_cmpw(uint16 x, uint16 y) {
int32 r = x - y;
regs.p.n = bool(r & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.p.c = (r >= 0);
return x;
}
uint8 sAPU::op_eor(uint8 x, uint8 y) {
x ^= y;
regs.p.n = bool(x & 0x80);
regs.p.z = (x == 0);
return x;
}
uint8 sAPU::op_or(uint8 x, uint8 y) {
x |= y;
regs.p.n = bool(x & 0x80);
regs.p.z = (x == 0);
return x;
}
uint8 sAPU::op_sbc(uint8 x, uint8 y) {
int16 r = x - y - !regs.p.c;
regs.p.n = bool(r & 0x80);
regs.p.v = bool((x ^ y) & (x ^ (uint8)r) & 0x80);
regs.p.h = !((x ^ y ^ (uint8)r) & 0x10);
regs.p.z = ((uint8)r == 0);
regs.p.c = (r >= 0);
return r;
}
uint16 sAPU::op_subw(uint16 x, uint16 y) {
int16 r;
regs.p.c = 1;
r = op_sbc(x, y);
r |= op_sbc(x >> 8, y >> 8) << 8;
regs.p.z = ((uint16)r == 0);
return r;
}
uint8 sAPU::op_inc(uint8 x) {
x++;
regs.p.n = bool(x & 0x80);
regs.p.z = (x == 0);
return x;
}
uint16 sAPU::op_incw(uint16 x) {
x++;
regs.p.n = bool(x & 0x8000);
regs.p.z = (x == 0);
return x;
}
uint8 sAPU::op_dec(uint8 x) {
x--;
regs.p.n = bool(x & 0x80);
regs.p.z = (x == 0);
return x;
}
uint16 sAPU::op_decw(uint16 x) {
x--;
regs.p.n = bool(x & 0x8000);
regs.p.z = (x == 0);
return x;
}
uint8 sAPU::op_asl(uint8 x) {
regs.p.c = bool(x & 0x80);
x <<= 1;
regs.p.n = bool(x & 0x80);
regs.p.z = (x == 0);
return x;
}
uint8 sAPU::op_lsr(uint8 x) {
regs.p.c = bool(x & 0x01);
x >>= 1;
regs.p.n = bool(x & 0x80);
regs.p.z = (x == 0);
return x;
}
uint8 sAPU::op_rol(uint8 x) {
uint8 c = regs.p.c;
regs.p.c = bool(x & 0x80);
x <<= 1;
x |= c;
regs.p.n = bool(x & 0x80);
regs.p.z = (x == 0);
return x;
}
uint8 sAPU::op_ror(uint8 x) {
uint8 c = (regs.p.c)?0x80:0x00;
regs.p.c = bool(x & 0x01);
x >>= 1;
x |= c;
regs.p.n = bool(x & 0x80);
regs.p.z = (x == 0);
return x;
}

View File

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

View File

@@ -0,0 +1,201 @@
uint8 sAPU::spcram_read(uint16 addr) {
uint8 r;
if((addr & 0xfff0) == 0x00f0) {
//addr >= 0x00f0 && addr <= 0x00ff
#ifdef FAVOR_SPEED
co_return();
#endif
switch(addr) {
case 0xf0: //TEST -- operation unknown, supposedly returns 0x00
r = 0x00;
break;
case 0xf1: //CONTROL -- write-only register, always returns 0x00
r = 0x00;
break;
case 0xf2: //DSPADDR
r = status.dsp_addr;
break;
case 0xf3: //DSPDATA
//0x80-0xff is a read-only mirror of 0x00-0x7f
r = r_dsp->read(status.dsp_addr & 0x7f);
break;
case 0xf4: //CPUIO0
case 0xf5: //CPUIO1
case 0xf6: //CPUIO2
case 0xf7: //CPUIO3
r = r_cpu->port_read(addr & 3);
break;
case 0xf8: //???
case 0xf9: //??? -- Mapped to SPCRAM
r = spcram[addr];
break;
case 0xfa: //T0TARGET
case 0xfb: //T1TARGET
case 0xfc: //T2TARGET -- write-only registers, always return 0x00
r = 0x00;
break;
case 0xfd: //T0OUT -- 4-bit counter value
r = t0.stage3_ticks & 15;
t0.stage3_ticks = 0;
break;
case 0xfe: //T1OUT -- 4-bit counter value
r = t1.stage3_ticks & 15;
t1.stage3_ticks = 0;
break;
case 0xff: //T2OUT -- 4-bit counter value
r = t2.stage3_ticks & 15;
t2.stage3_ticks = 0;
break;
}
} else if(addr < 0xffc0) {
r = spcram[addr];
} else {
if(status.iplrom_enabled == true) {
r = iplrom[addr & 0x3f];
} else {
r = spcram[addr];
}
}
#ifdef DEBUGGER
snes->notify(SNES::SPCRAM_READ, addr, r);
#endif
return r;
}
void sAPU::spcram_write(uint16 addr, uint8 data) {
if((addr & 0xfff0) == 0x00f0) {
//addr >= 0x00f0 && addr >= 0x00ff
#ifdef FAVOR_SPEED
co_return();
#endif
switch(addr) {
case 0xf0: //TEST -- operation unknown
break;
case 0xf1: //CONTROL
status.iplrom_enabled = !!(data & 0x80);
//one-time clearing of APU port read registers,
//emulated by simulating CPU writes of 0x00
if(data & 0x20) {
r_cpu->port_write(2, 0x00);
r_cpu->port_write(3, 0x00);
}
if(data & 0x10) {
r_cpu->port_write(0, 0x00);
r_cpu->port_write(1, 0x00);
}
//0->1 transistion resets timers
if(t2.enabled == false && (data & 0x04)) {
t2.stage2_ticks = 0;
t2.stage3_ticks = 0;
}
t2.enabled = !!(data & 0x04);
if(t1.enabled == false && (data & 0x02)) {
t1.stage2_ticks = 0;
t1.stage3_ticks = 0;
}
t1.enabled = !!(data & 0x02);
if(t0.enabled == false && (data & 0x01)) {
t0.stage2_ticks = 0;
t0.stage3_ticks = 0;
}
t0.enabled = !!(data & 0x01);
break;
case 0xf2: //DSPADDR
status.dsp_addr = data;
break;
case 0xf3: //DSPDATA
//0x80-0xff is a read-only mirror of 0x00-0x7f
if(status.dsp_addr < 0x80) {
r_dsp->write(status.dsp_addr & 0x7f, data);
}
break;
case 0xf4: //CPUIO0
case 0xf5: //CPUIO1
case 0xf6: //CPUIO2
case 0xf7: //CPUIO3
port_write(addr & 3, data);
break;
case 0xf8: //???
case 0xf9: //??? - Mapped to SPCRAM
spcram[addr] = data;
break;
case 0xfa: //T0TARGET
t0.target = data;
break;
case 0xfb: //T1TARGET
t1.target = data;
break;
case 0xfc: //T2TARGET
t2.target = data;
break;
case 0xfd: //T0OUT
case 0xfe: //T1OUT
case 0xff: //T2OUT -- read-only registers
break;
}
} else {
//writes to $ffc0-$ffff always go to spcram,
//even if the iplrom is enabled.
spcram[addr] = data;
}
#ifdef DEBUGGER
snes->notify(SNES::SPCRAM_WRITE, addr, data);
#endif
}
uint8 sAPU::port_read(uint8 port) {
return spcram[0xf4 + (port & 3)];
}
void sAPU::port_write(uint8 port, uint8 data) {
spcram[0xf4 + (port & 3)] = data;
}
//
void sAPU::op_io() {
add_clocks(24);
tick_timers();
//co_return();
}
uint8 sAPU::op_read(uint16 addr) {
add_clocks(8);
#ifdef FAVOR_ACCURACY
co_return();
#endif
uint8 r = spcram_read(addr);
add_clocks(16);
tick_timers();
return r;
}
void sAPU::op_write(uint16 addr, uint8 data) {
add_clocks(24);
tick_timers();
#ifdef FAVOR_ACCURACY
co_return();
#endif
spcram_write(addr, data);
}
//
uint8 sAPU::op_readpc () { return op_read(regs.pc++); }
uint8 sAPU::op_readstack () { return op_read(0x0100 | ++regs.sp); }
void sAPU::op_writestack(uint8 data) { op_write(0x0100 | regs.sp--, data); }
uint8 sAPU::op_readaddr (uint16 addr) { return op_read(addr); }
void sAPU::op_writeaddr (uint16 addr, uint8 data) { op_write(addr, data); }
uint8 sAPU::op_readdp (uint8 addr) { return op_read((uint(regs.p.p) << 8) + addr); }
void sAPU::op_writedp (uint8 addr, uint8 data) { op_write((uint(regs.p.p) << 8) + addr, data); }

View File

@@ -0,0 +1,24 @@
uint8 spcram_read (uint16 addr);
void spcram_write(uint16 addr, uint8 data);
uint8 port_read (uint8 port);
void port_write(uint8 port, uint8 data);
/*****
* core APU bus functions
*****/
inline void op_io ();
inline uint8 op_read (uint16 addr);
inline void op_write(uint16 addr, uint8 data);
/*****
* helper memory addressing functions used by APU core
*****/
inline uint8 op_readpc ();
inline uint8 op_readstack ();
inline void op_writestack(uint8 data);
inline uint8 op_readaddr (uint16 addr);
inline void op_writeaddr (uint16 addr, uint8 data);
inline uint8 op_readdp (uint8 addr);
inline void op_writedp (uint8 addr, uint8 data);

73
src/apu/sapu/sapu.cpp Normal file
View File

@@ -0,0 +1,73 @@
#include "../../base.h"
#include "core/core.cpp"
#include "memory/memory.cpp"
#include "timing/timing.cpp"
void sapu_entry_point() {
r_apu->main();
}
void sAPU::run() {
co_call(thread);
}
void sAPU::power() {
memset(spcram, 0x00, 65536);
reset();
}
void sAPU::reset() {
if(thread)co_delete(thread);
thread = co_create(sapu_entry_point, 65536);
regs.pc = 0xffc0;
regs.a = 0x00;
regs.x = 0x00;
regs.y = 0x00;
regs.sp = 0xef;
regs.p = 0x02;
status.clocks_executed = 0;
//$f1
status.iplrom_enabled = true;
//$f2
status.dsp_addr = 0x00;
t0.enabled = false;
t1.enabled = false;
t2.enabled = false;
t0.stage1_ticks = 0;
t1.stage1_ticks = 0;
t2.stage1_ticks = 0;
t0.stage2_ticks = 0;
t1.stage2_ticks = 0;
t2.stage2_ticks = 0;
t0.stage3_ticks = 0;
t1.stage3_ticks = 0;
t2.stage3_ticks = 0;
}
sAPU::sAPU() {
//#include "core/optable.cpp"
thread = 0;
t0.cycle_frequency = 128; //1.024mhz / 8khz = 128
t1.cycle_frequency = 128; //1.024mhz / 8khz = 128
t2.cycle_frequency = 16; //1.024mhz / 64khz = 16
//targets not initialized/changed upon reset
t0.target = 0;
t1.target = 0;
t2.target = 0;
}
sAPU::~sAPU() {
if(thread)co_delete(thread);
}

32
src/apu/sapu/sapu.h Normal file
View File

@@ -0,0 +1,32 @@
class sAPU : public APU {
public:
#include "core/core.h"
#include "memory/memory.h"
#include "timing/timing.h"
thread_t thread;
struct {
uint8 opcode;
bool in_opcode;
//timing
uint32 clocks_executed;
//$f1
bool iplrom_enabled;
//$f2
uint8 dsp_addr;
} status;
//sapu.cpp
void main();
void run();
void power();
void reset();
sAPU();
~sAPU();
};

View File

@@ -0,0 +1,35 @@
void sAPU::add_clocks(int clocks) {
status.clocks_executed += clocks;
}
uint32 sAPU::clocks_executed() {
uint32 r = status.clocks_executed;
status.clocks_executed = 0;
return r;
}
//occurs once every 24 clocks (once every APU opcode cycle)
void sAPU::tick_timers() {
t0.tick();
t1.tick();
t2.tick();
}
void sAPU::sAPUTimer::tick() {
//stage 1 increment
stage1_ticks++;
if(stage1_ticks < cycle_frequency)return;
stage1_ticks -= cycle_frequency;
if(enabled == false)return;
//stage 2 increment
stage2_ticks++;
if(stage2_ticks != target)return;
//stage 3 increment
stage2_ticks = 0;
stage3_ticks++;
stage3_ticks &= 15;
}

View File

@@ -0,0 +1,11 @@
class sAPUTimer {
public:
uint8 cycle_frequency, target;
uint8 stage1_ticks, stage2_ticks, stage3_ticks;
bool enabled;
inline void tick();
} t0, t1, t2;
inline void add_clocks(int clocks);
inline void tick_timers();
uint32 clocks_executed();

View File

@@ -1,53 +1,46 @@
#define BSNES_VERSION "0.016"
#define BSNES_TITLE "bsnes v" BSNES_VERSION
#define BSNES_VERSION "0.017"
#define BSNES_TITLE "bsnes v" BSNES_VERSION
#define MEMCORE bMemBus
#define CPUCORE bCPU
#define APUCORE bAPU
#define CPUCORE sCPU
#define APUCORE sAPU
#define DSPCORE bDSP
#define PPUCORE bPPU
//#define FAVOR_ACCURACY
#define FAVOR_SPEED
//game genie + pro action replay code support (~1-3% speed hit)
#define CHEAT_SYSTEM
//enable GZ, ZIP format support
//#define GZIP_SUPPORT
#define GZIP_SUPPORT
//enable JMA support
//#define JMA_SUPPORT
#define JMA_SUPPORT
//debugging extensions (~10% speed hit)
#define DEBUGGER
//#define DEBUGGER
//snes core polymorphism
//(allow mem/cpu/apu/ppu overriding, ~10% speed hit)
//#define POLYMORPHISM
//this should be declared in the port-specific makefiles
//#define ARCH_LSB
//#define ARCH_MSB
#ifndef ARCH_LSB
#ifndef ARCH_MSB
#define ARCH_LSB
#endif
#endif
#if defined(_WIN32)
#define _WIN32_
#undef _UNIX_
#elif defined(__GNUC__)
#define _UNIX_
#undef _WIN32_
#if defined(PROCESSOR_X86)
#define ARCH_LSB
#elif defined(PROCESSOR_X86_64)
#define ARCH_LSB
#elif defined(PROCESSOR_G5)
#define ARCH_MSB
#else
#error "unknown architecture"
#error "unsupported processor"
#endif
#include "lib/libbase.h"
#include "lib/libco_x86.h"
#include "lib/libvector.h"
#include "lib/libstring.h"
#include "lib/libconfig.h"
#include "lib/libbpf.h"
inline uint16 read16(uint8 *addr, uint pos) {
#ifdef ARCH_LSB
@@ -58,8 +51,18 @@ inline uint16 read16(uint8 *addr, uint pos) {
}
//platform-specific global functions
void alert(char *s, ...);
void dprintf(char *s, ...);
void alert(char *, ...);
void dprintf(char *, ...);
void dprintf(uint, char *, ...);
namespace source {
enum {
none = 0,
debug,
cpu,
apu,
};
};
//various class interfaces
#include "interface.h"

View File

@@ -1,62 +1,112 @@
#include "../base.h"
#include "database.cpp"
void Cartridge::read_dbi() {
info.srtc = false;
info.sdd1 = false;
info.c4 = false;
info.dsp1 = false;
info.dsp2 = false;
info.obc1 = false;
info.dsp1_mapper = 0;
info.header_index = 0x7fc0;
info.mapper = PCB;
strcpy(info.name, dbi.name);
strcpy(info.pcb, dbi.pcb);
info.region = NTSC;
info.cart_mmio = false;
info.rom_size = dbi.rom;
info.ram_size = dbi.ram;
}
void Cartridge::read_header() {
cart.srtc = false;
cart.sdd1 = false;
cart.c4 = false;
cart.dsp2 = false;
cart.obc1 = false;
info.srtc = false;
info.sdd1 = false;
info.c4 = false;
info.dsp1 = false;
info.dsp2 = false;
info.obc1 = false;
if(cart.header_index == 0x7fc0 && cart.rom_size >= 0x401000) {
cart.mapper = EXLOROM;
} else if(cart.header_index == 0x7fc0 && rom[cart.header_index + MAPPER] == 0x32) {
cart.mapper = EXLOROM;
} else if(cart.header_index == 0x7fc0) {
cart.mapper = LOROM;
} else if(cart.header_index == 0xffc0) {
cart.mapper = HIROM;
} else { //cart.header_index == 0x40ffc0
cart.mapper = EXHIROM;
info.dsp1_mapper = 0;
if(info.header_index == 0x7fc0 && info.rom_size >= 0x401000) {
info.mapper = EXLOROM;
strcpy(info.pcb, "UNL-EXLOROM");
} else if(info.header_index == 0x7fc0 && rom[info.header_index + MAPPER] == 0x32) {
info.mapper = EXLOROM;
strcpy(info.pcb, "UNL-EXLOROM");
} else if(info.header_index == 0x7fc0) {
info.mapper = LOROM;
strcpy(info.pcb, "UNL-LOROM");
} else if(info.header_index == 0xffc0) {
info.mapper = HIROM;
strcpy(info.pcb, "UNL-HIROM");
} else { //info.header_index == 0x40ffc0
info.mapper = EXHIROM;
strcpy(info.pcb, "UNL-EXHIROM");
}
uint8 mapper = rom[cart.header_index + MAPPER];
uint8 rom_type = rom[cart.header_index + ROM_TYPE];
uint8 mapper = rom[info.header_index + MAPPER];
uint8 rom_type = rom[info.header_index + ROM_TYPE];
if(mapper == 0x35 && rom_type == 0x55) {
cart.srtc = true;
info.srtc = true;
}
if(mapper == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
cart.sdd1 = true;
info.sdd1 = true;
}
if(mapper == 0x20 && rom_type == 0xf3) {
cart.c4 = true;
info.c4 = true;
}
if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) {
info.dsp1 = true;
}
if(mapper == 0x30 && rom_type == 0x05) {
info.dsp1 = true;
}
if(mapper == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) {
info.dsp1 = true;
}
if(info.dsp1 == true) {
if((mapper & 0x2f) == 0x20 && info.rom_size <= 0x100000) {
info.dsp1_mapper = DSP1_LOROM_1MB;
} else if((mapper & 0x2f) == 0x20) {
info.dsp1_mapper = DSP1_LOROM_2MB;
} else if((mapper & 0x2f) == 0x21) {
info.dsp1_mapper = DSP1_HIROM;
}
}
if(mapper == 0x20 && rom_type == 0x05) {
cart.dsp2 = true;
info.dsp2 = true;
}
if(mapper == 0x30 && rom_type == 0x25) {
cart.obc1 = true;
info.obc1 = true;
}
cart.cart_mmio = cart.c4 | cart.dsp2 | cart.obc1;
info.cart_mmio = info.c4 | info.dsp1 | info.dsp2 | info.obc1;
if(rom[cart.header_index + SRAM_SIZE] & 7) {
cart.sram_size = 1024 << (rom[cart.header_index + SRAM_SIZE] & 7);
if(rom[info.header_index + SRAM_SIZE] & 7) {
info.ram_size = 1024 << (rom[info.header_index + SRAM_SIZE] & 7);
} else {
cart.sram_size = 0;
info.ram_size = 0;
}
cart.region = ((rom[cart.header_index + REGION] & 0x7f) < 2) ? NTSC : PAL;
memcpy(&cart.name, &rom[cart.header_index + CART_NAME], 21);
cart.name[21] = 0;
memcpy(&info.name, &rom[info.header_index + CART_NAME], 21);
info.name[21] = 0;
for(int i = 0; i < 22; i++) {
if(cart.name[i] & 0x80) {
cart.name[i] = '?';
if(info.name[i] & 0x80) {
info.name[i] = '?';
}
}
}
@@ -66,9 +116,9 @@ int32 score_lo = 0,
score_hi = 0,
score_ex = 0;
if(rom_size < 0x010000) {
//cart too small to be anything else
cart.header_index = 0x007fc0;
if(info.rom_size < 0x010000) {
//cart too small to be anything but lorom
info.header_index = 0x007fc0;
return;
}
@@ -90,6 +140,9 @@ int32 score_lo = 0,
if(rom[0x7fc0 + LICENSE] < 3)score_lo++;
if(rom[0xffc0 + LICENSE] < 3)score_hi++;
if(rom[0x7fc0 + RESH] & 0x80)score_lo += 2;
if(rom[0xffc0 + RESH] & 0x80)score_hi += 2;
uint16 cksum, icksum;
cksum = rom[0x7fc0 + CKSUM] | (rom[0x7fc0 + CKSUM + 1] << 8);
icksum = rom[0x7fc0 + ICKSUM] | (rom[0x7fc0 + ICKSUM + 1] << 8);
@@ -103,7 +156,7 @@ uint16 cksum, icksum;
score_hi += 8;
}
if(rom_size < 0x401000) {
if(info.rom_size < 0x401000) {
score_ex = 0;
} else {
if(rom[0x7fc0 + MAPPER] == 0x32)score_lo++;
@@ -111,100 +164,54 @@ uint16 cksum, icksum;
}
if(score_lo >= score_hi && score_lo >= score_ex) {
cart.header_index = 0x007fc0;
info.header_index = 0x007fc0;
} else if(score_hi >= score_ex) {
cart.header_index = 0x00ffc0;
info.header_index = 0x00ffc0;
} else {
cart.header_index = 0x40ffc0;
info.header_index = 0x40ffc0;
}
}
void Cartridge::load_sram() {
if(cart.sram_size == 0) {
if(info.ram_size == 0) {
sram = 0;
return;
}
FileReader ff(sram_fn);
if(!ff.ready()) {
sram = (uint8*)malloc(cart.sram_size);
memset(sram, 0, cart.sram_size);
sram = (uint8*)malloc(info.ram_size);
memset(sram, 0xff, info.ram_size);
return;
}
sram = ff.read(cart.sram_size);
sram = ff.read(info.ram_size);
}
void Cartridge::save_sram() {
if(cart.sram_size == 0)return;
if(info.ram_size == 0)return;
FileWriter ff(sram_fn);
if(!ff.ready())return;
ff.write(sram, cart.sram_size);
ff.write(sram, info.ram_size);
}
void Cartridge::load_rom(Reader *rf) {
base_rom = rf->read();
rom_size = rf->size();
if((rom_size & 0x7fff) == 0x0200) {
rom = base_rom + 512;
rom_size -= 512;
} else {
rom = base_rom;
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);
}
base_rom = rf.read(info.rom_size + (header ? 512 : 0));
rom = base_rom + (header ? 512 : 0);
cart.rom_size = rom_size;
cart.crc32 = 0xffffffff;
for(int32 i = 0; i < cart.rom_size; i++) {
cart.crc32 = crc32_adjust(cart.crc32, rom[i]);
info.crc32 = 0xffffffff;
for(int32 i = 0; i < info.rom_size; i++) {
info.crc32 = crc32_adjust(info.crc32, rom[i]);
}
cart.crc32 = ~cart.crc32;
}
void Cartridge::patch_rom(Reader *rf) {
uint8 *patch_data = rf->read();
uint32 patch_size = rf->size();
BPF bpf;
if(patch_size < 34)return;
uint32 target;
target = patch_data[BPF::INDEX_FORMAT + 0] << 0;
target |= patch_data[BPF::INDEX_FORMAT + 1] << 8;
target |= patch_data[BPF::INDEX_FORMAT + 2] << 16;
target |= patch_data[BPF::INDEX_FORMAT + 3] << 24;
if(target != BPF::FORMAT_SNES) {
alert("Warning: BPF patch file is not in SNES format!\n\n"
"The patch will still be applied, but it will not be "
"possible to determine whether the patch was created "
"against an image with a header or without a header.\n\n"
"bsnes is now forced to assume the patch was created "
"against a headerless source image. If this is not the "
"case, then patching will fail!\n\n"
"If you are the author of this patch, please recreate "
"the patch in SNES format.\n\n"
"If you are not the patch author, please contact the "
"author and ask them to create an SNES format BPF patch.");
}
if(bpf.apply_patch(patch_size, patch_data, rom_size, rom) == true) {
SafeFree(base_rom);
uint8 *temp = bpf.get_output_handle(rom_size);
base_rom = (uint8*)malloc(rom_size);
memcpy(base_rom, temp, rom_size);
rom = base_rom;
cart.rom_size = rom_size;
} else {
alert("Failed to apply patch.\n\nThis could be because the patch itself "
"does not match its internal checksum, because the ROM loaded does not "
"match the patch information for either the original or modified file, "
"or because the patched file does not match the checksum of either the "
"original or modified file that is stored inside the patch.\n\n"
"The original ROM image will be used instead.");
}
SafeFree(patch_data);
info.crc32 = ~info.crc32;
}
bool Cartridge::load(const char *fn) {
@@ -222,7 +229,7 @@ bool Cartridge::load(const char *fn) {
alert("Error loading image file (%s)!", rom_fn);
return false;
}
load_rom(static_cast<Reader*>(&ff));
load_rom(ff);
break;
}
#ifdef GZIP_SUPPORT
@@ -232,12 +239,12 @@ bool Cartridge::load(const char *fn) {
alert("Error loading image file (%s)!", rom_fn);
return false;
}
load_rom(static_cast<Reader*>(&gf));
load_rom(gf);
break;
}
case Reader::RF_ZIP: {
ZipReader zf(rom_fn);
load_rom(static_cast<Reader*>(&zf));
load_rom(zf);
break;
}
#endif
@@ -245,7 +252,7 @@ bool Cartridge::load(const char *fn) {
case Reader::RF_JMA: {
try {
JMAReader jf(rom_fn);
load_rom(static_cast<Reader*>(&jf));
load_rom(jf);
} catch(JMA::jma_errors jma_error) {
alert("Error loading image file (%s)!", rom_fn);
return false;
@@ -264,25 +271,6 @@ bool Cartridge::load(const char *fn) {
}
}
//check for bpf patch
#ifdef GZIP_SUPPORT
strcpy(patch_fn, sram_fn);
strcat(patch_fn, ".bpz");
if(fexists(patch_fn)) {
ZipReader zf(patch_fn);
patch_rom(static_cast<Reader*>(&zf));
} else {
#endif
strcpy(patch_fn, sram_fn);
strcat(patch_fn, ".bpf");
if(fexists(patch_fn)) {
FileReader ff(patch_fn);
patch_rom(static_cast<Reader*>(&ff));
}
#ifdef GZIP_SUPPORT
}
#endif
//add SRAM extension
strcat(sram_fn, ".");
strcat(sram_fn, config::fs.save_ext.sget());
@@ -318,13 +306,19 @@ bool Cartridge::load(const char *fn) {
strcat(cheat_fn, ".cht");
if(fexists(cheat_fn) == true) {
FileReader ff(cheat_fn);
cheat.load(static_cast<Reader*>(&ff));
cheat.load(ff);
}
if(read_database() == true) {
read_dbi();
} else {
find_header();
read_header();
}
find_header();
read_header();
load_sram();
cart_loaded = true;
r_mem->load_cart();
return true;
}
@@ -345,7 +339,7 @@ bool Cartridge::unload() {
if(cheat.count() > 0 || fexists(cheat_fn)) {
FileWriter ff(cheat_fn);
cheat.save(static_cast<Writer*>(&ff));
cheat.save(ff);
cheat.clear();
}
@@ -354,12 +348,13 @@ bool Cartridge::unload() {
}
Cartridge::Cartridge() {
load_database();
cart_loaded = false;
base_rom = 0;
rom = 0;
sram = 0;
rom_size = 0;
}
Cartridge::~Cartridge() {

View File

@@ -1,10 +1,24 @@
class Cartridge {
public:
/*****
* cart database
*****/
#include "db/db.h"
db_item dbi;
uint8 *database;
uint database_size;
uint database_blocksize;
void load_database();
bool read_database();
//
bool cart_loaded;
char rom_fn[4096], sram_fn[4096], cheat_fn[4096], patch_fn[4096];
uint8 *base_rom, *rom, *sram;
uint32 rom_size;
enum {
//header fields
@@ -18,28 +32,35 @@ enum {
VERSION = 0x1b,
ICKSUM = 0x1c,
CKSUM = 0x1e,
RESL = 0x3c,
RESH = 0x3d,
//regions
NTSC = 0,
PAL = 1,
//memory mappers
PCB = 0x00,
LOROM = 0x20,
HIROM = 0x21,
EXLOROM = 0x22,
EXHIROM = 0x25,
//special chip memory mappers
DSP1_LOROM_1MB = 1,
DSP1_LOROM_2MB = 2,
DSP1_HIROM = 3,
};
struct {
uint32 crc32;
uint32 header_index;
char name[128];
char pcb[32];
char name[32];
uint32 rom_size;
uint32 sram_size;
bool region;
uint32 mapper;
uint region;
uint mapper;
uint rom_size;
uint ram_size;
//set to true for games that need cart MMIO mapping (c4, dsp-n, ...),
//for games that map outside the standard MMIO range of $2000-$5fff
@@ -47,14 +68,20 @@ struct {
bool srtc;
bool sdd1;
bool c4;
bool dsp1;
bool dsp2;
bool obc1;
} cart;
void load_rom(Reader *rf);
void patch_rom(Reader *rf);
uint dsp1_mapper;
//HiROM / LoROM specific code
uint header_index;
} info;
void load_rom(Reader &rf);
void load_sram();
void save_sram();
void read_dbi();
void find_header();
void read_header();
bool loaded() { return cart_loaded; }

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;
}

View File

@@ -266,12 +266,12 @@ void Cheat::disable(uint32 n) {
* cheat file manipulation routines
*****/
bool Cheat::load(Reader *rf) {
if(!rf->ready())return false;
bool Cheat::load(Reader &rf) {
if(!rf.ready())return false;
uint8 *raw_data = rf->read();
uint8 *raw_data = rf.read();
string data;
raw_data[rf->size()] = 0;
raw_data[rf.size()] = 0;
strcpy(data, (char*)raw_data);
SafeFree(raw_data);
replace(data, "\r\n", "\n");
@@ -297,8 +297,8 @@ string line;
return true;
}
bool Cheat::save(Writer *wf) {
if(!wf->ready())return false;
bool Cheat::save(Writer &wf) {
if(!wf.ready())return false;
string data;
char t[4096];
@@ -308,7 +308,7 @@ char t[4096];
strcat(data, t);
}
wf->write((uint8*)strptr(data), strlen(data));
wf.write((uint8*)strptr(data), strlen(data));
return true;
}

View File

@@ -38,8 +38,8 @@ public:
bool enabled(uint32 n);
void enable (uint32 n);
void disable(uint32 n);
bool load(Reader *rf);
bool save(Writer *wf);
bool load(Reader &rf);
bool save(Writer &wf);
void clear();
Cheat();

View File

@@ -1,7 +1,7 @@
//Build OAM
void C4::op00_00() {
uint32 oamptr = ram[0x626] << 2;
for(int32 i=0x1fd;i>oamptr && i>=0;i-=4) {
for(int32 i = 0x1fd; i > oamptr && i >= 0; i -= 4) {
//clear oam-to-be
if(i >= 0)ram[i] = 0xe0;
}
@@ -19,58 +19,55 @@ uint8 sprcount;
sprcount = 128 - ram[0x626];
uint8 offset = (ram[0x626] & 3) * 2;
for(int pri=0x30;pri>=0;pri-=0x10) {
uint32 srcptr = 0x220;
for(int i=ram[0x620];i>0 && sprcount>0;i--, srcptr+=16) {
if((ram[srcptr + 4] & 0x30) != pri)continue;
sprx = readw(srcptr) - globalx;
spry = readw(srcptr + 2) - globaly;
sprname = ram[srcptr + 5];
sprattr = ram[srcptr + 4] | ram[srcptr + 6];
uint32 srcptr = 0x220;
for(int i = ram[0x620]; i > 0 && sprcount > 0; i--, srcptr += 16) {
sprx = readw(srcptr) - globalx;
spry = readw(srcptr + 2) - globaly;
sprname = ram[srcptr + 5];
sprattr = ram[srcptr + 4] | ram[srcptr + 6];
uint32 spraddr = readl(srcptr + 7);
if(r_mem->read(spraddr)) {
int16 x, y;
for(int sprcnt=r_mem->read(spraddr++);sprcnt>0 && sprcount>0;sprcnt--, spraddr+=4) {
x = (int8)r_mem->read(spraddr + 1);
if(sprattr & 0x40) {
x = -x - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
uint32 spraddr = readl(srcptr + 7);
if(r_mem->read(spraddr)) {
int16 x, y;
for(int sprcnt = r_mem->read(spraddr++); sprcnt > 0 && sprcount > 0; sprcnt--, spraddr += 4) {
x = (int8)r_mem->read(spraddr + 1);
if(sprattr & 0x40) {
x = -x - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
}
x += sprx;
if(x >= -16 && x <= 272) {
y = (int8)r_mem->read(spraddr + 2);
if(sprattr & 0x80) {
y = -y - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
}
x += sprx;
if(x >= -16 && x <= 272) {
y = (int8)r_mem->read(spraddr + 2);
if(sprattr & 0x80) {
y = -y - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
}
y += spry;
if(y >= -16 && y <= 224) {
ram[oamptr ] = (uint8)x;
ram[oamptr + 1] = (uint8)y;
ram[oamptr + 2] = sprname + r_mem->read(spraddr + 3);
ram[oamptr + 3] = sprattr ^ (r_mem->read(spraddr) & 0xc0);
ram[oamptr2] &= ~(3 << offset);
if(x & 0x100)ram[oamptr2] |= 1 << offset;
if(r_mem->read(spraddr) & 0x20)ram[oamptr2] |= 2 << offset;
oamptr += 4;
sprcount--;
offset = (offset + 2) & 6;
if(!offset)oamptr2++;
}
y += spry;
if(y >= -16 && y <= 224) {
ram[oamptr ] = (uint8)x;
ram[oamptr + 1] = (uint8)y;
ram[oamptr + 2] = sprname + r_mem->read(spraddr + 3);
ram[oamptr + 3] = sprattr ^ (r_mem->read(spraddr) & 0xc0);
ram[oamptr2] &= ~(3 << offset);
if(x & 0x100)ram[oamptr2] |= 1 << offset;
if(r_mem->read(spraddr) & 0x20)ram[oamptr2] |= 2 << offset;
oamptr += 4;
sprcount--;
offset = (offset + 2) & 6;
if(!offset)oamptr2++;
}
}
} else if(sprcount > 0) {
ram[oamptr ] = (uint8)sprx;
ram[oamptr + 1] = (uint8)spry;
ram[oamptr + 2] = sprname;
ram[oamptr + 3] = sprattr;
ram[oamptr2] &= ~(3 << offset);
if(sprx & 0x100)ram[oamptr2] |= 3 << offset;
else ram[oamptr2] |= 2 << offset;
oamptr += 4;
sprcount--;
offset = (offset + 2) & 6;
if(!offset)oamptr2++;
}
} else if(sprcount > 0) {
ram[oamptr ] = (uint8)sprx;
ram[oamptr + 1] = (uint8)spry;
ram[oamptr + 2] = sprname;
ram[oamptr + 3] = sprattr;
ram[oamptr2] &= ~(3 << offset);
if(sprx & 0x100)ram[oamptr2] |= 3 << offset;
else ram[oamptr2] |= 2 << offset;
oamptr += 4;
sprcount--;
offset = (offset + 2) & 6;
if(!offset)oamptr2++;
}
}
}
@@ -178,13 +175,11 @@ uint32 waveptr = read(0x1f83);
uint16 mask1 = 0xc0c0;
uint16 mask2 = 0x3f3f;
int32 i, j;
int16 height, temp;
for(j = 0; j < 0x10; j++) {
for(int j = 0; j < 0x10; j++) {
do {
height = -((int8)ram[waveptr + 0xb00]) - 16;
for(i = 0; i < 40; i++) {
temp = readw(destptr + wave_data[i]) & mask2;
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
for(int i = 0; i < 40; i++) {
uint16 temp = readw(destptr + wave_data[i]) & mask2;
if(height >= 0) {
if(height < 8) {
temp |= mask1 & readw(0xa00 + height * 2);
@@ -202,22 +197,22 @@ int16 height, temp;
destptr += 16;
do {
height = -((int8)ram[waveptr + 0xb00]) - 16;
for(i = 0; i < 40; i++) {
temp = readw(destptr + wave_data[i]) & mask2;
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
for(int i = 0; i < 40; i++) {
uint16 temp = readw(destptr + wave_data[i]) & mask2;
if(height >= 0) {
if(height < 8) {
temp |= mask1 & readw(0xa10 + height * 2);
} else {
temp |= mask1 & 0xff00;
}
writew(destptr + wave_data[i], temp);
height++;
}
waveptr = (waveptr + 1) & 0x7f;
mask1 = (mask1 >> 2) | (mask1 << 6);
mask2 = (mask2 >> 2) | (mask2 << 6);
writew(destptr + wave_data[i], temp);
height++;
}
waveptr = (waveptr + 1) & 0x7f;
mask1 = (mask1 >> 2) | (mask1 << 6);
mask2 = (mask2 >> 2) | (mask2 << 6);
} while(mask1 != 0xc0c0);
destptr += 16;
}

54
src/chip/dsp1/dsp1.cpp Normal file
View File

@@ -0,0 +1,54 @@
#include "../../base.h"
#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);
}
}

16
src/chip/dsp1/dsp1.h Normal file
View File

@@ -0,0 +1,16 @@
#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);
};

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

View File

@@ -1,13 +1,13 @@
class DSP2 {
public:
struct {
bool waiting_for_command;
uint command;
uint in_count, in_index;
uint out_count, out_index;
bool waiting_for_command;
uint command;
uint in_count, in_index;
uint out_count, out_index;
uint8 parameters[512];
uint8 output[512];
uint8 parameters[512];
uint8 output[512];
uint8 op05transparent;
bool op05haslen;
@@ -20,6 +20,7 @@ struct {
int op0doutlen;
int op0dinlen;
} status;
void init();
void enable();
void power();

View File

@@ -2,22 +2,15 @@ Config config_file;
namespace config {
FS::Path FS::base_path(0, "fs.base_path", "Directory that bsnes resides in", "");
FS::Path FS::rom_path(&config_file, "fs.rom_path",
"Default path to look for ROM files in (\"\" = use default directory)", "");
FS::Path FS::save_path(&config_file, "fs.save_path",
"Default path for all save RAM and cheat files (\"\" = use current directory)", "");
void FS::Path::sset(const char *_data) {
void fs_set_path(Setting &s, const char *data) {
string path;
strcpy(path, _data);
strcpy(path, data);
strunquote(path);
replace(path, "\\", "/");
//blank path?
if(strlen(path) == 0) {
Setting::sset(strptr(path));
s.sset(strptr(path));
return;
}
@@ -26,36 +19,38 @@ string path;
strcat(path, "/");
}
Setting::sset(strptr(path));
s.sset(strptr(path));
}
Setting FS::base_path(0, "fs.base_path",
"Directory that bsnes resides in", "");
Setting FS::rom_path(&config_file, "fs.rom_path",
"Default path to look for ROM files in (\"\" = use default directory)", "");
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");
SNES::VideoColorAdjust SNES::gamma_ramp(&config_file, "snes.colorfilter.gamma_ramp",
Setting SNES::gamma_ramp(&config_file, "snes.colorfilter.gamma_ramp",
"Use precalculated TV-style gamma ramp", true, Setting::TRUE_FALSE);
SNES::VideoColorAdjust SNES::sepia(&config_file, "snes.colorfilter.sepia",
Setting SNES::sepia(&config_file, "snes.colorfilter.sepia",
"Convert color to sepia tone", false, Setting::TRUE_FALSE);
SNES::VideoColorAdjust SNES::grayscale(&config_file, "snes.colorfilter.grayscale",
Setting SNES::grayscale(&config_file, "snes.colorfilter.grayscale",
"Convert color to grayscale tone", false, Setting::TRUE_FALSE);
SNES::VideoColorAdjust SNES::invert(&config_file, "snes.colorfilter.invert",
Setting SNES::invert(&config_file, "snes.colorfilter.invert",
"Invert output image colors", false, Setting::TRUE_FALSE);
SNES::VideoColorAdjust SNES::contrast(&config_file, "snes.colorfilter.contrast",
"", 0, Setting::DEC);
SNES::VideoColorAdjust SNES::brightness(&config_file, "snes.colorfilter.brightness",
"", 0, Setting::DEC);
SNES::VideoColorAdjust SNES::gamma(&config_file, "snes.colorfilter.gamma",
"", 100, Setting::DEC);
void SNES::VideoColorAdjust::set(uint32 _data) {
Setting::set(_data);
::snes->update_color_lookup_table();
}
Setting SNES::contrast(&config_file, "snes.colorfilter.contrast",
"Contrast", 0, Setting::DEC);
Setting SNES::brightness(&config_file, "snes.colorfilter.brightness",
"Brightness", 0, Setting::DEC);
Setting SNES::gamma(&config_file, "snes.colorfilter.gamma",
"Gamma", 80, Setting::DEC);
Setting SNES::ntsc_merge_fields(&config_file, "snes.ntsc_merge_fields",
"Merge fields in NTSC video filter\n"
"Set to true if using filter at any refresh rate other than 60hz\n"
"", false, Setting::TRUE_FALSE);
"", true, Setting::TRUE_FALSE);
Setting SNES::mute(&config_file, "snes.mute", "Mutes SNES audio output when enabled",
false, Setting::TRUE_FALSE);

View File

@@ -2,22 +2,15 @@ extern Config config_file;
namespace config {
void fs_set_path(Setting &s, const char *data);
extern struct FS {
static class Path : public Setting {
public:
void sset(const char *_data);
SettingOperators(Path);
} base_path, rom_path, save_path;
static Setting base_path, rom_path, save_path;
static Setting save_ext;
} fs;
extern struct SNES {
static class VideoColorAdjust : public Setting {
public:
void set(uint32 _data);
SettingOperators(VideoColorAdjust);
} gamma_ramp, sepia, grayscale, invert, contrast, brightness, gamma;
static Setting gamma_ramp, sepia, grayscale, invert, contrast, brightness, gamma;
static Setting ntsc_merge_fields;
static Setting mute;
} snes;

View File

@@ -22,53 +22,23 @@ void bCPU::run() {
return;
}
if(status.cycle_pos == 0) {
//interrupts only trigger on opcode edges
if(!run_state.irq && !run_state.stp) {
if(status.cycle_pos == 0) { //interrupts only trigger on opcode edges
if(run_state.irq && !run_state.stp) {
run_state.irq = false;
if(time.nmi_pending == true) {
time.nmi_pending = false;
aa.w = 0xffea;
run_state.irq = true;
aa.w = (regs.e == false) ? 0xffea : 0xfffa;
} else if(time.irq_pending == true) {
time.irq_pending = false;
aa.w = 0xffee;
run_state.irq = true;
aa.w = (regs.e == false) ? 0xffee : 0xfffe;
}
irq_run();
}
}
exec_cycle();
}
void bCPU::scanline() {
time.hdma_triggered = false;
if(vcounter() == (overscan() == false ? 227 : 242) && status.auto_joypad_poll == true) {
snes->poll_input(SNES::DEV_JOYPAD1);
snes->poll_input(SNES::DEV_JOYPAD2);
//When the SNES auto-polls the joypads, it writes 1, then 0 to
//$4016, then reads from each 16 times to get the joypad state
//information. As a result, the joypad read positions are set
//to 16 after such a poll. Position 16 is the controller
//connected status bit.
status.joypad1_read_pos = 16;
status.joypad2_read_pos = 16;
}
}
void bCPU::frame() {
time.nmi_read = 1;
time.nmi_line = 1;
time.nmi_transition = 0;
if(cpu_version == 2) {
time.hdmainit_trigger_pos = 12 + dma_counter();
} else {
time.hdmainit_trigger_pos = 12 + 8 - dma_counter();
}
time.hdmainit_triggered = false;
}
void bCPU::power() {
region = snes->region();
@@ -93,9 +63,6 @@ void bCPU::reset() {
regs.e = 1;
regs.mdr = 0x00;
//simulate pbr:pc push during reset irq vector
regs.s.l -= 3;
time_reset();
mmio_reset();
dma_reset();

View File

@@ -82,9 +82,7 @@ struct {
inline uint8 pio_status();
inline void run();
inline uint32 cycles_executed();
inline void scanline();
inline void frame();
inline uint32 clocks_executed();
inline void power();
inline void reset();

View File

@@ -1,8 +1,8 @@
void bCPU::last_cycle() {
//DMV27: keep previous nmi value,
//to allow wai and irq to work properly
time.nmi_pending = nmi_test() || time.nmi_pending;
time.irq_pending = irq_test();
time.nmi_pending |= nmi_test();
time.irq_pending |= irq_test();
run_state.irq = (time.nmi_pending || time.irq_pending);
}
void bCPU::pre_exec_cycle() {
@@ -56,12 +56,7 @@ static int z;
status.hdma_state = HDMASTATE_IDMASYNC3;
break;
case HDMASTATE_IDMASYNC3:
channel[z].hdma_active = channel[z].hdma_enabled;
if(channel[z].hdma_enabled) {
channel[z].hdma_addr = channel[z].srcaddr;
hdma_update(z); //updates status.hdma_cycle_count
}
if(++z < 8)break;
hdma_init();
if(!run_state.dma) {
status.hdma_state = HDMASTATE_ICPUSYNC;
} else {
@@ -89,7 +84,7 @@ static int z;
status.hdma_state = HDMASTATE_DMASYNC3;
break;
case HDMASTATE_DMASYNC3:
if(channel[z].hdma_active) {
if(channel[z].hdma_line_counter) {
add_cycles(8);
status.hdma_cycle_count += 8;
}
@@ -126,7 +121,7 @@ static int z;
status.dma_state = DMASTATE_DMASYNC3;
break;
case DMASTATE_DMASYNC3:
if(channel[z].active == true) {
if(channel[z].dma_enabled == true) {
add_cycles(8);
status.dma_cycle_count += 8;
}
@@ -144,12 +139,6 @@ static int z;
}
void bCPU::exec_cycle() {
//irq active? run one bus cycle of the irq event and return
if(run_state.irq) {
irq_run();
return;
}
if(status.cycle_pos) {
(this->*optbl[status.opcode])();
#ifdef DEBUGGER
@@ -164,7 +153,7 @@ void bCPU::exec_cycle() {
#ifdef DEBUGGER
snes->notify(SNES::CPU_EXEC_OPCODE_BEGIN);
#endif
status.opcode = op_read();
status.opcode = op_readpc();
status.cycle_pos = 1;
}

View File

@@ -1,57 +1,20 @@
/*
[IRQ cycles]
[0] pbr,pc ; opcode
[1] pbr,pc ; io
[2] 0,s ; pbr
[3] 0,s-1 ; pch
[4] 0,s-2 ; pcl
[5] 0,s-3 ; p
[6] 0,va ; aavl
[7] 0,va+1 ; aavh
*/
void bCPU::irq_run() {
//WDC documentation is incorrect, first cycle
//is a memory read fetch from PBR:PC
switch(status.cycle_pos++) {
case 0:
//read from PBR:PC, but do not increment PC counter
mem_read(regs.pc.d);
break;
case 1:
cpu_io();
if(regs.e)status.cycle_pos++;
break;
case 2:
stack_write(regs.pc.b);
break;
case 3:
stack_write(regs.pc.h);
break;
case 4:
stack_write(regs.pc.l);
break;
case 5:
//emulation-mode irqs clear brk bit 0x10
stack_write((regs.e) ? (regs.p & ~0x10) : regs.p);
break;
case 6:
//todo: test if NMI can override IRQ here...
rd.l = op_read(OPMODE_ADDR, aa.w);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
break;
case 7:
rd.h = op_read(OPMODE_ADDR, aa.w + 1);
regs.pc.w = rd.w;
#ifdef DEBUGGER
//let debugger know the new IRQ opcode address
snes->notify(SNES::CPU_EXEC_OPCODE_END);
#endif
status.cycle_pos = 0;
run_state.irq = false;
break;
}
mem_read(regs.pc.d);
cpu_io();
if(!regs.e)op_writestack(regs.pc.b);
op_writestack(regs.pc.h);
op_writestack(regs.pc.l);
op_writestack(regs.e ? (regs.p & ~0x10) : regs.p);
rd.l = op_readaddr(aa.w + 0);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
rd.h = op_readaddr(aa.w + 1);
regs.pc.w = rd.w;
#ifdef DEBUGGER
//let debugger know the new IRQ opcode address
snes->notify(SNES::CPU_EXEC_OPCODE_END);
#endif
}
bool bCPU::nmi_test() {
@@ -83,6 +46,5 @@ _true:
time.irq_transition = 0;
run_state.wai = false;
if(regs.p.i)return false;
return true;
return (regs.p.i) ? false : true;
}

View File

@@ -329,12 +329,12 @@ uint8 bCPU::mmio_r43xb(uint8 i) {
uint8 bCPU::mmio_read(uint16 addr) {
//APU
if(addr >= 0x2140 && addr <= 0x217f) {
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
return r_apu->port_read(addr & 3);
}
//HDMA
if(addr >= 0x4300 && addr <= 0x437f) {
if((addr & 0xff80) == 0x4300) { //$4300-$437f
uint i = (addr >> 4) & 7;
switch(addr & 0xf) {
case 0x0: return mmio_r43x0(i);
@@ -457,6 +457,7 @@ void bCPU::mmio_w4202(uint8 value) {
status.mul_a = value;
}
//WRMPYB
void bCPU::mmio_w4203(uint8 value) {
status.mul_b = value;
status.r4216 = status.mul_a * status.mul_b;
@@ -464,7 +465,7 @@ void bCPU::mmio_w4203(uint8 value) {
//WRDIVL
void bCPU::mmio_w4204(uint8 value) {
status.div_a = (status.div_a & 0xff00) | value;
status.div_a = (status.div_a & 0xff00) | (value);
}
//WRDIVH
@@ -481,29 +482,30 @@ void bCPU::mmio_w4206(uint8 value) {
//HTIMEL
void bCPU::mmio_w4207(uint8 value) {
status.hirq_pos = (status.hirq_pos & 0xff00) | value;
status.hirq_pos = ((status.hirq_pos & 0xff00) | value) & 0x01ff;
update_interrupts();
}
//HTIMEH
void bCPU::mmio_w4208(uint8 value) {
status.hirq_pos = (status.hirq_pos & 0x00ff) | (value << 8);
status.hirq_pos = ((status.hirq_pos & 0x00ff) | (value << 8)) & 0x01ff;
update_interrupts();
}
//VTIMEL
void bCPU::mmio_w4209(uint8 value) {
status.virq_pos = (status.virq_pos & 0xff00) | value;
status.virq_pos = ((status.virq_pos & 0xff00) | value) & 0x01ff;
update_interrupts();
}
//VTIMEH
void bCPU::mmio_w420a(uint8 value) {
status.virq_pos = (status.virq_pos & 0x00ff) | (value << 8);
status.virq_pos = ((status.virq_pos & 0x00ff) | (value << 8)) & 0x01ff;
update_interrupts();
}
//DMAEN
//DMA enable does not disable active HDMA channels
void bCPU::mmio_w420b(uint8 value) {
if(value != 0x00) {
run_state.dma = true;
@@ -511,11 +513,9 @@ void bCPU::mmio_w420b(uint8 value) {
}
for(int i = 0; i < 8; i++) {
if(value & (1 << i)) {
//DMA enable does not disable active HDMA channels
channel[i].active = true;
channel[i].read_index = 0;
}
channel[i].dma_enabled = bool(value & (1 << i));
//TODO: clearing read_index may interfere with DMA+HDMA occurring simultaneously
if(channel[i].dma_enabled)channel[i].read_index = 0;
}
}
@@ -523,7 +523,6 @@ void bCPU::mmio_w420b(uint8 value) {
void bCPU::mmio_w420c(uint8 value) {
for(int i = 0; i < 8; i++) {
channel[i].hdma_enabled = bool(value & (1 << i));
channel[i].hdma_active = bool(value & (1 << i));
}
}
@@ -599,13 +598,13 @@ void bCPU::mmio_w43xb(uint8 value, uint8 i) {
void bCPU::mmio_write(uint16 addr, uint8 data) {
//APU
if(addr >= 0x2140 && addr <= 0x217f) {
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
port_write(addr & 3, data);
return;
}
//HDMA
if(addr >= 0x4300 && addr <= 0x437f) {
if((addr & 0xff80) == 0x4300) { //$4300-$437f
uint i = (addr >> 4) & 7;
switch(addr & 0xf) {
case 0x0: mmio_w43x0(data, i); return;

View File

@@ -1,8 +1 @@
@del *.exe
@del op_misc.cpp
@del op_pc.cpp
@del op_read.cpp
@del op_rmw.cpp
@del op_write.cpp
@del optable.cpp
@del op.h

View File

@@ -23,68 +23,6 @@ void bCPU::cpu_c6(uint16 addr) {
}
}
uint32 bCPU::op_addr(uint8 mode, uint32 addr) {
switch(mode) {
case OPMODE_ADDR:
addr &= 0xffff;
break;
case OPMODE_LONG:
addr &= 0xffffff;
break;
case OPMODE_DBR:
addr = ((regs.db << 16) + addr) & 0xffffff;
break;
case OPMODE_PBR:
addr &= 0xffff;
addr = (regs.pc.b << 16) + addr;
break;
case OPMODE_DP:
addr &= 0xffff;
addr = (regs.d + addr) & 0xffff;
break;
case OPMODE_SP:
addr &= 0xffff;
addr = (regs.s + addr) & 0xffff;
break;
}
return addr;
}
uint8 bCPU::op_read() {
uint8 r;
r = mem_read(regs.pc.d);
regs.pc.w++;
return r;
}
uint8 bCPU::op_read(uint8 mode, uint32 addr) {
addr = op_addr(mode, addr);
return mem_read(addr);
}
void bCPU::op_write(uint8 mode, uint32 addr, uint8 value) {
addr = op_addr(mode, addr);
mem_write(addr, value);
}
uint8 bCPU::stack_read() {
if(regs.e) {
regs.s.l++;
} else {
regs.s.w++;
}
return mem_read(regs.s);
}
void bCPU::stack_write(uint8 value) {
mem_write(regs.s, value);
if(regs.e) {
regs.s.l--;
} else {
regs.s.w--;
}
}
void bCPU::init_op_tables() {
#include "optable.cpp"
}

View File

@@ -57,18 +57,6 @@ uint8 dp, sp;
inline void cpu_c4(uint16 x, uint16 y);
inline void cpu_c6(uint16 addr);
enum {
OPMODE_ADDR, OPMODE_LONG,
OPMODE_DBR, OPMODE_PBR,
OPMODE_DP, OPMODE_SP
};
inline uint32 op_addr(uint8 mode, uint32 addr);
inline uint8 op_read();
inline uint8 op_read(uint8 mode, uint32 addr);
inline void op_write(uint8 mode, uint32 addr, uint8 value);
inline uint8 stack_read();
inline void stack_write(uint8 value);
inline void init_op_tables();
#include "op.h"

View File

@@ -5,7 +5,7 @@ nop(0xea) {
wdm(0x42) {
1:last_cycle();
op_read();
op_readpc();
}
xba(0xeb) {
@@ -21,11 +21,11 @@ xba(0xeb) {
mvn(0x54, ++),
mvp(0x44, --) {
1:dp = op_read();
2:sp = op_read();
1:dp = op_readpc();
2:sp = op_readpc();
3:regs.db = dp;
rd.l = op_read(OPMODE_LONG, (sp << 16) | regs.x.w);
4:op_write(OPMODE_LONG, (dp << 16) | regs.y.w, rd.l);
rd.l = op_readlong((sp << 16) | regs.x.w);
4:op_writelong((dp << 16) | regs.y.w, rd.l);
5:cpu_io();
if(regs.p.x) { regs.x.l$1; regs.y.l$1; }
else { regs.x.w$1; regs.y.w$1; }
@@ -36,18 +36,18 @@ mvp(0x44, --) {
brk(0x00, 0xfffe, 0xffff, 0xffe6, 0xffe7),
cop(0x02, 0xfff4, 0xfff5, 0xffe4, 0xffe5) {
1:op_read();
1:op_readpc();
if(regs.e)skip;
2:stack_write(regs.pc.b);
3:stack_write(regs.pc.h);
4:stack_write(regs.pc.l);
5:stack_write(regs.p);
6:rd.l = op_read(OPMODE_LONG, (regs.e) ? $1 : $3);
2:op_writestack(regs.pc.b);
3:op_writestack(regs.pc.h);
4:op_writestack(regs.pc.l);
5:op_writestack(regs.p);
6:rd.l = op_readlong((regs.e) ? $1 : $3);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
7:last_cycle();
rd.h = op_read(OPMODE_LONG, (regs.e) ? $2 : $4);
rd.h = op_readlong((regs.e) ? $2 : $4);
regs.pc.w = rd.w;
}
@@ -104,7 +104,7 @@ sei(0x78, regs.p.i = 1) {
rep(0xc2, &=~),
sep(0xe2, |=) {
1:rd.l = op_read();
1:rd.l = op_readpc();
2:last_cycle();
cpu_io();
regs.p $1 rd.l;
@@ -200,9 +200,9 @@ phy(0x5a, regs.p.x, y),
phd(0x0b, 0, d) {
1:cpu_io();
if($1)skip;
2:stack_write(regs.$2.h);
2:op_writestack(regs.$2.h);
3:last_cycle();
stack_write(regs.$2.l);
op_writestack(regs.$2.l);
}
phb(0x8b, regs.db),
@@ -210,7 +210,7 @@ phk(0x4b, regs.pc.b),
php(0x08, regs.p) {
1:cpu_io();
2:last_cycle();
stack_write($1);
op_writestack($1);
}
pla(0x68, regs.p.m, a),
@@ -220,14 +220,14 @@ pld(0x2b, 0, d) {
1:cpu_io();
2:cpu_io();
3:if($1)last_cycle();
regs.$2.l = stack_read();
regs.$2.l = op_readstack();
if($1) {
regs.p.n = !!(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0);
end;
}
4:last_cycle();
regs.$2.h = stack_read();
regs.$2.h = op_readstack();
regs.p.n = !!(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0);
}
@@ -236,7 +236,7 @@ plb(0xab) {
1:cpu_io();
2:cpu_io();
3:last_cycle();
regs.db = stack_read();
regs.db = op_readstack();
regs.p.n = !!(regs.db & 0x80);
regs.p.z = (regs.db == 0);
}
@@ -245,7 +245,7 @@ plp(0x28) {
1:cpu_io();
2:cpu_io();
3:last_cycle();
regs.p = stack_read();
regs.p = op_readstack();
if(regs.e)regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
@@ -254,29 +254,29 @@ plp(0x28) {
}
pea(0xf4) {
1:aa.l = op_read();
2:aa.h = op_read();
3:stack_write(aa.h);
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_writestack(aa.h);
4:last_cycle();
stack_write(aa.l);
op_writestack(aa.l);
}
pei(0xd4) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
5:stack_write(aa.h);
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:op_writestack(aa.h);
6:last_cycle();
stack_write(aa.l);
op_writestack(aa.l);
}
per(0x62) {
1:aa.l = op_read();
2:aa.h = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_io();
rd.w = regs.pc.d + (int16)aa.w;
4:stack_write(rd.h);
4:op_writestack(rd.h);
5:last_cycle();
stack_write(rd.l);
op_writestack(rd.l);
}

View File

@@ -12,7 +12,7 @@ void bCPU::op_wdm() {
switch(status.cycle_pos++) {
case 1: {
last_cycle();
op_read();
op_readpc();
status.cycle_pos = 0;
} break;
}
@@ -39,17 +39,17 @@ void bCPU::op_xba() {
void bCPU::op_mvn() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
sp = op_read();
sp = op_readpc();
} break;
case 3: {
regs.db = dp;
rd.l = op_read(OPMODE_LONG, (sp << 16) | regs.x.w);
rd.l = op_readlong((sp << 16) | regs.x.w);
} break;
case 4: {
op_write(OPMODE_LONG, (dp << 16) | regs.y.w, rd.l);
op_writelong((dp << 16) | regs.y.w, rd.l);
} break;
case 5: {
cpu_io();
@@ -68,17 +68,17 @@ void bCPU::op_mvn() {
void bCPU::op_mvp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
sp = op_read();
sp = op_readpc();
} break;
case 3: {
regs.db = dp;
rd.l = op_read(OPMODE_LONG, (sp << 16) | regs.x.w);
rd.l = op_readlong((sp << 16) | regs.x.w);
} break;
case 4: {
op_write(OPMODE_LONG, (dp << 16) | regs.y.w, rd.l);
op_writelong((dp << 16) | regs.y.w, rd.l);
} break;
case 5: {
cpu_io();
@@ -97,30 +97,30 @@ void bCPU::op_mvp() {
void bCPU::op_brk() {
switch(status.cycle_pos++) {
case 1: {
op_read();
op_readpc();
if(regs.e)status.cycle_pos++;
} break;
case 2: {
stack_write(regs.pc.b);
op_writestack(regs.pc.b);
} break;
case 3: {
stack_write(regs.pc.h);
op_writestack(regs.pc.h);
} break;
case 4: {
stack_write(regs.pc.l);
op_writestack(regs.pc.l);
} break;
case 5: {
stack_write(regs.p);
op_writestack(regs.p);
} break;
case 6: {
rd.l = op_read(OPMODE_LONG, (regs.e) ? 0xfffe : 0xffe6);
rd.l = op_readlong((regs.e) ? 0xfffe : 0xffe6);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
} break;
case 7: {
last_cycle();
rd.h = op_read(OPMODE_LONG, (regs.e) ? 0xffff : 0xffe7);
rd.h = op_readlong((regs.e) ? 0xffff : 0xffe7);
regs.pc.w = rd.w;
status.cycle_pos = 0;
} break;
@@ -130,30 +130,30 @@ void bCPU::op_brk() {
void bCPU::op_cop() {
switch(status.cycle_pos++) {
case 1: {
op_read();
op_readpc();
if(regs.e)status.cycle_pos++;
} break;
case 2: {
stack_write(regs.pc.b);
op_writestack(regs.pc.b);
} break;
case 3: {
stack_write(regs.pc.h);
op_writestack(regs.pc.h);
} break;
case 4: {
stack_write(regs.pc.l);
op_writestack(regs.pc.l);
} break;
case 5: {
stack_write(regs.p);
op_writestack(regs.p);
} break;
case 6: {
rd.l = op_read(OPMODE_LONG, (regs.e) ? 0xfff4 : 0xffe4);
rd.l = op_readlong((regs.e) ? 0xfff4 : 0xffe4);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
} break;
case 7: {
last_cycle();
rd.h = op_read(OPMODE_LONG, (regs.e) ? 0xfff5 : 0xffe5);
rd.h = op_readlong((regs.e) ? 0xfff5 : 0xffe5);
regs.pc.w = rd.w;
status.cycle_pos = 0;
} break;
@@ -302,7 +302,7 @@ void bCPU::op_sei() {
void bCPU::op_rep() {
switch(status.cycle_pos++) {
case 1: {
rd.l = op_read();
rd.l = op_readpc();
} break;
case 2: {
last_cycle();
@@ -321,7 +321,7 @@ void bCPU::op_rep() {
void bCPU::op_sep() {
switch(status.cycle_pos++) {
case 1: {
rd.l = op_read();
rd.l = op_readpc();
} break;
case 2: {
last_cycle();
@@ -548,11 +548,11 @@ void bCPU::op_pha() {
if(regs.p.m)status.cycle_pos++;
} break;
case 2: {
stack_write(regs.a.h);
op_writestack(regs.a.h);
} break;
case 3: {
last_cycle();
stack_write(regs.a.l);
op_writestack(regs.a.l);
status.cycle_pos = 0;
} break;
}
@@ -565,11 +565,11 @@ void bCPU::op_phx() {
if(regs.p.x)status.cycle_pos++;
} break;
case 2: {
stack_write(regs.x.h);
op_writestack(regs.x.h);
} break;
case 3: {
last_cycle();
stack_write(regs.x.l);
op_writestack(regs.x.l);
status.cycle_pos = 0;
} break;
}
@@ -582,11 +582,11 @@ void bCPU::op_phy() {
if(regs.p.x)status.cycle_pos++;
} break;
case 2: {
stack_write(regs.y.h);
op_writestack(regs.y.h);
} break;
case 3: {
last_cycle();
stack_write(regs.y.l);
op_writestack(regs.y.l);
status.cycle_pos = 0;
} break;
}
@@ -599,11 +599,11 @@ void bCPU::op_phd() {
if(0)status.cycle_pos++;
} break;
case 2: {
stack_write(regs. d.h);
op_writestack(regs. d.h);
} break;
case 3: {
last_cycle();
stack_write(regs. d.l);
op_writestack(regs. d.l);
status.cycle_pos = 0;
} break;
}
@@ -616,7 +616,7 @@ void bCPU::op_phb() {
} break;
case 2: {
last_cycle();
stack_write(regs.db);
op_writestack(regs.db);
status.cycle_pos = 0;
} break;
}
@@ -629,7 +629,7 @@ void bCPU::op_phk() {
} break;
case 2: {
last_cycle();
stack_write(regs.pc.b);
op_writestack(regs.pc.b);
status.cycle_pos = 0;
} break;
}
@@ -642,7 +642,7 @@ void bCPU::op_php() {
} break;
case 2: {
last_cycle();
stack_write(regs.p);
op_writestack(regs.p);
status.cycle_pos = 0;
} break;
}
@@ -658,7 +658,7 @@ void bCPU::op_pla() {
} break;
case 3: {
if(regs.p.m)last_cycle();
regs.a.l = stack_read();
regs.a.l = op_readstack();
if(regs.p.m) {
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
@@ -667,7 +667,7 @@ void bCPU::op_pla() {
} break;
case 4: {
last_cycle();
regs.a.h = stack_read();
regs.a.h = op_readstack();
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
status.cycle_pos = 0;
@@ -685,7 +685,7 @@ void bCPU::op_plx() {
} break;
case 3: {
if(regs.p.x)last_cycle();
regs.x.l = stack_read();
regs.x.l = op_readstack();
if(regs.p.x) {
regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
@@ -694,7 +694,7 @@ void bCPU::op_plx() {
} break;
case 4: {
last_cycle();
regs.x.h = stack_read();
regs.x.h = op_readstack();
regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
status.cycle_pos = 0;
@@ -712,7 +712,7 @@ void bCPU::op_ply() {
} break;
case 3: {
if(regs.p.x)last_cycle();
regs.y.l = stack_read();
regs.y.l = op_readstack();
if(regs.p.x) {
regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
@@ -721,7 +721,7 @@ void bCPU::op_ply() {
} break;
case 4: {
last_cycle();
regs.y.h = stack_read();
regs.y.h = op_readstack();
regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
status.cycle_pos = 0;
@@ -739,7 +739,7 @@ void bCPU::op_pld() {
} break;
case 3: {
if(0)last_cycle();
regs. d.l = stack_read();
regs. d.l = op_readstack();
if(0) {
regs.p.n = !!(regs. d.l & 0x80);
regs.p.z = (regs. d.l == 0);
@@ -748,7 +748,7 @@ void bCPU::op_pld() {
} break;
case 4: {
last_cycle();
regs. d.h = stack_read();
regs. d.h = op_readstack();
regs.p.n = !!(regs. d.w & 0x8000);
regs.p.z = (regs. d.w == 0);
status.cycle_pos = 0;
@@ -766,7 +766,7 @@ void bCPU::op_plb() {
} break;
case 3: {
last_cycle();
regs.db = stack_read();
regs.db = op_readstack();
regs.p.n = !!(regs.db & 0x80);
regs.p.z = (regs.db == 0);
status.cycle_pos = 0;
@@ -784,7 +784,7 @@ void bCPU::op_plp() {
} break;
case 3: {
last_cycle();
regs.p = stack_read();
regs.p = op_readstack();
if(regs.e)regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
@@ -798,17 +798,17 @@ void bCPU::op_plp() {
void bCPU::op_pea() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
stack_write(aa.h);
op_writestack(aa.h);
} break;
case 4: {
last_cycle();
stack_write(aa.l);
op_writestack(aa.l);
status.cycle_pos = 0;
} break;
}
@@ -817,23 +817,23 @@ void bCPU::op_pea() {
void bCPU::op_pei() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
aa.l = op_read(OPMODE_DP, dp);
aa.l = op_readdp(dp);
} break;
case 4: {
aa.h = op_read(OPMODE_DP, dp + 1);
aa.h = op_readdp(dp + 1);
} break;
case 5: {
stack_write(aa.h);
op_writestack(aa.h);
} break;
case 6: {
last_cycle();
stack_write(aa.l);
op_writestack(aa.l);
status.cycle_pos = 0;
} break;
}
@@ -842,21 +842,21 @@ void bCPU::op_pei() {
void bCPU::op_per() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
rd.w = regs.pc.d + (int16)aa.w;
} break;
case 4: {
stack_write(rd.h);
op_writestack(rd.h);
} break;
case 5: {
last_cycle();
stack_write(rd.l);
op_writestack(rd.l);
status.cycle_pos = 0;
} break;
}

View File

@@ -7,7 +7,7 @@ bmi(0x30, regs.p.n),
bvc(0x50, !regs.p.v),
bvs(0x70, regs.p.v) {
1:if(!$1)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if($1) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
@@ -20,7 +20,7 @@ bvs(0x70, regs.p.v) {
}
bra(0x80) {
1:rd.l = op_read();
1:rd.l = op_readpc();
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
2:cpu_c6(aa.w);
@@ -29,119 +29,119 @@ bra(0x80) {
}
brl(0x82) {
1:rd.l = op_read();
2:rd.h = op_read();
1:rd.l = op_readpc();
2:rd.h = op_readpc();
3:last_cycle();
cpu_io();
regs.pc.w = regs.pc.d + (int16)rd.w;
}
jmp_addr(0x4c) {
1:rd.l = op_read();
1:rd.l = op_readpc();
2:last_cycle();
rd.h = op_read();
rd.h = op_readpc();
regs.pc.w = rd.w;
}
jmp_long(0x5c) {
1:rd.l = op_read();
2:rd.h = op_read();
1:rd.l = op_readpc();
2:rd.h = op_readpc();
3:last_cycle();
rd.b = op_read();
rd.b = op_readpc();
regs.pc.d = rd.d & 0xffffff;
}
jmp_iaddr(0x6c) {
1:aa.l = op_read();
2:aa.h = op_read();
3:rd.l = op_read(OPMODE_ADDR, aa.w);
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:rd.l = op_readaddr(aa.w);
4:last_cycle();
rd.h = op_read(OPMODE_ADDR, aa.w + 1);
rd.h = op_readaddr(aa.w + 1);
regs.pc.w = rd.w;
}
jmp_iaddrx(0x7c) {
1:aa.l = op_read();
2:aa.h = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_io();
4:rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w);
4:rd.l = op_readpbr(aa.w + regs.x.w);
5:last_cycle();
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1);
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
}
jmp_iladdr(0xdc) {
1:aa.l = op_read();
2:aa.h = op_read();
3:rd.l = op_read(OPMODE_ADDR, aa.w);
4:rd.h = op_read(OPMODE_ADDR, aa.w + 1);
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:rd.l = op_readaddr(aa.w);
4:rd.h = op_readaddr(aa.w + 1);
5:last_cycle();
rd.b = op_read(OPMODE_ADDR, aa.w + 2);
rd.b = op_readaddr(aa.w + 2);
regs.pc.d = rd.d & 0xffffff;
}
jsr_addr(0x20) {
1:aa.l = op_read();
2:aa.h = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_io();
4:regs.pc.w--;
stack_write(regs.pc.h);
op_writestack(regs.pc.h);
5:last_cycle();
stack_write(regs.pc.l);
op_writestack(regs.pc.l);
regs.pc.w = aa.w;
}
jsr_long(0x22) {
1:aa.l = op_read();
2:aa.h = op_read();
3:stack_write(regs.pc.b);
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_writestack(regs.pc.b);
4:cpu_io();
5:aa.b = op_read();
5:aa.b = op_readpc();
6:regs.pc.w--;
stack_write(regs.pc.h);
op_writestack(regs.pc.h);
7:last_cycle();
stack_write(regs.pc.l);
op_writestack(regs.pc.l);
regs.pc.d = aa.d & 0xffffff;
}
jsr_iaddrx(0xfc) {
1:aa.l = op_read();
2:stack_write(regs.pc.h);
3:stack_write(regs.pc.l);
4:aa.h = op_read();
1:aa.l = op_readpc();
2:op_writestack(regs.pc.h);
3:op_writestack(regs.pc.l);
4:aa.h = op_readpc();
5:cpu_io();
6:rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w);
6:rd.l = op_readpbr(aa.w + regs.x.w);
7:last_cycle();
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1);
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
}
rti(0x40) {
1:cpu_io();
2:cpu_io();
3:regs.p = stack_read();
3:regs.p = op_readstack();
if(regs.e)regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
4:rd.l = stack_read();
4:rd.l = op_readstack();
5:if(regs.e)last_cycle();
rd.h = stack_read();
rd.h = op_readstack();
if(regs.e) {
regs.pc.w = rd.w;
end;
}
6:last_cycle();
rd.b = stack_read();
rd.b = op_readstack();
regs.pc.d = rd.d & 0xffffff;
}
rts(0x60) {
1:cpu_io();
2:cpu_io();
3:rd.l = stack_read();
4:rd.h = stack_read();
3:rd.l = op_readstack();
4:rd.h = op_readstack();
5:last_cycle();
cpu_io();
regs.pc.w = rd.w;
@@ -151,10 +151,10 @@ rts(0x60) {
rtl(0x6b) {
1:cpu_io();
2:cpu_io();
3:rd.l = stack_read();
4:rd.h = stack_read();
3:rd.l = op_readstack();
4:rd.h = op_readstack();
5:last_cycle();
rd.b = stack_read();
rd.b = op_readstack();
regs.pc.d = rd.d & 0xffffff;
regs.pc.w++;
}

View File

@@ -2,7 +2,7 @@ void bCPU::op_bcc() {
switch(status.cycle_pos++) {
case 1: {
if(!!regs.p.c)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if(!regs.p.c) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
@@ -25,7 +25,7 @@ void bCPU::op_bcs() {
switch(status.cycle_pos++) {
case 1: {
if(!regs.p.c)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if(regs.p.c) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
@@ -48,7 +48,7 @@ void bCPU::op_bne() {
switch(status.cycle_pos++) {
case 1: {
if(!!regs.p.z)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if(!regs.p.z) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
@@ -71,7 +71,7 @@ void bCPU::op_beq() {
switch(status.cycle_pos++) {
case 1: {
if(!regs.p.z)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if(regs.p.z) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
@@ -94,7 +94,7 @@ void bCPU::op_bpl() {
switch(status.cycle_pos++) {
case 1: {
if(!!regs.p.n)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if(!regs.p.n) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
@@ -117,7 +117,7 @@ void bCPU::op_bmi() {
switch(status.cycle_pos++) {
case 1: {
if(!regs.p.n)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if(regs.p.n) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
@@ -140,7 +140,7 @@ void bCPU::op_bvc() {
switch(status.cycle_pos++) {
case 1: {
if(!!regs.p.v)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if(!regs.p.v) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
@@ -163,7 +163,7 @@ void bCPU::op_bvs() {
switch(status.cycle_pos++) {
case 1: {
if(!regs.p.v)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if(regs.p.v) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
@@ -185,7 +185,7 @@ void bCPU::op_bvs() {
void bCPU::op_bra() {
switch(status.cycle_pos++) {
case 1: {
rd.l = op_read();
rd.l = op_readpc();
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} break;
@@ -203,10 +203,10 @@ void bCPU::op_bra() {
void bCPU::op_brl() {
switch(status.cycle_pos++) {
case 1: {
rd.l = op_read();
rd.l = op_readpc();
} break;
case 2: {
rd.h = op_read();
rd.h = op_readpc();
} break;
case 3: {
last_cycle();
@@ -220,11 +220,11 @@ void bCPU::op_brl() {
void bCPU::op_jmp_addr() {
switch(status.cycle_pos++) {
case 1: {
rd.l = op_read();
rd.l = op_readpc();
} break;
case 2: {
last_cycle();
rd.h = op_read();
rd.h = op_readpc();
regs.pc.w = rd.w;
status.cycle_pos = 0;
} break;
@@ -234,14 +234,14 @@ void bCPU::op_jmp_addr() {
void bCPU::op_jmp_long() {
switch(status.cycle_pos++) {
case 1: {
rd.l = op_read();
rd.l = op_readpc();
} break;
case 2: {
rd.h = op_read();
rd.h = op_readpc();
} break;
case 3: {
last_cycle();
rd.b = op_read();
rd.b = op_readpc();
regs.pc.d = rd.d & 0xffffff;
status.cycle_pos = 0;
} break;
@@ -251,17 +251,17 @@ void bCPU::op_jmp_long() {
void bCPU::op_jmp_iaddr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_ADDR, aa.w);
rd.l = op_readaddr(aa.w);
} break;
case 4: {
last_cycle();
rd.h = op_read(OPMODE_ADDR, aa.w + 1);
rd.h = op_readaddr(aa.w + 1);
regs.pc.w = rd.w;
status.cycle_pos = 0;
} break;
@@ -271,20 +271,20 @@ void bCPU::op_jmp_iaddr() {
void bCPU::op_jmp_iaddrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w);
rd.l = op_readpbr(aa.w + regs.x.w);
} break;
case 5: {
last_cycle();
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1);
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
status.cycle_pos = 0;
} break;
@@ -294,20 +294,20 @@ void bCPU::op_jmp_iaddrx() {
void bCPU::op_jmp_iladdr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_ADDR, aa.w);
rd.l = op_readaddr(aa.w);
} break;
case 4: {
rd.h = op_read(OPMODE_ADDR, aa.w + 1);
rd.h = op_readaddr(aa.w + 1);
} break;
case 5: {
last_cycle();
rd.b = op_read(OPMODE_ADDR, aa.w + 2);
rd.b = op_readaddr(aa.w + 2);
regs.pc.d = rd.d & 0xffffff;
status.cycle_pos = 0;
} break;
@@ -317,21 +317,21 @@ void bCPU::op_jmp_iladdr() {
void bCPU::op_jsr_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
} break;
case 4: {
regs.pc.w--;
stack_write(regs.pc.h);
op_writestack(regs.pc.h);
} break;
case 5: {
last_cycle();
stack_write(regs.pc.l);
op_writestack(regs.pc.l);
regs.pc.w = aa.w;
status.cycle_pos = 0;
} break;
@@ -341,27 +341,27 @@ void bCPU::op_jsr_addr() {
void bCPU::op_jsr_long() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
stack_write(regs.pc.b);
op_writestack(regs.pc.b);
} break;
case 4: {
cpu_io();
} break;
case 5: {
aa.b = op_read();
aa.b = op_readpc();
} break;
case 6: {
regs.pc.w--;
stack_write(regs.pc.h);
op_writestack(regs.pc.h);
} break;
case 7: {
last_cycle();
stack_write(regs.pc.l);
op_writestack(regs.pc.l);
regs.pc.d = aa.d & 0xffffff;
status.cycle_pos = 0;
} break;
@@ -371,26 +371,26 @@ void bCPU::op_jsr_long() {
void bCPU::op_jsr_iaddrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
stack_write(regs.pc.h);
op_writestack(regs.pc.h);
} break;
case 3: {
stack_write(regs.pc.l);
op_writestack(regs.pc.l);
} break;
case 4: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 5: {
cpu_io();
} break;
case 6: {
rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w);
rd.l = op_readpbr(aa.w + regs.x.w);
} break;
case 7: {
last_cycle();
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1);
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
status.cycle_pos = 0;
} break;
@@ -406,7 +406,7 @@ void bCPU::op_rti() {
cpu_io();
} break;
case 3: {
regs.p = stack_read();
regs.p = op_readstack();
if(regs.e)regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
@@ -414,11 +414,11 @@ void bCPU::op_rti() {
}
} break;
case 4: {
rd.l = stack_read();
rd.l = op_readstack();
} break;
case 5: {
if(regs.e)last_cycle();
rd.h = stack_read();
rd.h = op_readstack();
if(regs.e) {
regs.pc.w = rd.w;
status.cycle_pos = 0;
@@ -426,7 +426,7 @@ void bCPU::op_rti() {
} break;
case 6: {
last_cycle();
rd.b = stack_read();
rd.b = op_readstack();
regs.pc.d = rd.d & 0xffffff;
status.cycle_pos = 0;
} break;
@@ -442,10 +442,10 @@ void bCPU::op_rts() {
cpu_io();
} break;
case 3: {
rd.l = stack_read();
rd.l = op_readstack();
} break;
case 4: {
rd.h = stack_read();
rd.h = op_readstack();
} break;
case 5: {
last_cycle();
@@ -466,14 +466,14 @@ void bCPU::op_rtl() {
cpu_io();
} break;
case 3: {
rd.l = stack_read();
rd.l = op_readstack();
} break;
case 4: {
rd.h = stack_read();
rd.h = op_readstack();
} break;
case 5: {
last_cycle();
rd.b = stack_read();
rd.b = op_readstack();
regs.pc.d = rd.d & 0xffffff;
regs.pc.w++;
status.cycle_pos = 0;

View File

@@ -10,10 +10,10 @@ ldy_const(0xa0, ldy, regs.p.x),
ora_const(0x09, ora, regs.p.m),
sbc_const(0xe9, sbc, regs.p.m) {
1:if($2)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if($2) { op_$1_b(); end; }
2:last_cycle();
rd.h = op_read();
rd.h = op_readpc();
op_$1_w();
}
@@ -29,13 +29,13 @@ ldx_addr(0xae, ldx, regs.p.x),
ldy_addr(0xac, ldy, regs.p.x),
ora_addr(0x0d, ora, regs.p.m),
sbc_addr(0xed, sbc, regs.p.m) {
1:aa.l = op_read();
2:aa.h = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:if($2)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if($2) { op_$1_b(); end; }
4:last_cycle();
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
op_$1_w();
}
@@ -48,14 +48,14 @@ lda_addrx(0xbd, lda, regs.p.m),
ldy_addrx(0xbc, ldy, regs.p.x),
ora_addrx(0x1d, ora, regs.p.m),
sbc_addrx(0xfd, sbc, regs.p.m) {
1:aa.l = op_read();
2:aa.h = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_c4(aa.w, aa.w + regs.x.w);
4:if($2)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w);
rd.l = op_readdbr(aa.w + regs.x.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1);
rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_$1_w();
}
@@ -67,14 +67,14 @@ lda_addry(0xb9, lda, regs.p.m),
ldx_addry(0xbe, ldx, regs.p.x),
ora_addry(0x19, ora, regs.p.m),
sbc_addry(0xf9, sbc, regs.p.m) {
1:aa.l = op_read();
2:aa.h = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_c4(aa.w, aa.w + regs.y.w);
4:if($2)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w);
rd.l = op_readdbr(aa.w + regs.y.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1);
rd.h = op_readdbr(aa.w + regs.y.w + 1);
op_$1_w();
}
@@ -85,14 +85,14 @@ eor_long(0x4f, eor, regs.p.m),
lda_long(0xaf, lda, regs.p.m),
ora_long(0x0f, ora, regs.p.m),
sbc_long(0xef, sbc, regs.p.m) {
1:aa.l = op_read();
2:aa.h = op_read();
3:aa.b = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if($2)last_cycle();
rd.l = op_read(OPMODE_LONG, aa.d);
rd.l = op_readlong(aa.d);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_read(OPMODE_LONG, aa.d + 1);
rd.h = op_readlong(aa.d + 1);
op_$1_w();
}
@@ -103,14 +103,14 @@ eor_longx(0x5f, eor, regs.p.m),
lda_longx(0xbf, lda, regs.p.m),
ora_longx(0x1f, ora, regs.p.m),
sbc_longx(0xff, sbc, regs.p.m) {
1:aa.l = op_read();
2:aa.h = op_read();
3:aa.b = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if($2)last_cycle();
rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w);
rd.l = op_readlong(aa.d + regs.x.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1);
rd.h = op_readlong(aa.d + regs.x.w + 1);
op_$1_w();
}
@@ -126,13 +126,13 @@ ldx_dp(0xa6, ldx, regs.p.x),
ldy_dp(0xa4, ldy, regs.p.x),
ora_dp(0x05, ora, regs.p.m),
sbc_dp(0xe5, sbc, regs.p.m) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:if($2)last_cycle();
rd.l = op_read(OPMODE_DP, dp);
rd.l = op_readdp(dp);
if($2) { op_$1_b(); end; }
4:last_cycle();
rd.h = op_read(OPMODE_DP, dp + 1);
rd.h = op_readdp(dp + 1);
op_$1_w();
}
@@ -145,26 +145,26 @@ lda_dpx(0xb5, lda, regs.p.m),
ldy_dpx(0xb4, ldy, regs.p.x),
ora_dpx(0x15, ora, regs.p.m),
sbc_dpx(0xf5, sbc, regs.p.m) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
4:if($2)last_cycle();
rd.l = op_read(OPMODE_DP, dp + regs.x.w);
rd.l = op_readdp(dp + regs.x.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
rd.h = op_readdp(dp + regs.x.w + 1);
op_$1_w();
}
ldx_dpy(0xb6, ldx, regs.p.x) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
4:if($2)last_cycle();
rd.l = op_read(OPMODE_DP, dp + regs.y.w);
rd.l = op_readdp(dp + regs.y.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_read(OPMODE_DP, dp + regs.y.w + 1);
rd.h = op_readdp(dp + regs.y.w + 1);
op_$1_w();
}
@@ -175,15 +175,15 @@ eor_idp(0x52, eor, regs.p.m),
lda_idp(0xb2, lda, regs.p.m),
ora_idp(0x12, ora, regs.p.m),
sbc_idp(0xf2, sbc, regs.p.m) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:if($2)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if($2) { op_$1_b(); end; }
6:last_cycle();
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
op_$1_w();
}
@@ -194,16 +194,16 @@ eor_idpx(0x41, eor, regs.p.m),
lda_idpx(0xa1, lda, regs.p.m),
ora_idpx(0x01, ora, regs.p.m),
sbc_idpx(0xe1, sbc, regs.p.m) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
4:aa.l = op_read(OPMODE_DP, dp + regs.x.w);
5:aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
4:aa.l = op_readdp(dp + regs.x.w);
5:aa.h = op_readdp(dp + regs.x.w + 1);
6:if($2)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
op_$1_w();
}
@@ -214,16 +214,16 @@ eor_idpy(0x51, eor, regs.p.m),
lda_idpy(0xb1, lda, regs.p.m),
ora_idpy(0x11, ora, regs.p.m),
sbc_idpy(0xf1, sbc, regs.p.m) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:cpu_c4(aa.w, aa.w + regs.y.w);
6:if($2)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w);
rd.l = op_readdbr(aa.w + regs.y.w);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1);
rd.h = op_readdbr(aa.w + regs.y.w + 1);
op_$1_w();
}
@@ -234,16 +234,16 @@ eor_ildp(0x47, eor, regs.p.m),
lda_ildp(0xa7, lda, regs.p.m),
ora_ildp(0x07, ora, regs.p.m),
sbc_ildp(0xe7, sbc, regs.p.m) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
5:aa.b = op_read(OPMODE_DP, dp + 2);
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if($2)last_cycle();
rd.l = op_read(OPMODE_LONG, aa.d);
rd.l = op_readlong(aa.d);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_read(OPMODE_LONG, aa.d + 1);
rd.h = op_readlong(aa.d + 1);
op_$1_w();
}
@@ -254,16 +254,16 @@ eor_ildpy(0x57, eor, regs.p.m),
lda_ildpy(0xb7, lda, regs.p.m),
ora_ildpy(0x17, ora, regs.p.m),
sbc_ildpy(0xf7, sbc, regs.p.m) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
5:aa.b = op_read(OPMODE_DP, dp + 2);
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if($2)last_cycle();
rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w);
rd.l = op_readlong(aa.d + regs.y.w);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1);
rd.h = op_readlong(aa.d + regs.y.w + 1);
op_$1_w();
}
@@ -274,13 +274,13 @@ eor_sr(0x43, eor, regs.p.m),
lda_sr(0xa3, lda, regs.p.m),
ora_sr(0x03, ora, regs.p.m),
sbc_sr(0xe3, sbc, regs.p.m) {
1:sp = op_read();
1:sp = op_readpc();
2:cpu_io();
3:if($2)last_cycle();
rd.l = op_read(OPMODE_SP, sp);
rd.l = op_readsp(sp);
if($2) { op_$1_b(); end; }
4:last_cycle();
rd.h = op_read(OPMODE_SP, sp + 1);
rd.h = op_readsp(sp + 1);
op_$1_w();
}
@@ -291,27 +291,27 @@ eor_isry(0x53, eor),
lda_isry(0xb3, lda),
ora_isry(0x13, ora),
sbc_isry(0xf3, sbc) {
1:sp = op_read();
1:sp = op_readpc();
2:cpu_io();
3:aa.l = op_read(OPMODE_SP, sp);
4:aa.h = op_read(OPMODE_SP, sp + 1);
3:aa.l = op_readsp(sp);
4:aa.h = op_readsp(sp + 1);
5:cpu_io();
6:if(regs.p.m)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w);
rd.l = op_readdbr(aa.w + regs.y.w);
if(regs.p.m) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1);
rd.h = op_readdbr(aa.w + regs.y.w + 1);
op_$1_w();
}
bit_const(0x89) {
1:if(regs.p.m)last_cycle();
rd.l = op_read();
rd.l = op_readpc();
if(regs.p.m) {
regs.p.z = ((rd.l & regs.a.l) == 0);
end;
}
2:last_cycle();
rd.h = op_read();
rd.h = op_readpc();
regs.p.z = ((rd.w & regs.a.w) == 0);
}

File diff suppressed because it is too large Load Diff

View File

@@ -110,17 +110,17 @@ rol_addr(0x2e, rol),
ror_addr(0x6e, ror),
trb_addr(0x1c, trb),
tsb_addr(0x0c, tsb) {
1:aa.l = op_read();
2:aa.h = op_read();
3:rd.l = op_read(OPMODE_DBR, aa.w);
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:rd.l = op_readdbr(aa.w);
if(regs.p.m)skip;
4:rd.h = op_read(OPMODE_DBR, aa.w + 1);
4:rd.h = op_readdbr(aa.w + 1);
5:cpu_io();
if(regs.p.m) { op_$1_b(); skip; }
else op_$1_w();
6:op_write(OPMODE_DBR, aa.w + 1, rd.h);
6:op_writedbr(aa.w + 1, rd.h);
7:last_cycle();
op_write(OPMODE_DBR, aa.w, rd.l);
op_writedbr(aa.w, rd.l);
}
inc_addrx(0xfe, inc),
@@ -129,18 +129,18 @@ asl_addrx(0x1e, asl),
lsr_addrx(0x5e, lsr),
rol_addrx(0x3e, rol),
ror_addrx(0x7e, ror) {
1:aa.l = op_read();
2:aa.h = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_io();
4:rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w);
4:rd.l = op_readdbr(aa.w + regs.x.w);
if(regs.p.m)skip;
5:rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1);
5:rd.h = op_readdbr(aa.w + regs.x.w + 1);
6:cpu_io();
if(regs.p.m) { op_$1_b(); skip; }
else op_$1_w();
7:op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h);
7:op_writedbr(aa.w + regs.x.w + 1, rd.h);
8:last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l);
op_writedbr(aa.w + regs.x.w, rd.l);
}
inc_dp(0xe6, inc),
@@ -151,17 +151,17 @@ rol_dp(0x26, rol),
ror_dp(0x66, ror),
trb_dp(0x14, trb),
tsb_dp(0x04, tsb) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:rd.l = op_read(OPMODE_DP, dp);
3:rd.l = op_readdp(dp);
if(regs.p.m)skip;
4:rd.h = op_read(OPMODE_DP, dp + 1);
4:rd.h = op_readdp(dp + 1);
5:cpu_io();
if(regs.p.m) { op_$1_b(); skip; }
else op_$1_w();
6:op_write(OPMODE_DP, dp + 1, rd.h);
6:op_writedp(dp + 1, rd.h);
7:last_cycle();
op_write(OPMODE_DP, dp, rd.l);
op_writedp(dp, rd.l);
}
inc_dpx(0xf6, inc),
@@ -170,16 +170,16 @@ asl_dpx(0x16, asl),
lsr_dpx(0x56, lsr),
rol_dpx(0x36, rol),
ror_dpx(0x76, ror) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
4:rd.l = op_read(OPMODE_DP, dp + regs.x.w);
4:rd.l = op_readdp(dp + regs.x.w);
if(regs.p.m)skip;
5:rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
5:rd.h = op_readdp(dp + regs.x.w + 1);
6:cpu_io();
if(regs.p.m) { op_$1_b(); skip; }
else op_$1_w();
7:op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h);
7:op_writedp(dp + regs.x.w + 1, rd.h);
8:last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, rd.l);
op_writedp(dp + regs.x.w, rd.l);
}

View File

@@ -207,17 +207,17 @@ void bCPU::op_ror() {
void bCPU::op_inc_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
} break;
case 5: {
cpu_io();
@@ -225,11 +225,11 @@ void bCPU::op_inc_addr() {
else op_inc_w();
} break;
case 6: {
op_write(OPMODE_DBR, aa.w + 1, rd.h);
op_writedbr(aa.w + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w, rd.l);
op_writedbr(aa.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -238,17 +238,17 @@ void bCPU::op_inc_addr() {
void bCPU::op_dec_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
} break;
case 5: {
cpu_io();
@@ -256,11 +256,11 @@ void bCPU::op_dec_addr() {
else op_dec_w();
} break;
case 6: {
op_write(OPMODE_DBR, aa.w + 1, rd.h);
op_writedbr(aa.w + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w, rd.l);
op_writedbr(aa.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -269,17 +269,17 @@ void bCPU::op_dec_addr() {
void bCPU::op_asl_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
} break;
case 5: {
cpu_io();
@@ -287,11 +287,11 @@ void bCPU::op_asl_addr() {
else op_asl_w();
} break;
case 6: {
op_write(OPMODE_DBR, aa.w + 1, rd.h);
op_writedbr(aa.w + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w, rd.l);
op_writedbr(aa.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -300,17 +300,17 @@ void bCPU::op_asl_addr() {
void bCPU::op_lsr_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
} break;
case 5: {
cpu_io();
@@ -318,11 +318,11 @@ void bCPU::op_lsr_addr() {
else op_lsr_w();
} break;
case 6: {
op_write(OPMODE_DBR, aa.w + 1, rd.h);
op_writedbr(aa.w + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w, rd.l);
op_writedbr(aa.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -331,17 +331,17 @@ void bCPU::op_lsr_addr() {
void bCPU::op_rol_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
} break;
case 5: {
cpu_io();
@@ -349,11 +349,11 @@ void bCPU::op_rol_addr() {
else op_rol_w();
} break;
case 6: {
op_write(OPMODE_DBR, aa.w + 1, rd.h);
op_writedbr(aa.w + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w, rd.l);
op_writedbr(aa.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -362,17 +362,17 @@ void bCPU::op_rol_addr() {
void bCPU::op_ror_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
} break;
case 5: {
cpu_io();
@@ -380,11 +380,11 @@ void bCPU::op_ror_addr() {
else op_ror_w();
} break;
case 6: {
op_write(OPMODE_DBR, aa.w + 1, rd.h);
op_writedbr(aa.w + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w, rd.l);
op_writedbr(aa.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -393,17 +393,17 @@ void bCPU::op_ror_addr() {
void bCPU::op_trb_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
} break;
case 5: {
cpu_io();
@@ -411,11 +411,11 @@ void bCPU::op_trb_addr() {
else op_trb_w();
} break;
case 6: {
op_write(OPMODE_DBR, aa.w + 1, rd.h);
op_writedbr(aa.w + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w, rd.l);
op_writedbr(aa.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -424,17 +424,17 @@ void bCPU::op_trb_addr() {
void bCPU::op_tsb_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
rd.l = op_read(OPMODE_DBR, aa.w);
rd.l = op_readdbr(aa.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DBR, aa.w + 1);
rd.h = op_readdbr(aa.w + 1);
} break;
case 5: {
cpu_io();
@@ -442,11 +442,11 @@ void bCPU::op_tsb_addr() {
else op_tsb_w();
} break;
case 6: {
op_write(OPMODE_DBR, aa.w + 1, rd.h);
op_writedbr(aa.w + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w, rd.l);
op_writedbr(aa.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -455,20 +455,20 @@ void bCPU::op_tsb_addr() {
void bCPU::op_inc_addrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w);
rd.l = op_readdbr(aa.w + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1);
rd.h = op_readdbr(aa.w + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -476,11 +476,11 @@ void bCPU::op_inc_addrx() {
else op_inc_w();
} break;
case 7: {
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h);
op_writedbr(aa.w + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l);
op_writedbr(aa.w + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -489,20 +489,20 @@ void bCPU::op_inc_addrx() {
void bCPU::op_dec_addrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w);
rd.l = op_readdbr(aa.w + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1);
rd.h = op_readdbr(aa.w + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -510,11 +510,11 @@ void bCPU::op_dec_addrx() {
else op_dec_w();
} break;
case 7: {
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h);
op_writedbr(aa.w + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l);
op_writedbr(aa.w + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -523,20 +523,20 @@ void bCPU::op_dec_addrx() {
void bCPU::op_asl_addrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w);
rd.l = op_readdbr(aa.w + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1);
rd.h = op_readdbr(aa.w + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -544,11 +544,11 @@ void bCPU::op_asl_addrx() {
else op_asl_w();
} break;
case 7: {
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h);
op_writedbr(aa.w + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l);
op_writedbr(aa.w + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -557,20 +557,20 @@ void bCPU::op_asl_addrx() {
void bCPU::op_lsr_addrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w);
rd.l = op_readdbr(aa.w + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1);
rd.h = op_readdbr(aa.w + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -578,11 +578,11 @@ void bCPU::op_lsr_addrx() {
else op_lsr_w();
} break;
case 7: {
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h);
op_writedbr(aa.w + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l);
op_writedbr(aa.w + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -591,20 +591,20 @@ void bCPU::op_lsr_addrx() {
void bCPU::op_rol_addrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w);
rd.l = op_readdbr(aa.w + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1);
rd.h = op_readdbr(aa.w + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -612,11 +612,11 @@ void bCPU::op_rol_addrx() {
else op_rol_w();
} break;
case 7: {
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h);
op_writedbr(aa.w + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l);
op_writedbr(aa.w + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -625,20 +625,20 @@ void bCPU::op_rol_addrx() {
void bCPU::op_ror_addrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w);
rd.l = op_readdbr(aa.w + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DBR, aa.w + regs.x.w + 1);
rd.h = op_readdbr(aa.w + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -646,11 +646,11 @@ void bCPU::op_ror_addrx() {
else op_ror_w();
} break;
case 7: {
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, rd.h);
op_writedbr(aa.w + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, rd.l);
op_writedbr(aa.w + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -659,17 +659,17 @@ void bCPU::op_ror_addrx() {
void bCPU::op_inc_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
rd.l = op_read(OPMODE_DP, dp);
rd.l = op_readdp(dp);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DP, dp + 1);
rd.h = op_readdp(dp + 1);
} break;
case 5: {
cpu_io();
@@ -677,11 +677,11 @@ void bCPU::op_inc_dp() {
else op_inc_w();
} break;
case 6: {
op_write(OPMODE_DP, dp + 1, rd.h);
op_writedp(dp + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DP, dp, rd.l);
op_writedp(dp, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -690,17 +690,17 @@ void bCPU::op_inc_dp() {
void bCPU::op_dec_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
rd.l = op_read(OPMODE_DP, dp);
rd.l = op_readdp(dp);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DP, dp + 1);
rd.h = op_readdp(dp + 1);
} break;
case 5: {
cpu_io();
@@ -708,11 +708,11 @@ void bCPU::op_dec_dp() {
else op_dec_w();
} break;
case 6: {
op_write(OPMODE_DP, dp + 1, rd.h);
op_writedp(dp + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DP, dp, rd.l);
op_writedp(dp, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -721,17 +721,17 @@ void bCPU::op_dec_dp() {
void bCPU::op_asl_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
rd.l = op_read(OPMODE_DP, dp);
rd.l = op_readdp(dp);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DP, dp + 1);
rd.h = op_readdp(dp + 1);
} break;
case 5: {
cpu_io();
@@ -739,11 +739,11 @@ void bCPU::op_asl_dp() {
else op_asl_w();
} break;
case 6: {
op_write(OPMODE_DP, dp + 1, rd.h);
op_writedp(dp + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DP, dp, rd.l);
op_writedp(dp, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -752,17 +752,17 @@ void bCPU::op_asl_dp() {
void bCPU::op_lsr_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
rd.l = op_read(OPMODE_DP, dp);
rd.l = op_readdp(dp);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DP, dp + 1);
rd.h = op_readdp(dp + 1);
} break;
case 5: {
cpu_io();
@@ -770,11 +770,11 @@ void bCPU::op_lsr_dp() {
else op_lsr_w();
} break;
case 6: {
op_write(OPMODE_DP, dp + 1, rd.h);
op_writedp(dp + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DP, dp, rd.l);
op_writedp(dp, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -783,17 +783,17 @@ void bCPU::op_lsr_dp() {
void bCPU::op_rol_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
rd.l = op_read(OPMODE_DP, dp);
rd.l = op_readdp(dp);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DP, dp + 1);
rd.h = op_readdp(dp + 1);
} break;
case 5: {
cpu_io();
@@ -801,11 +801,11 @@ void bCPU::op_rol_dp() {
else op_rol_w();
} break;
case 6: {
op_write(OPMODE_DP, dp + 1, rd.h);
op_writedp(dp + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DP, dp, rd.l);
op_writedp(dp, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -814,17 +814,17 @@ void bCPU::op_rol_dp() {
void bCPU::op_ror_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
rd.l = op_read(OPMODE_DP, dp);
rd.l = op_readdp(dp);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DP, dp + 1);
rd.h = op_readdp(dp + 1);
} break;
case 5: {
cpu_io();
@@ -832,11 +832,11 @@ void bCPU::op_ror_dp() {
else op_ror_w();
} break;
case 6: {
op_write(OPMODE_DP, dp + 1, rd.h);
op_writedp(dp + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DP, dp, rd.l);
op_writedp(dp, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -845,17 +845,17 @@ void bCPU::op_ror_dp() {
void bCPU::op_trb_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
rd.l = op_read(OPMODE_DP, dp);
rd.l = op_readdp(dp);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DP, dp + 1);
rd.h = op_readdp(dp + 1);
} break;
case 5: {
cpu_io();
@@ -863,11 +863,11 @@ void bCPU::op_trb_dp() {
else op_trb_w();
} break;
case 6: {
op_write(OPMODE_DP, dp + 1, rd.h);
op_writedp(dp + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DP, dp, rd.l);
op_writedp(dp, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -876,17 +876,17 @@ void bCPU::op_trb_dp() {
void bCPU::op_tsb_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
rd.l = op_read(OPMODE_DP, dp);
rd.l = op_readdp(dp);
if(regs.p.m)status.cycle_pos++;
} break;
case 4: {
rd.h = op_read(OPMODE_DP, dp + 1);
rd.h = op_readdp(dp + 1);
} break;
case 5: {
cpu_io();
@@ -894,11 +894,11 @@ void bCPU::op_tsb_dp() {
else op_tsb_w();
} break;
case 6: {
op_write(OPMODE_DP, dp + 1, rd.h);
op_writedp(dp + 1, rd.h);
} break;
case 7: {
last_cycle();
op_write(OPMODE_DP, dp, rd.l);
op_writedp(dp, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -907,7 +907,7 @@ void bCPU::op_tsb_dp() {
void bCPU::op_inc_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -916,11 +916,11 @@ void bCPU::op_inc_dpx() {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DP, dp + regs.x.w);
rd.l = op_readdp(dp + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
rd.h = op_readdp(dp + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -928,11 +928,11 @@ void bCPU::op_inc_dpx() {
else op_inc_w();
} break;
case 7: {
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h);
op_writedp(dp + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, rd.l);
op_writedp(dp + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -941,7 +941,7 @@ void bCPU::op_inc_dpx() {
void bCPU::op_dec_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -950,11 +950,11 @@ void bCPU::op_dec_dpx() {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DP, dp + regs.x.w);
rd.l = op_readdp(dp + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
rd.h = op_readdp(dp + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -962,11 +962,11 @@ void bCPU::op_dec_dpx() {
else op_dec_w();
} break;
case 7: {
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h);
op_writedp(dp + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, rd.l);
op_writedp(dp + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -975,7 +975,7 @@ void bCPU::op_dec_dpx() {
void bCPU::op_asl_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -984,11 +984,11 @@ void bCPU::op_asl_dpx() {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DP, dp + regs.x.w);
rd.l = op_readdp(dp + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
rd.h = op_readdp(dp + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -996,11 +996,11 @@ void bCPU::op_asl_dpx() {
else op_asl_w();
} break;
case 7: {
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h);
op_writedp(dp + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, rd.l);
op_writedp(dp + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -1009,7 +1009,7 @@ void bCPU::op_asl_dpx() {
void bCPU::op_lsr_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -1018,11 +1018,11 @@ void bCPU::op_lsr_dpx() {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DP, dp + regs.x.w);
rd.l = op_readdp(dp + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
rd.h = op_readdp(dp + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -1030,11 +1030,11 @@ void bCPU::op_lsr_dpx() {
else op_lsr_w();
} break;
case 7: {
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h);
op_writedp(dp + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, rd.l);
op_writedp(dp + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -1043,7 +1043,7 @@ void bCPU::op_lsr_dpx() {
void bCPU::op_rol_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -1052,11 +1052,11 @@ void bCPU::op_rol_dpx() {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DP, dp + regs.x.w);
rd.l = op_readdp(dp + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
rd.h = op_readdp(dp + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -1064,11 +1064,11 @@ void bCPU::op_rol_dpx() {
else op_rol_w();
} break;
case 7: {
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h);
op_writedp(dp + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, rd.l);
op_writedp(dp + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}
@@ -1077,7 +1077,7 @@ void bCPU::op_rol_dpx() {
void bCPU::op_ror_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -1086,11 +1086,11 @@ void bCPU::op_ror_dpx() {
cpu_io();
} break;
case 4: {
rd.l = op_read(OPMODE_DP, dp + regs.x.w);
rd.l = op_readdp(dp + regs.x.w);
if(regs.p.m)status.cycle_pos++;
} break;
case 5: {
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
rd.h = op_readdp(dp + regs.x.w + 1);
} break;
case 6: {
cpu_io();
@@ -1098,11 +1098,11 @@ void bCPU::op_ror_dpx() {
else op_ror_w();
} break;
case 7: {
op_write(OPMODE_DP, dp + regs.x.w + 1, rd.h);
op_writedp(dp + regs.x.w + 1, rd.h);
} break;
case 8: {
last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, rd.l);
op_writedp(dp + regs.x.w, rd.l);
status.cycle_pos = 0;
} break;
}

View File

@@ -2,180 +2,180 @@ sta_addr(0x8d, regs.p.m, regs.a.w),
stx_addr(0x8e, regs.p.x, regs.x.w),
sty_addr(0x8c, regs.p.x, regs.y.w),
stz_addr(0x9c, regs.p.m, 0x0000) {
1:aa.l = op_read();
2:aa.h = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:if($1)last_cycle();
op_write(OPMODE_DBR, aa.w, $2);
op_writedbr(aa.w, $2);
if($1)end;
4:last_cycle();
op_write(OPMODE_DBR, aa.w + 1, $2 >> 8);
op_writedbr(aa.w + 1, $2 >> 8);
}
sta_addrx(0x9d, regs.p.m, regs.a.w),
stz_addrx(0x9e, regs.p.m, 0x0000) {
1:aa.l = op_read();
2:aa.h = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_c4(aa.w, aa.w + regs.x.w);
4:if($1)last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, $2);
op_writedbr(aa.w + regs.x.w, $2);
if($1)end;
5:last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, $2 >> 8);
op_writedbr(aa.w + regs.x.w + 1, $2 >> 8);
}
sta_addry(0x99) {
1:aa.l = op_read();
2:aa.h = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_c4(aa.w, aa.w + regs.y.w);
4:if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l);
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)end;
5:last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h);
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}
sta_long(0x8f) {
1:aa.l = op_read();
2:aa.h = op_read();
3:aa.b = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if(regs.p.m)last_cycle();
op_write(OPMODE_LONG, aa.d, regs.a.l);
op_writelong(aa.d, regs.a.l);
if(regs.p.m)end;
5:last_cycle();
op_write(OPMODE_LONG, aa.d + 1, regs.a.h);
op_writelong(aa.d + 1, regs.a.h);
}
sta_longx(0x9f) {
1:aa.l = op_read();
2:aa.h = op_read();
3:aa.b = op_read();
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if(regs.p.m)last_cycle();
op_write(OPMODE_LONG, aa.d + regs.x.w, regs.a.l);
op_writelong(aa.d + regs.x.w, regs.a.l);
if(regs.p.m)end;
5:last_cycle();
op_write(OPMODE_LONG, aa.d + regs.x.w + 1, regs.a.h);
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
}
sta_dp(0x85, regs.p.m, regs.a.w),
stx_dp(0x86, regs.p.x, regs.x.w),
sty_dp(0x84, regs.p.x, regs.y.w),
stz_dp(0x64, regs.p.m, 0x0000) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:if($1)last_cycle();
op_write(OPMODE_DP, dp, $2);
op_writedp(dp, $2);
if($1)end;
4:last_cycle();
op_write(OPMODE_DP, dp + 1, $2 >> 8);
op_writedp(dp + 1, $2 >> 8);
}
sta_dpx(0x95, regs.p.m, regs.a.w),
sty_dpx(0x94, regs.p.x, regs.y.w),
stz_dpx(0x74, regs.p.m, 0x0000) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
4:if($1)last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, $2);
op_writedp(dp + regs.x.w, $2);
if($1)end;
5:last_cycle();
op_write(OPMODE_DP, dp + regs.x.w + 1, $2 >> 8);
op_writedp(dp + regs.x.w + 1, $2 >> 8);
}
stx_dpy(0x96) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
4:if(regs.p.x)last_cycle();
op_write(OPMODE_DP, dp + regs.y.w, regs.x.l);
op_writedp(dp + regs.y.w, regs.x.l);
if(regs.p.x)end;
5:last_cycle();
op_write(OPMODE_DP, dp + regs.y.w + 1, regs.x.h);
op_writedp(dp + regs.y.w + 1, regs.x.h);
}
sta_idp(0x92) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w, regs.a.l);
op_writedbr(aa.w, regs.a.l);
if(regs.p.m)end;
6:last_cycle();
op_write(OPMODE_DBR, aa.w + 1, regs.a.h);
op_writedbr(aa.w + 1, regs.a.h);
}
sta_ildp(0x87) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
5:aa.b = op_read(OPMODE_DP, dp + 2);
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if(regs.p.m)last_cycle();
op_write(OPMODE_LONG, aa.d, regs.a.l);
op_writelong(aa.d, regs.a.l);
if(regs.p.m)end;
7:last_cycle();
op_write(OPMODE_LONG, aa.d + 1, regs.a.h);
op_writelong(aa.d + 1, regs.a.h);
}
sta_idpx(0x81) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
4:aa.l = op_read(OPMODE_DP, dp + regs.x.w);
5:aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
4:aa.l = op_readdp(dp + regs.x.w);
5:aa.h = op_readdp(dp + regs.x.w + 1);
6:if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w, regs.a.l);
op_writedbr(aa.w, regs.a.l);
if(regs.p.m)end;
7:last_cycle();
op_write(OPMODE_DBR, aa.w + 1, regs.a.h);
op_writedbr(aa.w + 1, regs.a.h);
}
sta_idpy(0x91) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
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(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l);
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)end;
7:last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h);
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}
sta_ildpy(0x97) {
1:dp = op_read();
1:dp = op_readpc();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
5:aa.b = op_read(OPMODE_DP, dp + 2);
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if(regs.p.m)last_cycle();
op_write(OPMODE_LONG, aa.d + regs.y.w, regs.a.l);
op_writelong(aa.d + regs.y.w, regs.a.l);
if(regs.p.m)end;
7:last_cycle();
op_write(OPMODE_LONG, aa.d + regs.y.w + 1, regs.a.h);
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
}
sta_sr(0x83) {
1:sp = op_read();
1:sp = op_readpc();
2:cpu_io();
3:if(regs.p.m)last_cycle();
op_write(OPMODE_SP, sp, regs.a.l);
op_writesp(sp, regs.a.l);
if(regs.p.m)end;
4:last_cycle();
op_write(OPMODE_SP, sp + 1, regs.a.h);
op_writesp(sp + 1, regs.a.h);
}
sta_isry(0x93) {
1:sp = op_read();
1:sp = op_readpc();
2:cpu_io();
3:aa.l = op_read(OPMODE_SP, sp);
4:aa.h = op_read(OPMODE_SP, sp + 1);
3:aa.l = op_readsp(sp);
4:aa.h = op_readsp(sp + 1);
5:cpu_io();
6:if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l);
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)end;
7:last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h);
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}

View File

@@ -1,19 +1,19 @@
void bCPU::op_sta_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w, regs.a.w);
op_writedbr(aa.w, regs.a.w);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_write(OPMODE_DBR, aa.w + 1, regs.a.w >> 8);
op_writedbr(aa.w + 1, regs.a.w >> 8);
status.cycle_pos = 0;
} break;
}
@@ -22,19 +22,19 @@ void bCPU::op_sta_addr() {
void bCPU::op_stx_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
if(regs.p.x)last_cycle();
op_write(OPMODE_DBR, aa.w, regs.x.w);
op_writedbr(aa.w, regs.x.w);
if(regs.p.x)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_write(OPMODE_DBR, aa.w + 1, regs.x.w >> 8);
op_writedbr(aa.w + 1, regs.x.w >> 8);
status.cycle_pos = 0;
} break;
}
@@ -43,19 +43,19 @@ void bCPU::op_stx_addr() {
void bCPU::op_sty_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
if(regs.p.x)last_cycle();
op_write(OPMODE_DBR, aa.w, regs.y.w);
op_writedbr(aa.w, regs.y.w);
if(regs.p.x)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_write(OPMODE_DBR, aa.w + 1, regs.y.w >> 8);
op_writedbr(aa.w + 1, regs.y.w >> 8);
status.cycle_pos = 0;
} break;
}
@@ -64,19 +64,19 @@ void bCPU::op_sty_addr() {
void bCPU::op_stz_addr() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w, 0x0000);
op_writedbr(aa.w, 0x0000);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_write(OPMODE_DBR, aa.w + 1, 0x0000 >> 8);
op_writedbr(aa.w + 1, 0x0000 >> 8);
status.cycle_pos = 0;
} break;
}
@@ -85,22 +85,22 @@ void bCPU::op_stz_addr() {
void bCPU::op_sta_addrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_c4(aa.w, aa.w + regs.x.w);
} break;
case 4: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, regs.a.w);
op_writedbr(aa.w + regs.x.w, regs.a.w);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, regs.a.w >> 8);
op_writedbr(aa.w + regs.x.w + 1, regs.a.w >> 8);
status.cycle_pos = 0;
} break;
}
@@ -109,22 +109,22 @@ void bCPU::op_sta_addrx() {
void bCPU::op_stz_addrx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_c4(aa.w, aa.w + regs.x.w);
} break;
case 4: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w, 0x0000);
op_writedbr(aa.w + regs.x.w, 0x0000);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, 0x0000 >> 8);
op_writedbr(aa.w + regs.x.w + 1, 0x0000 >> 8);
status.cycle_pos = 0;
} break;
}
@@ -133,22 +133,22 @@ void bCPU::op_stz_addrx() {
void bCPU::op_sta_addry() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
cpu_c4(aa.w, aa.w + regs.y.w);
} break;
case 4: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l);
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h);
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
@@ -157,22 +157,22 @@ void bCPU::op_sta_addry() {
void bCPU::op_sta_long() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
aa.b = op_read();
aa.b = op_readpc();
} break;
case 4: {
if(regs.p.m)last_cycle();
op_write(OPMODE_LONG, aa.d, regs.a.l);
op_writelong(aa.d, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_write(OPMODE_LONG, aa.d + 1, regs.a.h);
op_writelong(aa.d + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
@@ -181,22 +181,22 @@ void bCPU::op_sta_long() {
void bCPU::op_sta_longx() {
switch(status.cycle_pos++) {
case 1: {
aa.l = op_read();
aa.l = op_readpc();
} break;
case 2: {
aa.h = op_read();
aa.h = op_readpc();
} break;
case 3: {
aa.b = op_read();
aa.b = op_readpc();
} break;
case 4: {
if(regs.p.m)last_cycle();
op_write(OPMODE_LONG, aa.d + regs.x.w, regs.a.l);
op_writelong(aa.d + regs.x.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_write(OPMODE_LONG, aa.d + regs.x.w + 1, regs.a.h);
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
@@ -205,19 +205,19 @@ void bCPU::op_sta_longx() {
void bCPU::op_sta_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DP, dp, regs.a.w);
op_writedp(dp, regs.a.w);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_write(OPMODE_DP, dp + 1, regs.a.w >> 8);
op_writedp(dp + 1, regs.a.w >> 8);
status.cycle_pos = 0;
} break;
}
@@ -226,19 +226,19 @@ void bCPU::op_sta_dp() {
void bCPU::op_stx_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
if(regs.p.x)last_cycle();
op_write(OPMODE_DP, dp, regs.x.w);
op_writedp(dp, regs.x.w);
if(regs.p.x)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_write(OPMODE_DP, dp + 1, regs.x.w >> 8);
op_writedp(dp + 1, regs.x.w >> 8);
status.cycle_pos = 0;
} break;
}
@@ -247,19 +247,19 @@ void bCPU::op_stx_dp() {
void bCPU::op_sty_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
if(regs.p.x)last_cycle();
op_write(OPMODE_DP, dp, regs.y.w);
op_writedp(dp, regs.y.w);
if(regs.p.x)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_write(OPMODE_DP, dp + 1, regs.y.w >> 8);
op_writedp(dp + 1, regs.y.w >> 8);
status.cycle_pos = 0;
} break;
}
@@ -268,19 +268,19 @@ void bCPU::op_sty_dp() {
void bCPU::op_stz_dp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DP, dp, 0x0000);
op_writedp(dp, 0x0000);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_write(OPMODE_DP, dp + 1, 0x0000 >> 8);
op_writedp(dp + 1, 0x0000 >> 8);
status.cycle_pos = 0;
} break;
}
@@ -289,7 +289,7 @@ void bCPU::op_stz_dp() {
void bCPU::op_sta_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -299,12 +299,12 @@ void bCPU::op_sta_dpx() {
} break;
case 4: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, regs.a.w);
op_writedp(dp + regs.x.w, regs.a.w);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_write(OPMODE_DP, dp + regs.x.w + 1, regs.a.w >> 8);
op_writedp(dp + regs.x.w + 1, regs.a.w >> 8);
status.cycle_pos = 0;
} break;
}
@@ -313,7 +313,7 @@ void bCPU::op_sta_dpx() {
void bCPU::op_sty_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -323,12 +323,12 @@ void bCPU::op_sty_dpx() {
} break;
case 4: {
if(regs.p.x)last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, regs.y.w);
op_writedp(dp + regs.x.w, regs.y.w);
if(regs.p.x)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_write(OPMODE_DP, dp + regs.x.w + 1, regs.y.w >> 8);
op_writedp(dp + regs.x.w + 1, regs.y.w >> 8);
status.cycle_pos = 0;
} break;
}
@@ -337,7 +337,7 @@ void bCPU::op_sty_dpx() {
void bCPU::op_stz_dpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -347,12 +347,12 @@ void bCPU::op_stz_dpx() {
} break;
case 4: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DP, dp + regs.x.w, 0x0000);
op_writedp(dp + regs.x.w, 0x0000);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_write(OPMODE_DP, dp + regs.x.w + 1, 0x0000 >> 8);
op_writedp(dp + regs.x.w + 1, 0x0000 >> 8);
status.cycle_pos = 0;
} break;
}
@@ -361,7 +361,7 @@ void bCPU::op_stz_dpx() {
void bCPU::op_stx_dpy() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -371,12 +371,12 @@ void bCPU::op_stx_dpy() {
} break;
case 4: {
if(regs.p.x)last_cycle();
op_write(OPMODE_DP, dp + regs.y.w, regs.x.l);
op_writedp(dp + regs.y.w, regs.x.l);
if(regs.p.x)status.cycle_pos = 0;
} break;
case 5: {
last_cycle();
op_write(OPMODE_DP, dp + regs.y.w + 1, regs.x.h);
op_writedp(dp + regs.y.w + 1, regs.x.h);
status.cycle_pos = 0;
} break;
}
@@ -385,25 +385,25 @@ void bCPU::op_stx_dpy() {
void bCPU::op_sta_idp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
aa.l = op_read(OPMODE_DP, dp);
aa.l = op_readdp(dp);
} break;
case 4: {
aa.h = op_read(OPMODE_DP, dp + 1);
aa.h = op_readdp(dp + 1);
} break;
case 5: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w, regs.a.l);
op_writedbr(aa.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 6: {
last_cycle();
op_write(OPMODE_DBR, aa.w + 1, regs.a.h);
op_writedbr(aa.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
@@ -412,28 +412,28 @@ void bCPU::op_sta_idp() {
void bCPU::op_sta_ildp() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
aa.l = op_read(OPMODE_DP, dp);
aa.l = op_readdp(dp);
} break;
case 4: {
aa.h = op_read(OPMODE_DP, dp + 1);
aa.h = op_readdp(dp + 1);
} break;
case 5: {
aa.b = op_read(OPMODE_DP, dp + 2);
aa.b = op_readdp(dp + 2);
} break;
case 6: {
if(regs.p.m)last_cycle();
op_write(OPMODE_LONG, aa.d, regs.a.l);
op_writelong(aa.d, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 7: {
last_cycle();
op_write(OPMODE_LONG, aa.d + 1, regs.a.h);
op_writelong(aa.d + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
@@ -442,7 +442,7 @@ void bCPU::op_sta_ildp() {
void bCPU::op_sta_idpx() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
@@ -451,19 +451,19 @@ void bCPU::op_sta_idpx() {
cpu_io();
} break;
case 4: {
aa.l = op_read(OPMODE_DP, dp + regs.x.w);
aa.l = op_readdp(dp + regs.x.w);
} break;
case 5: {
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
aa.h = op_readdp(dp + regs.x.w + 1);
} break;
case 6: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w, regs.a.l);
op_writedbr(aa.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w + 1, regs.a.h);
op_writedbr(aa.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
@@ -472,28 +472,28 @@ void bCPU::op_sta_idpx() {
void bCPU::op_sta_idpy() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
aa.l = op_read(OPMODE_DP, dp);
aa.l = op_readdp(dp);
} break;
case 4: {
aa.h = op_read(OPMODE_DP, dp + 1);
aa.h = op_readdp(dp + 1);
} break;
case 5: {
cpu_c4(aa.w, aa.w + regs.y.w);
} break;
case 6: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l);
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h);
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
@@ -502,28 +502,28 @@ void bCPU::op_sta_idpy() {
void bCPU::op_sta_ildpy() {
switch(status.cycle_pos++) {
case 1: {
dp = op_read();
dp = op_readpc();
} break;
case 2: {
cpu_c2();
} break;
case 3: {
aa.l = op_read(OPMODE_DP, dp);
aa.l = op_readdp(dp);
} break;
case 4: {
aa.h = op_read(OPMODE_DP, dp + 1);
aa.h = op_readdp(dp + 1);
} break;
case 5: {
aa.b = op_read(OPMODE_DP, dp + 2);
aa.b = op_readdp(dp + 2);
} break;
case 6: {
if(regs.p.m)last_cycle();
op_write(OPMODE_LONG, aa.d + regs.y.w, regs.a.l);
op_writelong(aa.d + regs.y.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 7: {
last_cycle();
op_write(OPMODE_LONG, aa.d + regs.y.w + 1, regs.a.h);
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
@@ -532,19 +532,19 @@ void bCPU::op_sta_ildpy() {
void bCPU::op_sta_sr() {
switch(status.cycle_pos++) {
case 1: {
sp = op_read();
sp = op_readpc();
} break;
case 2: {
cpu_io();
} break;
case 3: {
if(regs.p.m)last_cycle();
op_write(OPMODE_SP, sp, regs.a.l);
op_writesp(sp, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 4: {
last_cycle();
op_write(OPMODE_SP, sp + 1, regs.a.h);
op_writesp(sp + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}
@@ -553,28 +553,28 @@ void bCPU::op_sta_sr() {
void bCPU::op_sta_isry() {
switch(status.cycle_pos++) {
case 1: {
sp = op_read();
sp = op_readpc();
} break;
case 2: {
cpu_io();
} break;
case 3: {
aa.l = op_read(OPMODE_SP, sp);
aa.l = op_readsp(sp);
} break;
case 4: {
aa.h = op_read(OPMODE_SP, sp + 1);
aa.h = op_readsp(sp + 1);
} break;
case 5: {
cpu_io();
} break;
case 6: {
if(regs.p.m)last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l);
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m)status.cycle_pos = 0;
} break;
case 7: {
last_cycle();
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h);
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
status.cycle_pos = 0;
} break;
}

View File

@@ -24,13 +24,27 @@ uint8 r;
//read from address bus b, write to address bus a
//block invalid writes, see comments above
r = (bbus == 0x80) ? r_cpu->regs.mdr : r_mem->read(0x2100 | bbus);
r = r_mem->read(0x2100 | bbus);
if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300 ||
(abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c)return;
r_mem->write(abus, r);
}
}
uint8 bCPU::dma_bbus(uint8 i, uint8 index) {
switch(channel[i].xfermode) {
default:
case 0: return (channel[i].destaddr); break; //0
case 1: return (channel[i].destaddr + (index & 1)); break; //0,1
case 2: return (channel[i].destaddr); break; //0,0
case 3: return (channel[i].destaddr + ((index >> 1) & 1)); break; //0,0,1,1
case 4: return (channel[i].destaddr + (index & 3)); break; //0,1,2,3
case 5: return (channel[i].destaddr + (index & 1)); break; //0,1,0,1
case 6: return (channel[i].destaddr); break; //0,0 [2]
case 7: return (channel[i].destaddr + ((index >> 1) & 1)); break; //0,0,1,1 [3]
}
}
void bCPU::dma_add_cycles(uint32 cycles) {
status.dma_cycle_count += cycles;
}
@@ -53,19 +67,19 @@ uint32 r;
return r;
}
void bCPU::dma_cputommio(uint8 i, uint8 index) {
if(sdd1->dma_active() == true) {
r_mem->write(0x2100 | ((channel[i].destaddr + index) & 0xff), sdd1->dma_read());
void bCPU::dma_cputommio(uint8 i, uint8 bbus) {
if(cartridge.info.sdd1 == true && sdd1->dma_active() == true) {
r_mem->write(0x2100 | bbus, sdd1->dma_read());
} else {
dma_transfer_byte(0, ((channel[i].destaddr + index) & 0xff), dma_addr(i));
dma_transfer_byte(0, bbus, dma_addr(i));
}
add_cycles(8);
channel[i].xfersize--;
}
void bCPU::dma_mmiotocpu(uint8 i, uint8 index) {
dma_transfer_byte(1, ((channel[i].destaddr + index) & 0xff), dma_addr(i));
void bCPU::dma_mmiotocpu(uint8 i, uint8 bbus) {
dma_transfer_byte(1, bbus, dma_addr(i));
add_cycles(8);
channel[i].xfersize--;
@@ -81,30 +95,19 @@ void bCPU::dma_write(uint8 i, uint8 index) {
void bCPU::dma_run() {
for(int i = 0; i < 8; i++) {
if(channel[i].active == false)continue;
if(channel[i].dma_enabled == false)continue;
//first byte transferred?
if(channel[i].read_index == 0) {
if(cartridge.info.sdd1 == true && channel[i].read_index == 0) {
sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr),
channel[i].xfersize);
}
switch(channel[i].xfermode) {
case 0: dma_write(i, 0); break; //0
case 1: dma_write(i, channel[i].read_index & 1); break; //0,1
case 2: dma_write(i, 0); break; //0,0
case 3: dma_write(i, (channel[i].read_index >> 1) & 1); break; //0,0,1,1
case 4: dma_write(i, channel[i].read_index & 3); break; //0,1,2,3
case 5: dma_write(i, channel[i].read_index & 1); break; //0,1,0,1
case 6: dma_write(i, 0); break; //0,0 [2]
case 7: dma_write(i, (channel[i].read_index >> 1) & 1); break; //0,0,1,1 [3]
}
channel[i].read_index++;
dma_write(i, dma_bbus(i, channel[i].read_index++));
dma_add_cycles(8);
if(channel[i].xfersize == 0) {
channel[i].active = false;
channel[i].dma_enabled = false;
}
return;
@@ -121,23 +124,6 @@ uint32 bCPU::hdma_iaddr(uint8 i) {
return (channel[i].hdma_ibank << 16) | (channel[i].hdma_iaddr++);
}
uint16 bCPU::hdma_mmio(uint8 i) {
uint8 l = channel[i].read_index;
uint16 index;
switch(channel[i].xfermode) {
case 0: index = 0; break; //0
case 1: index = l & 1; break; //0,1
case 2: index = 0; break; //0,0
case 3: index = (l >> 1) & 1; break; //0,0,1,1
case 4: index = l & 3; break; //0,1,2,3
case 5: index = l & 1; break; //0,1,0,1
case 6: index = 0; break; //0,0 [2]
case 7: index = (l >> 1) & 1; break; //0,0,1,1 [3]
}
return (0x2100 | ((channel[i].destaddr + index) & 0xff));
}
void bCPU::hdma_update(uint8 i) {
channel[i].hdma_line_counter = r_mem->read(hdma_addr(i));
add_cycles(8);
@@ -150,7 +136,7 @@ void bCPU::hdma_update(uint8 i) {
}
if(channel[i].hdma_line_counter == 0) {
channel[i].hdma_active = false;
channel[i].hdma_completed = true;
channel[i].hdma_do_transfer = false;
return;
}
@@ -168,13 +154,13 @@ void bCPU::hdma_update(uint8 i) {
void bCPU::hdma_run() {
static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
for(int i = 0; i < 8; i++) {
if(!channel[i].hdma_enabled || !channel[i].hdma_active)continue;
if(!channel[i].hdma_enabled || channel[i].hdma_completed)continue;
if(channel[i].hdma_do_transfer) {
int xferlen = hdma_xferlen[channel[i].xfermode];
for(channel[i].read_index = 0; channel[i].read_index < xferlen; channel[i].read_index++) {
if(bool(config::cpu.hdma_enable) == true) {
dma_transfer_byte(channel[i].direction, hdma_mmio(i),
dma_transfer_byte(channel[i].direction, dma_bbus(i, channel[i].read_index),
channel[i].hdma_indirect ? hdma_iaddr(i) : hdma_addr(i));
}
add_cycles(8);
@@ -190,6 +176,15 @@ static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
}
}
void bCPU::hdma_init() {
for(int i = 0; i < 8; i++) {
if(!channel[i].hdma_enabled)continue;
channel[i].hdma_addr = channel[i].srcaddr;
hdma_update(i);
}
}
uint8 bCPU::hdma_enabled_channels() {
int r = 0;
for(int i = 0; i < 8; i++) {
@@ -201,7 +196,7 @@ int r = 0;
uint8 bCPU::hdma_active_channels() {
int r = 0;
for(int i = 0; i < 8; i++) {
if(channel[i].hdma_enabled && channel[i].hdma_active)r++;
if(channel[i].hdma_enabled && !channel[i].hdma_completed)r++;
}
return r;
}
@@ -215,7 +210,7 @@ int r = 0;
void bCPU::hdmainit_activate() {
for(int i = 0; i < 8; i++) {
channel[i].hdma_active = false;
channel[i].hdma_completed = false;
channel[i].hdma_do_transfer = false;
}
@@ -240,7 +235,7 @@ void bCPU::dma_reset() {
for(int i = 0; i < 8; i++) {
channel[i].read_index = 0;
channel[i].active = false;
channel[i].dma_enabled = false;
channel[i].hdma_enabled = false;
channel[i].dmap = 0xff;
channel[i].direction = 1;
@@ -259,7 +254,7 @@ void bCPU::dma_reset() {
channel[i].hdma_line_counter = 0xff;
channel[i].hdma_unknown = 0xff;
channel[i].hdma_active = false;
channel[i].hdma_completed = false;
channel[i].hdma_do_transfer = false;
}
}

View File

@@ -2,7 +2,7 @@ struct {
uint32 read_index; //set to 0 at beginning of DMA/HDMA
//$420b
bool active;
bool dma_enabled;
//$420c
bool hdma_enabled;
//$43x0
@@ -33,7 +33,7 @@ struct {
uint8 hdma_unknown;
//hdma-specific
bool hdma_active;
bool hdma_completed; //for this frame
bool hdma_do_transfer;
uint8 hdma_current_channel;
@@ -41,10 +41,12 @@ struct {
} channel[8];
inline void dma_transfer_byte(bool direction, uint8 bbus, uint32 abus);
inline uint8 dma_bbus(uint8 i, uint8 index);
inline void dma_add_cycles(uint32 cycles);
inline void hdma_add_cycles(uint32 cycles);
inline void dma_run();
inline void hdma_run();
inline void hdma_init();
inline void hdma_update(uint8 i);
inline uint8 hdma_enabled_channels();
inline uint8 hdma_active_channels();
@@ -56,5 +58,4 @@ struct {
inline uint32 dma_addr(uint8 i);
inline uint32 hdma_addr(uint8 i);
inline uint32 hdma_iaddr(uint8 i);
inline uint16 hdma_mmio(uint8 i);
inline void dma_reset();

View File

@@ -5,3 +5,23 @@ uint8 apu_port[4];
inline void cpu_io();
inline uint8 mem_read(uint32 addr);
inline void mem_write(uint32 addr, uint8 value);
/*****
* helper memory addressing functions used by CPU core
*****/
uint8 op_readpc () { return mem_read((regs.pc.b << 16) + regs.pc.w++); }
uint8 op_readstack() { (regs.e) ? regs.s.l++ : regs.s.w++; return mem_read(regs.s.w); }
uint8 op_readaddr (uint32 addr) { return mem_read(uclip<16>(addr)); }
uint8 op_readlong (uint32 addr) { return mem_read(uclip<24>(addr)); }
uint8 op_readdbr (uint32 addr) { return mem_read(uclip<24>((regs.db << 16) + addr)); }
uint8 op_readpbr (uint32 addr) { return mem_read((regs.pc.b << 16) + uclip<16>(addr)); }
uint8 op_readdp (uint32 addr) { return mem_read(uclip<16>(regs.d + uclip<16>(addr))); }
uint8 op_readsp (uint32 addr) { return mem_read(uclip<16>(regs.s + uclip<16>(addr))); }
void op_writestack(uint8 data) { mem_write(regs.s.w, data); (regs.e) ? regs.s.l-- : regs.s.w--; }
void op_writeaddr (uint32 addr, uint8 data) { mem_write(uclip<16>(addr), data); }
void op_writelong (uint32 addr, uint8 data) { mem_write(uclip<24>(addr), data); }
void op_writedbr (uint32 addr, uint8 data) { mem_write(uclip<24>((regs.db << 16) + addr), data); }
void op_writepbr (uint32 addr, uint8 data) { mem_write((regs.pc.b << 16) + uclip<16>(addr), data); }
void op_writedp (uint32 addr, uint8 data) { mem_write(uclip<16>(regs.d + uclip<16>(addr)), data); }
void op_writesp (uint32 addr, uint8 data) { mem_write(uclip<16>(regs.s + uclip<16>(addr)), data); }

View File

@@ -26,7 +26,6 @@
*/
uint16 bCPU::vcounter() { return time.v; }
uint16 bCPU::hcounter() { return get_hcounter(); }
uint16 bCPU::hcycles() { return time.hc; }
bool bCPU::interlace() { return time.interlace; }
@@ -39,6 +38,13 @@ void bCPU::set_overscan (bool r) { time.overscan = r; update_interrupts(); }
uint8 bCPU::dma_counter() { return (time.dma_counter + time.hc) & 6; }
uint16 bCPU::hcounter() {
if(time.v == 240 && time.interlace == false && time.interlace_field == 1) {
return time.hc >> 2;
}
return (time.hc - ((time.hc > 1292) << 1) - ((time.hc > 1310) << 1)) >> 2;
}
bool bCPU::nmi_trigger_pos_match(uint32 offset) {
uint16 v = overscan() ? 240 : 225;
uint16 hc = 2 + offset;
@@ -48,15 +54,16 @@ uint16 hc = 2 + offset;
bool bCPU::irq_trigger_pos_match(uint32 offset) {
uint16 v = status.virq_pos;
uint16 hc = (status.hirq_enabled) ? status.hirq_pos : 0;
uint16 vlimit = region_scanlines() >> 1;
//positions that can never be latched
//region_scanlines() = 262/NTSC, 312/PAL
//region_scanlines() = 525/NTSC, 625/PAL
//PAL results are unverified on hardware
if(v == 240 && hc == 339 && interlace() == false && interlace_field() == 1)return false;
if(v == (region_scanlines() - 1) && hc == 339 && interlace() == false)return false;
if(v == region_scanlines() && interlace() == false)return false;
if(v == region_scanlines() && hc == 339)return false;
if(v > region_scanlines())return false;
if(v == (vlimit - 1) && hc == 339 && interlace() == false)return false;
if(v == vlimit && interlace() == false)return false;
if(v == vlimit && hc == 339)return false;
if(v > vlimit)return false;
if(hc > 339)return false;
hc = (hc != 0) ? ((hc << 2) + 14) : 10;
@@ -88,15 +95,16 @@ void bCPU::update_nmi() {
void bCPU::update_irq() {
int vpos = status.virq_pos;
int hpos = (status.hirq_enabled) ? status.hirq_pos : 0;
int vlimit = region_scanlines() >> 1;
//positions that can never be latched
//region_scanlines() = 262/NTSC, 312/PAL
//PAL results are unverified on hardware
if(vpos == 240 && hpos == 339 && interlace() == false && interlace_field() == 1)goto _nolatch;
if(vpos == (region_scanlines() - 1) && hpos == 339 && interlace() == false)goto _nolatch;
if(vpos == region_scanlines() && interlace() == false)goto _nolatch;
if(vpos == region_scanlines() && hpos == 339)goto _nolatch;
if(vpos > region_scanlines())goto _nolatch;
if(vpos == (vlimit - 1) && hpos == 339 && interlace() == false)goto _nolatch;
if(vpos == vlimit && interlace() == false)goto _nolatch;
if(vpos == vlimit && hpos == 339)goto _nolatch;
if(vpos > vlimit)goto _nolatch;
if(hpos > 339)goto _nolatch;
hpos = (hpos != 0) ? ((hpos << 2) + 14) : 10;
@@ -177,36 +185,63 @@ int16 hc, hc_end;
}
}
//all scanlines are 1364 cycles long, except scanline 240
//on non-interlace odd-frames, which is 1360 cycles long.
//[NTSC]
//interlace mode has 525 scanlines: 263 on the even frame,
//and 262 on the odd.
//non-interlace mode has 524 scanlines: 262 scanlines on
//both even and odd frames.
//[PAL] <PAL info is unverified on hardware>
//interlace mode has 625 scanlines: 313 on the even frame,
//and 312 on the odd.
//non-interlace mode has 624 scanlines: 312 scanlines on
//both even and odd frames.
//
//cycles per frame:
// 263 * 1364 = 358732
// 262 * 1364 = 357368
// 262 * 1364 - 4 = 357364
void bCPU::inc_vcounter() {
time.v++;
if(time.v >= time.frame_lines) {
time.v = 0;
time.interlace_field ^= 1;
uint32 bCPU::clocks_executed() {
uint32 r = status.cycles_executed;
status.cycles_executed = 0;
return r;
}
if(interlace() == true && interlace_field() == 0) {
time.frame_lines = time.region_scanlines + 1;
} else {
time.frame_lines = time.region_scanlines;
void bCPU::cycle_edge() {
if(time.line_rendered == false) {
if(time.hc >= 128) {
time.line_rendered = true;
r_ppu->render_scanline();
}
}
if(time.hdmainit_triggered == false) {
if(time.hc >= time.hdmainit_trigger_pos || time.v) {
time.hdmainit_triggered = true;
hdmainit_activate();
}
}
if(time.hdma_triggered == false) {
//hdma_triggered only set to false for v <= (overscan ? 239 : 224)
if(time.hc >= 1106) {
time.hdma_triggered = true;
hdma_activate();
}
}
}
void bCPU::add_cycles(int cycles) {
status.cycles_executed += cycles;
poll_interrupts(cycles);
if(time.hc + cycles >= time.line_cycles) {
cycles = (time.hc + cycles) - time.line_cycles;
time.hc = 0;
scanline();
poll_interrupts(cycles);
}
time.hc += cycles;
if(time.dram_refreshed == false) {
if(time.hc >= time.dram_refresh_pos) {
time.dram_refreshed = true;
add_cycles(40);
return;
}
}
}
void bCPU::scanline() {
if(++time.v >= time.frame_lines) {
frame();
}
time.dma_counter += time.line_cycles;
if(time.v == 240 && time.interlace == false && time.interlace_field == 1) {
time.line_cycles = 1360;
@@ -215,103 +250,49 @@ void bCPU::inc_vcounter() {
}
time.dram_refreshed = false;
time.line_rendered =
time.hdma_triggered = (time.v <= (!overscan() ? 224 : 239)) ? false : true;
r_ppu->scanline();
snes->scanline();
update_interrupts();
}
//all dots are 4 cycles long, except dots 323 and 327. dots 323 and 327
//are 6 cycles long. this holds true for all scanlines except scanline
//240 on non-interlace odd frames. the reason for this is because this
//scanline is only 1360 cycles long, instead of 1364 like all other
//scanlines.
//this makes the effective range of hscan_pos 0-339 at all times.
//dot 323 range = { 1292, 1294, 1296 }
//dot 327 range = { 1310, 1312, 1314 }
uint16 bCPU::get_hcounter() {
if(time.v == 240 && time.interlace == false && time.interlace_field == 1) {
return time.hc >> 2;
}
return (time.hc - ((time.hc > 1292) << 1) - ((time.hc > 1310) << 1)) >> 2;
}
uint32 bCPU::cycles_executed() {
uint32 r = status.cycles_executed;
status.cycles_executed = 0;
return r;
}
void bCPU::cycle_edge() {
if(time.hdmainit_triggered == false) {
if(time.hc >= time.hdmainit_trigger_pos || time.v) {
time.hdmainit_triggered = true;
hdmainit_activate();
}
}
if(time.hdma_triggered == false) {
if(time.v <= (overscan() ? 239 : 224)) {
if(time.hc >= 1106) {
time.hdma_triggered = true;
hdma_activate();
}
}
if(vcounter() == (!overscan() ? 227 : 242) && status.auto_joypad_poll == true) {
snes->poll_input(SNES::DEV_JOYPAD1);
snes->poll_input(SNES::DEV_JOYPAD2);
//When the SNES auto-polls the joypads, it writes 1, then 0 to
//$4016, then reads from each 16 times to get the joypad state
//information. As a result, the joypad read positions are set
//to 16 after such a poll. Position 16 is the controller
//connected status bit.
status.joypad1_read_pos = 16;
status.joypad2_read_pos = 16;
}
}
void bCPU::add_cycles(int cycles) {
status.cycles_executed += cycles;
void bCPU::frame() {
time.nmi_read = 1;
time.nmi_line = 1;
time.nmi_transition = 0;
poll_interrupts(cycles);
if(time.hc + cycles >= time.line_cycles) {
cycles = (time.hc + cycles) - time.line_cycles;
time.hc = 0;
inc_vcounter();
poll_interrupts(cycles);
if(time.v == 0) {
frame();
r_ppu->frame();
snes->frame();
}
scanline();
r_ppu->scanline();
snes->scanline();
time.line_rendered = false;
time.v = 0;
time.interlace_field ^= 1;
if(interlace() == true && interlace_field() == 0) {
time.frame_lines = (time.region_scanlines >> 1) + 1;
} else {
time.frame_lines = (time.region_scanlines >> 1);
}
if(time.dram_refreshed == false) {
if(time.hc + cycles >= time.dram_refresh_pos) {
time.dram_refreshed = true;
status.cycles_executed += 40;
cycles = (time.hc + cycles) - time.dram_refresh_pos;
time.hc = time.dram_refresh_pos + 40;
if(cpu_version == 2) {
if(time.v != 240 || time.interlace != false || time.interlace_field != 1) {
if(time.dram_refresh_pos == 534) {
time.dram_refresh_pos = 538;
} else {
time.dram_refresh_pos = 534;
}
}
}
}
if(cpu_version == 2) {
time.hdmainit_trigger_pos = 12 + dma_counter();
} else {
time.hdmainit_trigger_pos = 12 + 8 - dma_counter();
}
time.hdmainit_triggered = false;
if(time.line_rendered == false) {
//rendering should start at H=18 (+256=274), but since the
//current PPU emulation renders the entire scanline at once,
//PPU register changes mid-scanline do not show up.
//therefore, wait a few dots before rendering the scanline
if(time.hc + cycles >= (48 * 4)) {
time.line_rendered = true;
r_ppu->render_scanline();
}
}
time.hc += cycles;
r_ppu->frame();
snes->frame();
}
void bCPU::time_reset() {
@@ -347,12 +328,12 @@ void bCPU::time_reset() {
switch(region) {
case NTSC:
time.region_scanlines = 262;
time.region_scanlines = 525;
break;
case PAL:
time.region_scanlines = 312;
time.region_scanlines = 625;
break;
}
time.frame_lines = time.region_scanlines;
time.frame_lines = time.region_scanlines >> 1;
}

View File

@@ -67,8 +67,8 @@ struct {
inline uint8 dma_counter();
inline void inc_vcounter();
inline uint16 get_hcounter();
inline void cycle_edge();
inline void add_cycles(int cycles);
inline void scanline();
inline void frame();
inline void time_reset();

View File

@@ -4,3 +4,5 @@
CPU::CPU() {
cpu_version = 1;
}
CPU::~CPU() {}

View File

@@ -12,9 +12,9 @@ uint8 cpu_version;
virtual uint16 vcounter() = 0;
virtual uint16 hcounter() = 0;
virtual uint16 hcycles() = 0;
virtual bool overscan() = 0;
virtual bool interlace() = 0;
virtual bool interlace_field() = 0;
virtual bool overscan() = 0;
virtual uint16 region_scanlines() = 0;
virtual void set_interlace(bool r) = 0;
virtual void set_overscan (bool r) = 0;
@@ -30,14 +30,32 @@ CPURegs regs;
FLAG_Z = 0x02, FLAG_C = 0x01
};
virtual uint8 pio_status() = 0;
virtual void main() {}
virtual void run() = 0;
virtual uint32 cycles_executed() = 0;
virtual uint32 clocks_executed() = 0;
virtual void scanline() = 0;
virtual void frame() = 0;
virtual void power() = 0;
virtual void reset() = 0;
//opcode disassembler
/*****
* in opcode-based CPU emulators, the main emulation routine
* will only be able to call the disassemble_opcode() function
* on clean opcode edges. but with cycle-based CPU emulators,
* the CPU may be in the middle of executing an opcode when the
* emulator (e.g. debugger) wants to disassemble an opcode. this
* would mean that important registers may not reflect what they
* did at the start of the opcode (especially regs.pc), so in
* cycle-based emulators, this function should be overridden to
* reflect whether or not an opcode has only been partially
* executed. if not, the debugger should abort attempts to skip,
* disable, or disassemble the current opcode.
*****/
virtual bool in_opcode() { return false; }
/*****
* opcode disassembler
*****/
enum {
OPTYPE_DP = 0, //dp
OPTYPE_DPX, //dp,x
@@ -57,17 +75,18 @@ enum {
OPTYPE_SR, //sr,s
OPTYPE_ISRY, //(sr,s),y
OPTYPE_ADDR_PC, //pbr:addr
OPTYPE_IADDR_PC //pbr:(addr)
OPTYPE_IADDR_PC, //pbr:(addr)
OPTYPE_RELB, //relb
OPTYPE_RELW, //relw
};
//see dcpu.cpp for notes on this function
virtual bool in_opcode();
void disassemble_opcode(char *output);
uint32 resolve_offset(uint8 offset_type, uint32 addr);
uint8 dreadb(uint32 addr);
uint16 dreadw(uint32 addr);
uint32 dreadl(uint32 addr);
uint32 decode(uint8 offset_type, uint32 addr);
uint8 opcode_length();
uint16 __relb(int8 offset);
uint16 __relw(int16 offset);
CPU();
virtual ~CPU() {}
virtual ~CPU();
};

View File

@@ -1,20 +1,18 @@
class CPURegFlags {
private:
template <uint8 B> class bit {
template<uint mask> class bit {
public:
uint8 _b;
inline operator bool() { return (_b & B); }
inline bool operator = (bool i) { (i) ? _b |= B : _b &= ~B; return (_b & B); }
inline bool operator & (bool i) { if(i)_b &= ~B; return (_b & B); }
inline bool operator &= (bool i) { if(i)_b &= ~B; return (_b & B); }
inline bool operator | (bool i) { if(i)_b |= B; return (_b & B); }
inline bool operator |= (bool i) { if(i)_b |= B; return (_b & B); }
inline bool operator ^ (bool i) { if(i)_b ^= B; return (_b & B); }
inline bool operator ^= (bool i) { if(i)_b ^= B; return (_b & B); }
uint data;
inline operator bool() { return bool(data & mask); }
inline bool operator = (const bool i) { (i) ? data |= mask : data &= ~mask; return bool(data & mask); }
inline bool operator |= (const bool i) { if(i)data |= mask; return bool(data & mask); }
inline bool operator ^= (const bool i) { if(i)data ^= mask; return bool(data & mask); }
inline bool operator &= (const bool i) { if(i)data &= mask; return bool(data & mask); }
};
public:
union {
uint8 _b;
uint8 data;
bit<0x80> n;
bit<0x40> v;
bit<0x20> m, p;
@@ -25,64 +23,60 @@ union {
bit<0x01> c;
};
CPURegFlags() { _b = 0; }
inline operator uint8() { return _b; }
inline unsigned operator = (uint8 i) { _b = i; return _b; }
inline unsigned operator &= (uint8 i) { _b &= i; return _b; }
inline unsigned operator |= (uint8 i) { _b |= i; return _b; }
inline unsigned operator ^= (uint8 i) { _b ^= i; return _b; }
inline operator unsigned() const { return data; }
inline unsigned operator = (const uint8 i) { data = i; return data; }
inline unsigned operator |= (const uint8 i) { data |= i; return data; }
inline unsigned operator ^= (const uint8 i) { data ^= i; return data; }
inline unsigned operator &= (const uint8 i) { data &= i; return data; }
CPURegFlags() : data(0) {}
};
class CPUReg16 {
public:
union {
uint16 w;
#ifdef ARCH_LSB
struct { uint8 l, h; };
#else
struct { uint8 h, l; };
#endif
struct { uint8 order_lsb2(l, h); };
};
CPUReg16() { w = 0; }
inline operator uint16() { return w; }
inline unsigned operator = (uint16 i) { w = i; return w; }
inline unsigned operator += (uint16 i) { w += i; return w; }
inline unsigned operator -= (uint16 i) { w -= i; return w; }
inline unsigned operator *= (uint16 i) { w *= i; return w; }
inline unsigned operator /= (uint16 i) { w /= i; return w; }
inline unsigned operator &= (uint16 i) { w &= i; return w; }
inline unsigned operator |= (uint16 i) { w |= i; return w; }
inline unsigned operator ^= (uint16 i) { w ^= i; return w; }
inline unsigned operator <<= (uint16 i) { w <<= i; return w; }
inline unsigned operator >>= (uint16 i) { w >>= i; return w; }
inline operator unsigned() const { return w; }
template<typename T> inline unsigned operator = (const T i) { w = i; return w; }
template<typename T> inline unsigned operator |= (const T i) { w |= i; return w; }
template<typename T> inline unsigned operator ^= (const T i) { w ^= i; return w; }
template<typename T> inline unsigned operator &= (const T i) { w &= i; return w; }
template<typename T> inline unsigned operator <<= (const T i) { w <<= i; return w; }
template<typename T> inline unsigned operator >>= (const T i) { w >>= i; return w; }
template<typename T> inline unsigned operator += (const T i) { w += i; return w; }
template<typename T> inline unsigned operator -= (const T i) { w -= i; return w; }
template<typename T> inline unsigned operator *= (const T i) { w *= i; return w; }
template<typename T> inline unsigned operator /= (const T i) { w /= i; return w; }
template<typename T> inline unsigned operator %= (const T i) { w %= i; return w; }
CPUReg16() : w(0) {}
};
class CPUReg24 {
public:
union {
uint32 d;
#ifdef ARCH_LSB
struct { uint16 w, null_w; };
struct { uint8 l, h, b, null_b; };
#else
struct { uint16 null_w, w; };
struct { uint8 null_b, b, h, l; };
#endif
struct { uint16 order_lsb2(w, wh); };
struct { uint8 order_lsb4(l, h, b, bh); };
};
CPUReg24() { d = 0; }
inline operator uint32() { return (d & 0xffffff); }
inline unsigned operator = (uint16 i) { d = i; return d; }
inline unsigned operator += (uint16 i) { d += i; return d; }
inline unsigned operator -= (uint16 i) { d -= i; return d; }
inline unsigned operator *= (uint16 i) { d *= i; return d; }
inline unsigned operator /= (uint16 i) { d /= i; return d; }
inline unsigned operator &= (uint16 i) { d &= i; return d; }
inline unsigned operator |= (uint16 i) { d |= i; return d; }
inline unsigned operator ^= (uint16 i) { d ^= i; return d; }
inline unsigned operator <<= (uint16 i) { d <<= i; return d; }
inline unsigned operator >>= (uint16 i) { d >>= i; return d; }
inline operator unsigned() const { return d; }
template<typename T> inline unsigned operator = (const T i) { d = uclip<24>(i); return d; }
template<typename T> inline unsigned operator |= (const T i) { d = uclip<24>(d | i); return d; }
template<typename T> inline unsigned operator ^= (const T i) { d = uclip<24>(d ^ i); return d; }
template<typename T> inline unsigned operator &= (const T i) { d = uclip<24>(d & i); return d; }
template<typename T> inline unsigned operator <<= (const T i) { d = uclip<24>(d << i); return d; }
template<typename T> inline unsigned operator >>= (const T i) { d = uclip<24>(d >> i); return d; }
template<typename T> inline unsigned operator += (const T i) { d = uclip<24>(d + i); return d; }
template<typename T> inline unsigned operator -= (const T i) { d = uclip<24>(d - i); return d; }
template<typename T> inline unsigned operator *= (const T i) { d = uclip<24>(d * i); return d; }
template<typename T> inline unsigned operator /= (const T i) { d = uclip<24>(d / i); return d; }
template<typename T> inline unsigned operator %= (const T i) { d = uclip<24>(d % i); return d; }
CPUReg24() : d(0) {}
};
class CPURegs {
@@ -91,7 +85,8 @@ CPUReg24 pc;
CPUReg16 a, x, y, s, d;
CPURegFlags p;
uint8 db;
uint8 mdr; //memory data register (openbus)
uint8 mdr;
bool e;
CPURegs() { db = 0; mdr = 0x00; e = false; }
bool acc_8b, idx_8b;
CPURegs() : db(0), mdr(0x00), e(false), acc_8b(true), idx_8b(true) {}
};

View File

@@ -1,30 +1,28 @@
//this is a virtual function.
//in opcode-based CPU emulators, the main emulation routine
//will only be able to call the disassemble_opcode() function
//on clean opcode edges. but with cycle-based CPU emulators,
//the CPU may be in the middle of executing an opcode when the
//emulator (e.g. debugger) wants to disassemble an opcode. this
//would mean that important registers may not reflect what they
//did at the start of the opcode (especially regs.pc), so in
//cycle-based emulators, this function should be overridden to
//reflect whether or not an opcode has only been partially
//executed. if not, the debugger should abort attempts to skip,
//disable, or disassemble the current opcode.
bool CPU::in_opcode() { return false; }
uint16 CPU::__relb(int8 offset) {
uint32 addr;
addr = (regs.pc.d & 0xff0000) | ((regs.pc.d + 2) & 0xffff);
return addr + offset;
uint8 CPU::dreadb(uint32 addr) {
if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) {
//$[00-3f|80-bf]:[2000-5fff]
//do not read MMIO registers within debugger
return 0x00;
}
return r_mem->read(addr);
}
uint16 CPU::__relw(int16 offset) {
uint32 addr;
addr = (regs.pc.d & 0xff0000) | ((regs.pc.d + 3) & 0xffff);
return addr + offset;
uint16 CPU::dreadw(uint32 addr) {
uint16 r;
r = dreadb((addr + 0) & 0xffffff) << 0;
r |= dreadb((addr + 1) & 0xffffff) << 8;
return r;
}
uint32 CPU::resolve_offset(uint8 offset_type, uint32 addr) {
uint32 CPU::dreadl(uint32 addr) {
uint32 r;
r = dreadb((addr + 0) & 0xffffff) << 0;
r |= dreadb((addr + 1) & 0xffffff) << 8;
r |= dreadb((addr + 2) & 0xffffff) << 16;
return r;
}
uint32 CPU::decode(uint8 offset_type, uint32 addr) {
uint32 r = 0;
switch(offset_type) {
case OPTYPE_DP:
@@ -38,23 +36,23 @@ uint32 r = 0;
break;
case OPTYPE_IDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + r_mem->read_word(addr);
r = (regs.db << 16) + dreadw(addr);
break;
case OPTYPE_IDPX:
addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + r_mem->read_word(addr);
r = (regs.db << 16) + dreadw(addr);
break;
case OPTYPE_IDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + r_mem->read_word(addr) + regs.y;
r = (regs.db << 16) + dreadw(addr) + regs.y;
break;
case OPTYPE_ILDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = r_mem->read_long(addr);
r = dreadl(addr);
break;
case OPTYPE_ILDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = r_mem->read_long(addr) + regs.y;
r = dreadl(addr) + regs.y;
break;
case OPTYPE_ADDR:
r = (regs.db << 16) + (addr & 0xffff);
@@ -75,31 +73,37 @@ uint32 r = 0;
r = (regs.pc.b << 16) + ((addr + regs.x) & 0xffff);
break;
case OPTYPE_ILADDR:
r = addr & 0xffffff;
r = addr;
break;
case OPTYPE_LONG:
r = addr & 0xffffff;
r = addr;
break;
case OPTYPE_LONGX:
r = (addr + regs.x) & 0xffffff;
r = (addr + regs.x);
break;
case OPTYPE_SR:
r = (regs.s + (addr & 0xff)) & 0xffff;
break;
case OPTYPE_ISRY:
addr = (regs.s + (addr & 0xff)) & 0xffff;
r = (regs.db << 16) + r_mem->read_word(addr) + regs.y;
r = (regs.db << 16) + dreadw(addr) + regs.y;
break;
case OPTYPE_RELB:
r = (regs.pc.b << 16) + ((regs.pc.w + 2) & 0xffff);
r += int8(addr);
break;
case OPTYPE_RELW:
r = (regs.pc.b << 16) + ((regs.pc.w + 3) & 0xffff);
r += int16(addr);
break;
}
return r;
return(r & 0xffffff);
}
void CPU::disassemble_opcode(char *output) {
char *s;
char t[256];
uint8 op, op0, op1, op2;
static CPUReg24 pc;
s = output;
char t[256];
char *s = output;
if(in_opcode() == true) {
strcpy(s, "?????? <CPU within opcode>");
@@ -107,332 +111,334 @@ static CPUReg24 pc;
}
pc.d = regs.pc.d;
sprintf(s, "%0.6x ", pc.d);
sprintf(s, "%0.6x ", uint32(pc.d));
op = r_mem->read(pc.d); pc.w++;
op0 = r_mem->read(pc.d); pc.w++;
op1 = r_mem->read(pc.d); pc.w++;
op2 = r_mem->read(pc.d);
uint8 op = dreadb(pc.d); pc.w++;
uint8 op0 = dreadb(pc.d); pc.w++;
uint8 op1 = dreadb(pc.d); pc.w++;
uint8 op2 = dreadb(pc.d);
#define op8 ((op0))
#define op16 ((op0) | (op1 << 8))
#define op24 ((op0) | (op1 << 8) | (op2 << 16))
#define a8 (regs.e || regs.p.m)
#define x8 (regs.e || regs.p.x)
switch(op) {
case 0x00:sprintf(t, "brk #$%0.2x ", op0);break;
case 0x01:sprintf(t, "ora ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0x02:sprintf(t, "cop #$%0.2x ", op0);break;
case 0x03:sprintf(t, "ora $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0x04:sprintf(t, "tsb $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x05:sprintf(t, "ora $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x06:sprintf(t, "asl $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x07:sprintf(t, "ora [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0x08:sprintf(t, "php ");break;
case 0x09:
if(regs.p.m)sprintf(t, "ora #$%0.2x ", op0);
else sprintf(t, "ora #$%0.4x ", op0|op1<<8);break;
case 0x0a:sprintf(t, "asl a ");break;
case 0x0b:sprintf(t, "phd ");break;
case 0x0c:sprintf(t, "tsb $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x0d:sprintf(t, "ora $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x0e:sprintf(t, "asl $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x0f:sprintf(t, "ora $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x10:sprintf(t, "bpl $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0x11:sprintf(t, "ora ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0x12:sprintf(t, "ora ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0x13:sprintf(t, "ora ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0x14:sprintf(t, "trb $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x15:sprintf(t, "ora $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x16:sprintf(t, "asl $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x17:sprintf(t, "ora [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0x18:sprintf(t, "clc ");break;
case 0x19:sprintf(t, "ora $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0x1a:sprintf(t, "inc ");break;
case 0x1b:sprintf(t, "tcs ");break;
case 0x1c:sprintf(t, "trb $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x1d:sprintf(t, "ora $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x1e:sprintf(t, "asl $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x1f:sprintf(t, "ora $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0x20:sprintf(t, "jsr $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR_PC, (op0|op1<<8)));break;
case 0x21:sprintf(t, "and ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0x22:sprintf(t, "jsl $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x23:sprintf(t, "and $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0x24:sprintf(t, "bit $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x25:sprintf(t, "and $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x26:sprintf(t, "rol $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x27:sprintf(t, "and [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0x28:sprintf(t, "plp ");break;
case 0x29:
if(regs.p.m)sprintf(t, "and #$%0.2x ", op0);
else sprintf(t, "and #$%0.4x ", op0|op1<<8);break;
case 0x2a:sprintf(t, "rol a ");break;
case 0x2b:sprintf(t, "pld ");break;
case 0x2c:sprintf(t, "bit $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x2d:sprintf(t, "and $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x2e:sprintf(t, "rol $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x2f:sprintf(t, "and $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x30:sprintf(t, "bmi $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0x31:sprintf(t, "and ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0x32:sprintf(t, "and ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0x33:sprintf(t, "and ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0x34:sprintf(t, "bit $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x35:sprintf(t, "and $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x36:sprintf(t, "rol $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x37:sprintf(t, "and [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0x38:sprintf(t, "sec ");break;
case 0x39:sprintf(t, "and $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0x3a:sprintf(t, "dec ");break;
case 0x3b:sprintf(t, "tsc ");break;
case 0x3c:sprintf(t, "bit $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x3d:sprintf(t, "and $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x3e:sprintf(t, "rol $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x3f:sprintf(t, "and $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0x40:sprintf(t, "rti ");break;
case 0x41:sprintf(t, "eor ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0x42:sprintf(t, "wdm ");break;
case 0x43:sprintf(t, "eor $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0x44:sprintf(t, "mvp $%0.2x,$%0.2x ", op1, op0);break;
case 0x45:sprintf(t, "eor $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x46:sprintf(t, "lsr $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x47:sprintf(t, "eor [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0x48:sprintf(t, "pha ");break;
case 0x49:
if(regs.p.m)sprintf(t, "eor #$%0.2x ", op0);
else sprintf(t, "eor #$%0.4x ", op0|op1<<8);break;
case 0x4a:sprintf(t, "lsr a ");break;
case 0x4b:sprintf(t, "phk ");break;
case 0x4c:sprintf(t, "jmp $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR_PC, (op0|op1<<8)));break;
case 0x4d:sprintf(t, "eor $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x4e:sprintf(t, "lsr $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x4f:sprintf(t, "eor $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x50:sprintf(t, "bvc $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0x51:sprintf(t, "eor ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0x52:sprintf(t, "eor ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0x53:sprintf(t, "eor ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0x54:sprintf(t, "mvn $%0.2x,$%0.2x ", op1, op0);break;
case 0x55:sprintf(t, "eor $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x56:sprintf(t, "lsr $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x57:sprintf(t, "eor [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0x58:sprintf(t, "cli ");break;
case 0x59:sprintf(t, "eor $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0x5a:sprintf(t, "phy ");break;
case 0x5b:sprintf(t, "tcd ");break;
case 0x5c:sprintf(t, "jml $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x5d:sprintf(t, "eor $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x5e:sprintf(t, "lsr $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x5f:sprintf(t, "eor $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0x60:sprintf(t, "rts ");break;
case 0x61:sprintf(t, "adc ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0x62:sprintf(t, "per $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x63:sprintf(t, "adc $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0x64:sprintf(t, "stz $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x65:sprintf(t, "adc $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x66:sprintf(t, "ror $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x67:sprintf(t, "adc [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0x68:sprintf(t, "pla ");break;
case 0x69:
if(regs.p.m)sprintf(t, "adc #$%0.2x ", op0);
else sprintf(t, "adc #$%0.4x ", op0|op1<<8);break;
case 0x6a:sprintf(t, "ror a ");break;
case 0x6b:sprintf(t, "rtl ");break;
case 0x6c:sprintf(t, "jmp ($%0.4x) [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_IADDR_PC, (op0|op1<<8)));break;
case 0x6d:sprintf(t, "adc $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x6e:sprintf(t, "ror $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x6f:sprintf(t, "adc $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x70:sprintf(t, "bvs $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0x71:sprintf(t, "adc ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0x72:sprintf(t, "adc ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0x73:sprintf(t, "adc ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0x74:sprintf(t, "stz $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x75:sprintf(t, "adc $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x76:sprintf(t, "ror $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x77:sprintf(t, "adc [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0x78:sprintf(t, "sei ");break;
case 0x79:sprintf(t, "adc $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0x7a:sprintf(t, "ply ");break;
case 0x7b:sprintf(t, "tdc ");break;
case 0x7c:sprintf(t, "jmp ($%0.4x,x) [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_IADDRX, (op0|op1<<8)));break;
case 0x7d:sprintf(t, "adc $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x7e:sprintf(t, "ror $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x7f:sprintf(t, "adc $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0x80:sprintf(t, "bra $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0x81:sprintf(t, "sta ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0x82:sprintf(t, "brl $%0.4x [$%0.6x]", __relw(op0|op1<<8)&0xffff, __relw(op0|op1<<8)&0xffffff);break;
case 0x83:sprintf(t, "sta $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0x84:sprintf(t, "sty $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x85:sprintf(t, "sta $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x86:sprintf(t, "stx $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0x87:sprintf(t, "sta [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0x88:sprintf(t, "dey ");break;
case 0x89:
if(regs.p.m)sprintf(t, "bit #$%0.2x ", op0);
else sprintf(t, "bit #$%0.4x ", op0|op1<<8);break;
case 0x8a:sprintf(t, "txa ");break;
case 0x8b:sprintf(t, "phb ");break;
case 0x8c:sprintf(t, "sty $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x8d:sprintf(t, "sta $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x8e:sprintf(t, "stx $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x8f:sprintf(t, "sta $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0x90:sprintf(t, "bcc $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0x91:sprintf(t, "sta ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0x92:sprintf(t, "sta ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0x93:sprintf(t, "sta ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0x94:sprintf(t, "sty $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x95:sprintf(t, "sta $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0x96:sprintf(t, "stx $%0.2x,y [$%0.6x]", op0, resolve_offset(OPTYPE_DPY, op0));break;
case 0x97:sprintf(t, "sta [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0x98:sprintf(t, "tya ");break;
case 0x99:sprintf(t, "sta $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0x9a:sprintf(t, "txs ");break;
case 0x9b:sprintf(t, "txy ");break;
case 0x9c:sprintf(t, "stz $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0x9d:sprintf(t, "sta $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x9e:sprintf(t, "stz $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0x9f:sprintf(t, "sta $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0xa0:
if(regs.p.x)sprintf(t, "ldy #$%0.2x ", op0);
else sprintf(t, "ldy #$%0.4x ", op0|op1<<8);break;
case 0xa1:sprintf(t, "lda ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0xa2:
if(regs.p.x)sprintf(t, "ldx #$%0.2x ", op0);
else sprintf(t, "ldx #$%0.4x ", op0|op1<<8);break;
case 0xa3:sprintf(t, "lda $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0xa4:sprintf(t, "ldy $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xa5:sprintf(t, "lda $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xa6:sprintf(t, "ldx $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xa7:sprintf(t, "lda [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0xa8:sprintf(t, "tay ");break;
case 0xa9:
if(regs.p.m)sprintf(t, "lda #$%0.2x ", op0);
else sprintf(t, "lda #$%0.4x ", op0|op1<<8);break;
case 0xaa:sprintf(t, "tax ");break;
case 0xab:sprintf(t, "plb ");break;
case 0xac:sprintf(t, "ldy $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xad:sprintf(t, "lda $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xae:sprintf(t, "ldx $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xaf:sprintf(t, "lda $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0xb0:sprintf(t, "bcs $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0xb1:sprintf(t, "lda ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0xb2:sprintf(t, "lda ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0xb3:sprintf(t, "lda ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0xb4:sprintf(t, "ldy $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0xb5:sprintf(t, "lda $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0xb6:sprintf(t, "ldx $%0.2x,y [$%0.6x]", op0, resolve_offset(OPTYPE_DPY, op0));break;
case 0xb7:sprintf(t, "lda [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0xb8:sprintf(t, "clv ");break;
case 0xb9:sprintf(t, "lda $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0xba:sprintf(t, "tsx ");break;
case 0xbb:sprintf(t, "tyx ");break;
case 0xbc:sprintf(t, "ldy $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0xbd:sprintf(t, "lda $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0xbe:sprintf(t, "ldx $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0xbf:sprintf(t, "lda $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0xc0:
if(regs.p.x)sprintf(t, "cpy #$%0.2x ", op0);
else sprintf(t, "cpy #$%0.4x ", op0|op1<<8);break;
case 0xc1:sprintf(t, "cmp ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0xc2:sprintf(t, "rep #$%0.2x ", op0);break;
case 0xc3:sprintf(t, "cmp $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0xc4:sprintf(t, "cpy $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xc5:sprintf(t, "cmp $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xc6:sprintf(t, "dec $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xc7:sprintf(t, "cmp [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0xc8:sprintf(t, "iny ");break;
case 0xc9:
if(regs.p.m)sprintf(t, "cmp #$%0.2x ", op0);
else sprintf(t, "cmp #$%0.4x ", op0|op1<<8);break;
case 0xca:sprintf(t, "dex ");break;
case 0xcb:sprintf(t, "wai ");break;
case 0xcc:sprintf(t, "cpy $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xcd:sprintf(t, "cmp $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xce:sprintf(t, "dec $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xcf:sprintf(t, "cmp $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0xd0:sprintf(t, "bne $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0xd1:sprintf(t, "cmp ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0xd2:sprintf(t, "cmp ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0xd3:sprintf(t, "cmp ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0xd4:sprintf(t, "pei ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0xd5:sprintf(t, "cmp $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0xd6:sprintf(t, "dec $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0xd7:sprintf(t, "cmp [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0xd8:sprintf(t, "cld ");break;
case 0xd9:sprintf(t, "cmp $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0xda:sprintf(t, "phx ");break;
case 0xdb:sprintf(t, "stp ");break;
case 0xdc:sprintf(t, "jmp [$%0.4x] [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ILADDR, (op0|op1<<8)));break;
case 0xdd:sprintf(t, "cmp $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0xde:sprintf(t, "dec $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0xdf:sprintf(t, "cmp $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0xe0:
if(regs.p.x)sprintf(t, "cpx #$%0.2x ", op0);
else sprintf(t, "cpx #$%0.4x ", op0|op1<<8);break;
case 0xe1:sprintf(t, "sbc ($%0.2x,x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDPX, op0));break;
case 0xe2:sprintf(t, "sep #$%0.2x ", op0);break;
case 0xe3:sprintf(t, "sbc $%0.2x,s [$%0.6x]", op0, resolve_offset(OPTYPE_SR, op0));break;
case 0xe4:sprintf(t, "cpx $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xe5:sprintf(t, "sbc $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xe6:sprintf(t, "inc $%0.2x [$%0.6x]", op0, resolve_offset(OPTYPE_DP, op0));break;
case 0xe7:sprintf(t, "sbc [$%0.2x] [$%0.6x]", op0, resolve_offset(OPTYPE_ILDP, op0));break;
case 0xe8:sprintf(t, "inx ");break;
case 0xe9:
if(regs.p.m)sprintf(t, "sbc #$%0.2x ", op0);
else sprintf(t, "sbc #$%0.4x ", op0|op1<<8);break;
case 0xea:sprintf(t, "nop ");break;
case 0xeb:sprintf(t, "xba ");break;
case 0xec:sprintf(t, "cpx $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xed:sprintf(t, "sbc $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xee:sprintf(t, "inc $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xef:sprintf(t, "sbc $%0.6x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONG, (op0|op1<<8|op2<<16)));break;
case 0xf0:sprintf(t, "beq $%0.4x [$%0.6x]", __relb(op0)&0xffff, __relb(op0)&0xffffff);break;
case 0xf1:sprintf(t, "sbc ($%0.2x),y [$%0.6x]", op0, resolve_offset(OPTYPE_IDPY, op0));break;
case 0xf2:sprintf(t, "sbc ($%0.2x) [$%0.6x]", op0, resolve_offset(OPTYPE_IDP, op0));break;
case 0xf3:sprintf(t, "sbc ($%0.2x,s),y [$%0.6x]", op0, resolve_offset(OPTYPE_ISRY, op0));break;
case 0xf4:sprintf(t, "pea $%0.4x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDR, (op0|op1<<8)));break;
case 0xf5:sprintf(t, "sbc $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0xf6:sprintf(t, "inc $%0.2x,x [$%0.6x]", op0, resolve_offset(OPTYPE_DPX, op0));break;
case 0xf7:sprintf(t, "sbc [$%0.2x],y [$%0.6x]", op0, resolve_offset(OPTYPE_ILDPY, op0));break;
case 0xf8:sprintf(t, "sed ");break;
case 0xf9:sprintf(t, "sbc $%0.4x,y [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRY, (op0|op1<<8)));break;
case 0xfa:sprintf(t, "plx ");break;
case 0xfb:sprintf(t, "xce ");break;
case 0xfc:sprintf(t, "jsr ($%0.4x,x) [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_IADDRX, (op0|op1<<8)));break;
case 0xfd:sprintf(t, "sbc $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0xfe:sprintf(t, "inc $%0.4x,x [$%0.6x]", op0|op1<<8, resolve_offset(OPTYPE_ADDRX, (op0|op1<<8)));break;
case 0xff:sprintf(t, "sbc $%0.6x,x [$%0.6x]", op0|op1<<8|op2<<16, resolve_offset(OPTYPE_LONGX, (op0|op1<<8|op2<<16)));break;
case 0x00: sprintf(t, "brk #$%0.2x ", op8); break;
case 0x01: sprintf(t, "ora ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x02: sprintf(t, "cop #$%0.2x ", op8); break;
case 0x03: sprintf(t, "ora $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x04: sprintf(t, "tsb $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x05: sprintf(t, "ora $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x06: sprintf(t, "asl $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x07: sprintf(t, "ora [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x08: sprintf(t, "php "); break;
case 0x09: if(a8)sprintf(t, "ora #$%0.2x ", op8);
else sprintf(t, "ora #$%0.4x ", op16); break;
case 0x0a: sprintf(t, "asl a "); break;
case 0x0b: sprintf(t, "phd "); break;
case 0x0c: sprintf(t, "tsb $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0d: sprintf(t, "ora $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0e: sprintf(t, "asl $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0f: sprintf(t, "ora $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x10: sprintf(t, "bpl $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x11: sprintf(t, "ora ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x12: sprintf(t, "ora ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x13: sprintf(t, "ora ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x14: sprintf(t, "trb $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x15: sprintf(t, "ora $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x16: sprintf(t, "asl $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x17: sprintf(t, "ora [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x18: sprintf(t, "clc "); break;
case 0x19: sprintf(t, "ora $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x1a: sprintf(t, "inc "); break;
case 0x1b: sprintf(t, "tcs "); break;
case 0x1c: sprintf(t, "trb $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x1d: sprintf(t, "ora $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x1e: sprintf(t, "asl $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x1f: sprintf(t, "ora $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x20: sprintf(t, "jsr $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break;
case 0x21: sprintf(t, "and ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x22: sprintf(t, "jsl $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x23: sprintf(t, "and $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x24: sprintf(t, "bit $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x25: sprintf(t, "and $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x26: sprintf(t, "rol $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x27: sprintf(t, "and [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x28: sprintf(t, "plp "); break;
case 0x29: if(a8)sprintf(t, "and #$%0.2x ", op8);
else sprintf(t, "and #$%0.4x ", op16); break;
case 0x2a: sprintf(t, "rol a "); break;
case 0x2b: sprintf(t, "pld "); break;
case 0x2c: sprintf(t, "bit $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2d: sprintf(t, "and $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2e: sprintf(t, "rol $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2f: sprintf(t, "and $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x30: sprintf(t, "bmi $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x31: sprintf(t, "and ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x32: sprintf(t, "and ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x33: sprintf(t, "and ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x34: sprintf(t, "bit $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x35: sprintf(t, "and $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x36: sprintf(t, "rol $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x37: sprintf(t, "and [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x38: sprintf(t, "sec "); break;
case 0x39: sprintf(t, "and $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x3a: sprintf(t, "dec "); break;
case 0x3b: sprintf(t, "tsc "); break;
case 0x3c: sprintf(t, "bit $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3d: sprintf(t, "and $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3e: sprintf(t, "rol $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3f: sprintf(t, "and $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x40: sprintf(t, "rti "); break;
case 0x41: sprintf(t, "eor ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x42: sprintf(t, "wdm "); break;
case 0x43: sprintf(t, "eor $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x44: sprintf(t, "mvp $%0.2x,$%0.2x ", op1, op8); break;
case 0x45: sprintf(t, "eor $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x46: sprintf(t, "lsr $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x47: sprintf(t, "eor [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x48: sprintf(t, "pha "); break;
case 0x49: if(a8)sprintf(t, "eor #$%0.2x ", op8);
else sprintf(t, "eor #$%0.4x ", op16); break;
case 0x4a: sprintf(t, "lsr a "); break;
case 0x4b: sprintf(t, "phk "); break;
case 0x4c: sprintf(t, "jmp $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break;
case 0x4d: sprintf(t, "eor $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x4e: sprintf(t, "lsr $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x4f: sprintf(t, "eor $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x50: sprintf(t, "bvc $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x51: sprintf(t, "eor ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x52: sprintf(t, "eor ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x53: sprintf(t, "eor ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x54: sprintf(t, "mvn $%0.2x,$%0.2x ", op1, op8); break;
case 0x55: sprintf(t, "eor $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x56: sprintf(t, "lsr $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x57: sprintf(t, "eor [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x58: sprintf(t, "cli "); break;
case 0x59: sprintf(t, "eor $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x5a: sprintf(t, "phy "); break;
case 0x5b: sprintf(t, "tcd "); break;
case 0x5c: sprintf(t, "jml $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x5d: sprintf(t, "eor $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x5e: sprintf(t, "lsr $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x5f: sprintf(t, "eor $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x60: sprintf(t, "rts "); break;
case 0x61: sprintf(t, "adc ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x62: sprintf(t, "per $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x63: sprintf(t, "adc $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x64: sprintf(t, "stz $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x65: sprintf(t, "adc $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x66: sprintf(t, "ror $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x67: sprintf(t, "adc [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x68: sprintf(t, "pla "); break;
case 0x69: if(a8)sprintf(t, "adc #$%0.2x ", op8);
else sprintf(t, "adc #$%0.4x ", op16); break;
case 0x6a: sprintf(t, "ror a "); break;
case 0x6b: sprintf(t, "rtl "); break;
case 0x6c: sprintf(t, "jmp ($%0.4x) [$%0.6x]", op16, decode(OPTYPE_IADDR_PC, op16)); break;
case 0x6d: sprintf(t, "adc $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x6e: sprintf(t, "ror $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x6f: sprintf(t, "adc $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x70: sprintf(t, "bvs $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x71: sprintf(t, "adc ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x72: sprintf(t, "adc ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x73: sprintf(t, "adc ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x74: sprintf(t, "stz $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x75: sprintf(t, "adc $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x76: sprintf(t, "ror $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x77: sprintf(t, "adc [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x78: sprintf(t, "sei "); break;
case 0x79: sprintf(t, "adc $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x7a: sprintf(t, "ply "); break;
case 0x7b: sprintf(t, "tdc "); break;
case 0x7c: sprintf(t, "jmp ($%0.4x,x) [$%0.6x]", op16, decode(OPTYPE_IADDRX, op16)); break;
case 0x7d: sprintf(t, "adc $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x7e: sprintf(t, "ror $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x7f: sprintf(t, "adc $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x80: sprintf(t, "bra $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x81: sprintf(t, "sta ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x82: sprintf(t, "brl $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELW, op16)), decode(OPTYPE_RELW, op16)); break;
case 0x83: sprintf(t, "sta $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x84: sprintf(t, "sty $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x85: sprintf(t, "sta $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x86: sprintf(t, "stx $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x87: sprintf(t, "sta [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x88: sprintf(t, "dey "); break;
case 0x89: if(a8)sprintf(t, "bit #$%0.2x ", op8);
else sprintf(t, "bit #$%0.4x ", op16); break;
case 0x8a: sprintf(t, "txa "); break;
case 0x8b: sprintf(t, "phb "); break;
case 0x8c: sprintf(t, "sty $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8d: sprintf(t, "sta $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8e: sprintf(t, "stx $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8f: sprintf(t, "sta $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x90: sprintf(t, "bcc $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x91: sprintf(t, "sta ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x92: sprintf(t, "sta ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x93: sprintf(t, "sta ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x94: sprintf(t, "sty $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x95: sprintf(t, "sta $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x96: sprintf(t, "stx $%0.2x,y [$%0.6x]", op8, decode(OPTYPE_DPY, op8)); break;
case 0x97: sprintf(t, "sta [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x98: sprintf(t, "tya "); break;
case 0x99: sprintf(t, "sta $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x9a: sprintf(t, "txs "); break;
case 0x9b: sprintf(t, "txy "); break;
case 0x9c: sprintf(t, "stz $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x9d: sprintf(t, "sta $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x9e: sprintf(t, "stz $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x9f: sprintf(t, "sta $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xa0: if(x8)sprintf(t, "ldy #$%0.2x ", op8);
else sprintf(t, "ldy #$%0.4x ", op16); break;
case 0xa1: sprintf(t, "lda ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xa2: if(x8)sprintf(t, "ldx #$%0.2x ", op8);
else sprintf(t, "ldx #$%0.4x ", op16); break;
case 0xa3: sprintf(t, "lda $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xa4: sprintf(t, "ldy $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa5: sprintf(t, "lda $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa6: sprintf(t, "ldx $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa7: sprintf(t, "lda [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xa8: sprintf(t, "tay "); break;
case 0xa9: if(a8)sprintf(t, "lda #$%0.2x ", op8);
else sprintf(t, "lda #$%0.4x ", op16); break;
case 0xaa: sprintf(t, "tax "); break;
case 0xab: sprintf(t, "plb "); break;
case 0xac: sprintf(t, "ldy $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xad: sprintf(t, "lda $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xae: sprintf(t, "ldx $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xaf: sprintf(t, "lda $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xb0: sprintf(t, "bcs $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xb1: sprintf(t, "lda ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xb2: sprintf(t, "lda ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xb3: sprintf(t, "lda ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xb4: sprintf(t, "ldy $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xb5: sprintf(t, "lda $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xb6: sprintf(t, "ldx $%0.2x,y [$%0.6x]", op8, decode(OPTYPE_DPY, op8)); break;
case 0xb7: sprintf(t, "lda [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xb8: sprintf(t, "clv "); break;
case 0xb9: sprintf(t, "lda $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xba: sprintf(t, "tsx "); break;
case 0xbb: sprintf(t, "tyx "); break;
case 0xbc: sprintf(t, "ldy $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xbd: sprintf(t, "lda $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xbe: sprintf(t, "ldx $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xbf: sprintf(t, "lda $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xc0: if(x8)sprintf(t, "cpy #$%0.2x ", op8);
else sprintf(t, "cpy #$%0.4x ", op16); break;
case 0xc1: sprintf(t, "cmp ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xc2: sprintf(t, "rep #$%0.2x ", op8); break;
case 0xc3: sprintf(t, "cmp $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xc4: sprintf(t, "cpy $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc5: sprintf(t, "cmp $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc6: sprintf(t, "dec $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc7: sprintf(t, "cmp [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xc8: sprintf(t, "iny "); break;
case 0xc9: if(a8)sprintf(t, "cmp #$%0.2x ", op8);
else sprintf(t, "cmp #$%0.4x ", op16); break;
case 0xca: sprintf(t, "dex "); break;
case 0xcb: sprintf(t, "wai "); break;
case 0xcc: sprintf(t, "cpy $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xcd: sprintf(t, "cmp $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xce: sprintf(t, "dec $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xcf: sprintf(t, "cmp $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xd0: sprintf(t, "bne $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xd1: sprintf(t, "cmp ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xd2: sprintf(t, "cmp ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xd3: sprintf(t, "cmp ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xd4: sprintf(t, "pei ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xd5: sprintf(t, "cmp $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xd6: sprintf(t, "dec $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xd7: sprintf(t, "cmp [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xd8: sprintf(t, "cld "); break;
case 0xd9: sprintf(t, "cmp $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xda: sprintf(t, "phx "); break;
case 0xdb: sprintf(t, "stp "); break;
case 0xdc: sprintf(t, "jmp [$%0.4x] [$%0.6x]", op16, decode(OPTYPE_ILADDR, op16)); break;
case 0xdd: sprintf(t, "cmp $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xde: sprintf(t, "dec $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xdf: sprintf(t, "cmp $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xe0: if(x8)sprintf(t, "cpx #$%0.2x ", op8);
else sprintf(t, "cpx #$%0.4x ", op16); break;
case 0xe1: sprintf(t, "sbc ($%0.2x,x) [$%0.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xe2: sprintf(t, "sep #$%0.2x ", op8); break;
case 0xe3: sprintf(t, "sbc $%0.2x,s [$%0.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xe4: sprintf(t, "cpx $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe5: sprintf(t, "sbc $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe6: sprintf(t, "inc $%0.2x [$%0.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe7: sprintf(t, "sbc [$%0.2x] [$%0.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xe8: sprintf(t, "inx "); break;
case 0xe9: if(a8)sprintf(t, "sbc #$%0.2x ", op8);
else sprintf(t, "sbc #$%0.4x ", op16); break;
case 0xea: sprintf(t, "nop "); break;
case 0xeb: sprintf(t, "xba "); break;
case 0xec: sprintf(t, "cpx $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xed: sprintf(t, "sbc $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xee: sprintf(t, "inc $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xef: sprintf(t, "sbc $%0.6x [$%0.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xf0: sprintf(t, "beq $%0.4x [$%0.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xf1: sprintf(t, "sbc ($%0.2x),y [$%0.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xf2: sprintf(t, "sbc ($%0.2x) [$%0.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xf3: sprintf(t, "sbc ($%0.2x,s),y [$%0.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xf4: sprintf(t, "pea $%0.4x [$%0.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xf5: sprintf(t, "sbc $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xf6: sprintf(t, "inc $%0.2x,x [$%0.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xf7: sprintf(t, "sbc [$%0.2x],y [$%0.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xf8: sprintf(t, "sed "); break;
case 0xf9: sprintf(t, "sbc $%0.4x,y [$%0.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xfa: sprintf(t, "plx "); break;
case 0xfb: sprintf(t, "xce "); break;
case 0xfc: sprintf(t, "jsr ($%0.4x,x) [$%0.6x]", op16, decode(OPTYPE_IADDRX, op16)); break;
case 0xfd: sprintf(t, "sbc $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xfe: sprintf(t, "inc $%0.4x,x [$%0.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xff: sprintf(t, "sbc $%0.6x,x [$%0.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
}
#undef op8
#undef op16
#undef op24
#undef a8
#undef x8
strcat(s, t);
strcat(s, " ");
sprintf(t, "A:%0.4x X:%0.4x Y:%0.4x S:%0.4x D:%0.4x DB:%0.2x ",
regs.a.w, regs.x.w, regs.y.w, regs.s.w, regs.d.w, regs.db);
strcat(s, t);
if(regs.e) {
sprintf(t, "%c%c%c%c%c%c%c%c",
(regs.p.n)?'N':'n', (regs.p.v)?'V':'v',
(regs.p.m)?'1':'0', (regs.p.x)?'B':'b',
(regs.p.d)?'D':'d', (regs.p.i)?'I':'i',
(regs.p.z)?'Z':'z', (regs.p.c)?'C':'c');
(regs.p.n) ? 'N' : 'n', (regs.p.v) ? 'V' : 'v',
(regs.p.m) ? '1' : '0', (regs.p.x) ? 'B' : 'b',
(regs.p.d) ? 'D' : 'd', (regs.p.i) ? 'I' : 'i',
(regs.p.z) ? 'Z' : 'z', (regs.p.c) ? 'C' : 'c');
} else {
sprintf(t, "%c%c%c%c%c%c%c%c",
(regs.p.n)?'N':'n', (regs.p.v)?'V':'v',
(regs.p.m)?'M':'m', (regs.p.x)?'X':'x',
(regs.p.d)?'D':'d', (regs.p.i)?'I':'i',
(regs.p.z)?'Z':'z', (regs.p.c)?'C':'c');
(regs.p.n) ? 'N' : 'n', (regs.p.v) ? 'V' : 'v',
(regs.p.m) ? 'M' : 'm', (regs.p.x) ? 'X' : 'x',
(regs.p.d) ? 'D' : 'd', (regs.p.i) ? 'I' : 'i',
(regs.p.z) ? 'Z' : 'z', (regs.p.c) ? 'C' : 'c');
}
strcat(s, t);
}
/*
opcode_length() retrieves the length of the next opcode
to be executed. It is used by the debugger to step over,
disable, and proceed cpu opcodes.
5 and 6 are special cases, 5 is used for #consts based on
the A register size, 6 for the X/Y register size. the
rest are literal sizes. There's no need to test for
emulation mode, as regs.p.m/regs.p.x should *always* be
set in emulation mode.
*/
/*****
* opcode_length() retrieves the length of the next opcode
* to be executed. It is used by the debugger to step over,
* disable and proceed cpu opcodes.
*
* 5 and 6 are special cases, 5 is used for #consts based on
* the A register size, 6 for the X/Y register size. the
* rest are literal sizes. There's no need to test for
* emulation mode, as regs.p.m/regs.p.x should *always* be
* set in emulation mode.
*****/
uint8 CPU::opcode_length() {
uint8 op, len;
static uint8 op_len_tbl[256] = {
//0,1,2,3, 4,5,6,7, 8,9,a,b, c,d,e,f
2,2,2,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x0n
2,2,2,2, 2,2,2,2, 1,3,1,1, 3,3,3,4, //0x1n
3,2,4,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0x2n
@@ -457,9 +463,9 @@ static uint8 op_len_tbl[256] = {
return 0;
}
op = r_mem->read(regs.pc.d);
op = dreadb(regs.pc.d);
len = op_len_tbl[op];
if(len == 5)return (regs.p.m)?2:3;
if(len == 6)return (regs.p.x)?2:3;
if(len == 5)return (regs.e || regs.p.m) ? 2 : 3;
if(len == 6)return (regs.e || regs.p.x) ? 2 : 3;
return len;
}

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

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

View File

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

View File

@@ -0,0 +1,76 @@
#include "opfn.cpp"
void sCPU::main() {
for(;;) {
#ifdef DEBUGGER
snes->notify(SNES::CPU_EXEC_OPCODE_BEGIN);
#endif
status.in_opcode = true;
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();
}
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 DEBUGGER
snes->notify(SNES::CPU_EXEC_OPCODE_END);
#endif
#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;
#ifdef DEBUGGER
status.in_opcode = false;
snes->notify(SNES::CPU_EXEC_OPCODE_END);
status.in_opcode = true;
#endif
}
//
void sCPU::op_io_cond2() {
if(regs.d.l != 0x00)op_io();
}
void sCPU::op_io_cond4(uint16 x, uint16 y) {
if(!regs.p.x && (x & 0xff00) != (y & 0xff00))op_io();
}
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);
}

View File

@@ -0,0 +1,570 @@
//inc
case 0x1a: {
last_cycle();
op_io();
if(regs.acc_8b) {
regs.a.l++;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.a.w++;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//inx
case 0xe8: {
last_cycle();
op_io();
if(regs.idx_8b) {
regs.x.l++;
regs.p.n = bool(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
} else {
regs.x.w++;
regs.p.n = bool(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
} break;
//iny
case 0xc8: {
last_cycle();
op_io();
if(regs.idx_8b) {
regs.y.l++;
regs.p.n = bool(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
} else {
regs.y.w++;
regs.p.n = bool(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
}
} break;
//dec
case 0x3a: {
last_cycle();
op_io();
if(regs.acc_8b) {
regs.a.l--;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.a.w--;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//dex
case 0xca: {
last_cycle();
op_io();
if(regs.idx_8b) {
regs.x.l--;
regs.p.n = bool(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
} else {
regs.x.w--;
regs.p.n = bool(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
} break;
//dey
case 0x88: {
last_cycle();
op_io();
if(regs.idx_8b) {
regs.y.l--;
regs.p.n = bool(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
} else {
regs.y.w--;
regs.p.n = bool(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
}
} break;
//asl
case 0x0a: {
last_cycle();
op_io();
if(regs.acc_8b) {
regs.p.c = bool(regs.a.l & 0x80);
regs.a.l <<= 1;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = bool(regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//lsr
case 0x4a: {
last_cycle();
op_io();
if(regs.acc_8b) {
regs.p.c = regs.a.l & 1;
regs.a.l >>= 1;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = regs.a.w & 1;
regs.a.w >>= 1;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//rol
case 0x2a: {
last_cycle();
op_io();
uint16 c = regs.p.c;
if(regs.acc_8b) {
regs.p.c = bool(regs.a.l & 0x80);
regs.a.l <<= 1;
regs.a.l |= c;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = bool(regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.a.w |= c;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//ror
case 0x6a: {
last_cycle();
op_io();
uint16 c;
if(regs.acc_8b) {
c = (regs.p.c)?0x80:0;
regs.p.c = regs.a.l & 1;
regs.a.l >>= 1;
regs.a.l |= c;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
c = (regs.p.c)?0x8000:0;
regs.p.c = regs.a.w & 1;
regs.a.w >>= 1;
regs.a.w |= c;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//inc_addr
case 0xee: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.acc_8b) { op_inc_b(); }
else { op_inc_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//dec_addr
case 0xce: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.acc_8b) { op_dec_b(); }
else { op_dec_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//asl_addr
case 0x0e: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.acc_8b) { op_asl_b(); }
else { op_asl_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//lsr_addr
case 0x4e: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.acc_8b) { op_lsr_b(); }
else { op_lsr_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//rol_addr
case 0x2e: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.acc_8b) { op_rol_b(); }
else { op_rol_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//ror_addr
case 0x6e: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.acc_8b) { op_ror_b(); }
else { op_ror_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//trb_addr
case 0x1c: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.acc_8b) { op_trb_b(); }
else { op_trb_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//tsb_addr
case 0x0c: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.acc_8b) { op_tsb_b(); }
else { op_tsb_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//inc_addrx
case 0xfe: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_inc_b(); }
else { op_inc_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
} break;
//dec_addrx
case 0xde: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_dec_b(); }
else { op_dec_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
} break;
//asl_addrx
case 0x1e: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_asl_b(); }
else { op_asl_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
} break;
//lsr_addrx
case 0x5e: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_lsr_b(); }
else { op_lsr_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
} break;
//rol_addrx
case 0x3e: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_rol_b(); }
else { op_rol_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
} break;
//ror_addrx
case 0x7e: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_ror_b(); }
else { op_ror_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
} break;
//inc_dp
case 0xe6: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
op_io();
if(regs.acc_8b) { op_inc_b(); }
else { op_inc_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//dec_dp
case 0xc6: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
op_io();
if(regs.acc_8b) { op_dec_b(); }
else { op_dec_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//asl_dp
case 0x06: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
op_io();
if(regs.acc_8b) { op_asl_b(); }
else { op_asl_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//lsr_dp
case 0x46: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
op_io();
if(regs.acc_8b) { op_lsr_b(); }
else { op_lsr_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//rol_dp
case 0x26: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
op_io();
if(regs.acc_8b) { op_rol_b(); }
else { op_rol_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//ror_dp
case 0x66: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
op_io();
if(regs.acc_8b) { op_ror_b(); }
else { op_ror_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//trb_dp
case 0x14: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
op_io();
if(regs.acc_8b) { op_trb_b(); }
else { op_trb_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//tsb_dp
case 0x04: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
op_io();
if(regs.acc_8b) { op_tsb_b(); }
else { op_tsb_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//inc_dpx
case 0xf6: {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_inc_b(); }
else { op_inc_w();
op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle();
op_writedp(dp + regs.x.w, rd.l);
} break;
//dec_dpx
case 0xd6: {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_dec_b(); }
else { op_dec_w();
op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle();
op_writedp(dp + regs.x.w, rd.l);
} break;
//asl_dpx
case 0x16: {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_asl_b(); }
else { op_asl_w();
op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle();
op_writedp(dp + regs.x.w, rd.l);
} break;
//lsr_dpx
case 0x56: {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_lsr_b(); }
else { op_lsr_w();
op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle();
op_writedp(dp + regs.x.w, rd.l);
} break;
//rol_dpx
case 0x36: {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_rol_b(); }
else { op_rol_w();
op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle();
op_writedp(dp + regs.x.w, rd.l);
} break;
//ror_dpx
case 0x76: {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
if(regs.acc_8b) { op_ror_b(); }
else { op_ror_w();
op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle();
op_writedp(dp + regs.x.w, rd.l);
} break;

View File

@@ -0,0 +1,181 @@
sta_addr(0x8d, regs.acc_8b, regs.a.w),
stx_addr(0x8e, regs.idx_8b, regs.x.w),
sty_addr(0x8c, regs.idx_8b, regs.y.w),
stz_addr(0x9c, regs.acc_8b, 0x0000) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:if($1)last_cycle();
op_writedbr(aa.w, $2);
if($1)end;
4:last_cycle();
op_writedbr(aa.w + 1, $2 >> 8);
}
sta_addrx(0x9d, regs.acc_8b, regs.a.w),
stz_addrx(0x9e, regs.acc_8b, 0x0000) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io_cond4(aa.w, aa.w + regs.x.w);
4:if($1)last_cycle();
op_writedbr(aa.w + regs.x.w, $2);
if($1)end;
5:last_cycle();
op_writedbr(aa.w + regs.x.w + 1, $2 >> 8);
}
sta_addry(0x99) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io_cond4(aa.w, aa.w + regs.y.w);
4:if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)end;
5:last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}
sta_long(0x8f) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if(regs.acc_8b)last_cycle();
op_writelong(aa.d, regs.a.l);
if(regs.acc_8b)end;
5:last_cycle();
op_writelong(aa.d + 1, regs.a.h);
}
sta_longx(0x9f) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if(regs.acc_8b)last_cycle();
op_writelong(aa.d + regs.x.w, regs.a.l);
if(regs.acc_8b)end;
5:last_cycle();
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
}
sta_dp(0x85, regs.acc_8b, regs.a.w),
stx_dp(0x86, regs.idx_8b, regs.x.w),
sty_dp(0x84, regs.idx_8b, regs.y.w),
stz_dp(0x64, regs.acc_8b, 0x0000) {
1:dp = op_readpc();
2:op_io_cond2();
3:if($1)last_cycle();
op_writedp(dp, $2);
if($1)end;
4:last_cycle();
op_writedp(dp + 1, $2 >> 8);
}
sta_dpx(0x95, regs.acc_8b, regs.a.w),
sty_dpx(0x94, regs.idx_8b, regs.y.w),
stz_dpx(0x74, regs.acc_8b, 0x0000) {
1:dp = op_readpc();
2:op_io_cond2();
3:op_io();
4:if($1)last_cycle();
op_writedp(dp + regs.x.w, $2);
if($1)end;
5:last_cycle();
op_writedp(dp + regs.x.w + 1, $2 >> 8);
}
stx_dpy(0x96) {
1:dp = op_readpc();
2:op_io_cond2();
3:op_io();
4:if(regs.idx_8b)last_cycle();
op_writedp(dp + regs.y.w, regs.x.l);
if(regs.idx_8b)end;
5:last_cycle();
op_writedp(dp + regs.y.w + 1, regs.x.h);
}
sta_idp(0x92) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:if(regs.acc_8b)last_cycle();
op_writedbr(aa.w, regs.a.l);
if(regs.acc_8b)end;
6:last_cycle();
op_writedbr(aa.w + 1, regs.a.h);
}
sta_ildp(0x87) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if(regs.acc_8b)last_cycle();
op_writelong(aa.d, regs.a.l);
if(regs.acc_8b)end;
7:last_cycle();
op_writelong(aa.d + 1, regs.a.h);
}
sta_idpx(0x81) {
1:dp = op_readpc();
2:op_io_cond2();
3:op_io();
4:aa.l = op_readdp(dp + regs.x.w);
5:aa.h = op_readdp(dp + regs.x.w + 1);
6:if(regs.acc_8b)last_cycle();
op_writedbr(aa.w, regs.a.l);
if(regs.acc_8b)end;
7:last_cycle();
op_writedbr(aa.w + 1, regs.a.h);
}
sta_idpy(0x91) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:op_io_cond4(aa.w, aa.w + regs.y.w);
6:if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)end;
7:last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}
sta_ildpy(0x97) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if(regs.acc_8b)last_cycle();
op_writelong(aa.d + regs.y.w, regs.a.l);
if(regs.acc_8b)end;
7:last_cycle();
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
}
sta_sr(0x83) {
1:sp = op_readpc();
2:op_io();
3:if(regs.acc_8b)last_cycle();
op_writesp(sp, regs.a.l);
if(regs.acc_8b)end;
4:last_cycle();
op_writesp(sp + 1, regs.a.h);
}
sta_isry(0x93) {
1:sp = op_readpc();
2:op_io();
3:aa.l = op_readsp(sp);
4:aa.h = op_readsp(sp + 1);
5:op_io();
6:if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)end;
7:last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}

View File

@@ -0,0 +1,290 @@
//sta_addr
case 0x8d: {
aa.l = op_readpc();
aa.h = op_readpc();
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w, regs.a.w);
if(regs.acc_8b)break;
last_cycle();
op_writedbr(aa.w + 1, regs.a.w >> 8);
} break;
//stx_addr
case 0x8e: {
aa.l = op_readpc();
aa.h = op_readpc();
if(regs.idx_8b)last_cycle();
op_writedbr(aa.w, regs.x.w);
if(regs.idx_8b)break;
last_cycle();
op_writedbr(aa.w + 1, regs.x.w >> 8);
} break;
//sty_addr
case 0x8c: {
aa.l = op_readpc();
aa.h = op_readpc();
if(regs.idx_8b)last_cycle();
op_writedbr(aa.w, regs.y.w);
if(regs.idx_8b)break;
last_cycle();
op_writedbr(aa.w + 1, regs.y.w >> 8);
} break;
//stz_addr
case 0x9c: {
aa.l = op_readpc();
aa.h = op_readpc();
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w, 0x0000);
if(regs.acc_8b)break;
last_cycle();
op_writedbr(aa.w + 1, 0x0000 >> 8);
} break;
//sta_addrx
case 0x9d: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io_cond4(aa.w, aa.w + regs.x.w);
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.x.w, regs.a.w);
if(regs.acc_8b)break;
last_cycle();
op_writedbr(aa.w + regs.x.w + 1, regs.a.w >> 8);
} break;
//stz_addrx
case 0x9e: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io_cond4(aa.w, aa.w + regs.x.w);
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.x.w, 0x0000);
if(regs.acc_8b)break;
last_cycle();
op_writedbr(aa.w + regs.x.w + 1, 0x0000 >> 8);
} break;
//sta_addry
case 0x99: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io_cond4(aa.w, aa.w + regs.y.w);
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
} break;
//sta_long
case 0x8f: {
aa.l = op_readpc();
aa.h = op_readpc();
aa.b = op_readpc();
if(regs.acc_8b)last_cycle();
op_writelong(aa.d, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writelong(aa.d + 1, regs.a.h);
} break;
//sta_longx
case 0x9f: {
aa.l = op_readpc();
aa.h = op_readpc();
aa.b = op_readpc();
if(regs.acc_8b)last_cycle();
op_writelong(aa.d + regs.x.w, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
} break;
//sta_dp
case 0x85: {
dp = op_readpc();
op_io_cond2();
if(regs.acc_8b)last_cycle();
op_writedp(dp, regs.a.w);
if(regs.acc_8b)break;
last_cycle();
op_writedp(dp + 1, regs.a.w >> 8);
} break;
//stx_dp
case 0x86: {
dp = op_readpc();
op_io_cond2();
if(regs.idx_8b)last_cycle();
op_writedp(dp, regs.x.w);
if(regs.idx_8b)break;
last_cycle();
op_writedp(dp + 1, regs.x.w >> 8);
} break;
//sty_dp
case 0x84: {
dp = op_readpc();
op_io_cond2();
if(regs.idx_8b)last_cycle();
op_writedp(dp, regs.y.w);
if(regs.idx_8b)break;
last_cycle();
op_writedp(dp + 1, regs.y.w >> 8);
} break;
//stz_dp
case 0x64: {
dp = op_readpc();
op_io_cond2();
if(regs.acc_8b)last_cycle();
op_writedp(dp, 0x0000);
if(regs.acc_8b)break;
last_cycle();
op_writedp(dp + 1, 0x0000 >> 8);
} break;
//sta_dpx
case 0x95: {
dp = op_readpc();
op_io_cond2();
op_io();
if(regs.acc_8b)last_cycle();
op_writedp(dp + regs.x.w, regs.a.w);
if(regs.acc_8b)break;
last_cycle();
op_writedp(dp + regs.x.w + 1, regs.a.w >> 8);
} break;
//sty_dpx
case 0x94: {
dp = op_readpc();
op_io_cond2();
op_io();
if(regs.idx_8b)last_cycle();
op_writedp(dp + regs.x.w, regs.y.w);
if(regs.idx_8b)break;
last_cycle();
op_writedp(dp + regs.x.w + 1, regs.y.w >> 8);
} break;
//stz_dpx
case 0x74: {
dp = op_readpc();
op_io_cond2();
op_io();
if(regs.acc_8b)last_cycle();
op_writedp(dp + regs.x.w, 0x0000);
if(regs.acc_8b)break;
last_cycle();
op_writedp(dp + regs.x.w + 1, 0x0000 >> 8);
} break;
//stx_dpy
case 0x96: {
dp = op_readpc();
op_io_cond2();
op_io();
if(regs.idx_8b)last_cycle();
op_writedp(dp + regs.y.w, regs.x.l);
if(regs.idx_8b)break;
last_cycle();
op_writedp(dp + regs.y.w + 1, regs.x.h);
} break;
//sta_idp
case 0x92: {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1);
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writedbr(aa.w + 1, regs.a.h);
} break;
//sta_ildp
case 0x87: {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
if(regs.acc_8b)last_cycle();
op_writelong(aa.d, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writelong(aa.d + 1, regs.a.h);
} break;
//sta_idpx
case 0x81: {
dp = op_readpc();
op_io_cond2();
op_io();
aa.l = op_readdp(dp + regs.x.w);
aa.h = op_readdp(dp + regs.x.w + 1);
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writedbr(aa.w + 1, regs.a.h);
} break;
//sta_idpy
case 0x91: {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1);
op_io_cond4(aa.w, aa.w + regs.y.w);
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
} break;
//sta_ildpy
case 0x97: {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
if(regs.acc_8b)last_cycle();
op_writelong(aa.d + regs.y.w, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
} break;
//sta_sr
case 0x83: {
sp = op_readpc();
op_io();
if(regs.acc_8b)last_cycle();
op_writesp(sp, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writesp(sp + 1, regs.a.h);
} break;
//sta_isry
case 0x93: {
sp = op_readpc();
op_io();
aa.l = op_readsp(sp);
aa.h = op_readsp(sp + 1);
op_io();
if(regs.acc_8b)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)break;
last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
} break;

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

@@ -0,0 +1,377 @@
//op_read
inline void sCPU::op_adc_b() {
int32 r = regs.a.l + rd.l + regs.p.c;
if(regs.p.d) {
uint8 n0 = (regs.a.l ) & 15;
uint8 n1 = (regs.a.l >> 4) & 15;
n0 += ((rd.l) & 15) + regs.p.c;
if(n0 > 9) {
n0 -= 10;
n0 &= 15;
n1++;
}
n1 += ((rd.l >> 4) & 15);
if(n1 > 9) {
n1 -= 10;
n1 &= 15;
regs.p.c = 1;
} else {
regs.p.c = 0;
}
r = (n1 << 4) | (n0);
} else {
r = regs.a.l + rd.l + regs.p.c;
regs.p.c = (r > 0xff);
}
regs.p.n = bool(r & 0x80);
regs.p.v = bool(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
regs.p.z = ((uint8)r == 0);
regs.a.l = r;
}
inline void sCPU::op_adc_w() {
int32 r;
if(regs.p.d) {
uint8 n0 = (regs.a.w ) & 15;
uint8 n1 = (regs.a.w >> 4) & 15;
uint8 n2 = (regs.a.w >> 8) & 15;
uint8 n3 = (regs.a.w >> 12) & 15;
n0 += ((rd.w) & 15) + regs.p.c;
if(n0 > 9) {
n0 -= 10;
n0 &= 15;
n1++;
}
n1 += ((rd.w >> 4) & 15);
if(n1 > 9) {
n1 -= 10;
n1 &= 15;
n2++;
}
n2 += ((rd.w >> 8) & 15);
if(n2 > 9) {
n2 -= 10;
n2 &= 15;
n3++;
}
n3 += ((rd.w >> 12) & 15);
if(n3 > 9) {
n3 -= 10;
n3 &= 15;
regs.p.c = 1;
} else {
regs.p.c = 0;
}
r = (n3 << 12) | (n2 << 8) | (n1 << 4) | (n0);
} else {
r = regs.a.w + rd.w + regs.p.c;
regs.p.c = (r > 0xffff);
}
regs.p.n = bool(r & 0x8000);
regs.p.v = bool(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.a.w = r;
}
inline void sCPU::op_and_b() {
regs.a.l &= rd.l;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
inline void sCPU::op_and_w() {
regs.a.w &= rd.w;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
inline void sCPU::op_bit_b() {
regs.p.n = bool(rd.l & 0x80);
regs.p.v = bool(rd.l & 0x40);
regs.p.z = ((rd.l & regs.a.l) == 0);
}
inline void sCPU::op_bit_w() {
regs.p.n = bool(rd.w & 0x8000);
regs.p.v = bool(rd.w & 0x4000);
regs.p.z = ((rd.w & regs.a.w) == 0);
}
inline void sCPU::op_cmp_b() {
int32 r = regs.a.l - rd.l;
regs.p.n = bool(r & 0x80);
regs.p.z = ((uint8)r == 0);
regs.p.c = (r >= 0);
}
inline void sCPU::op_cmp_w() {
int32 r = regs.a.w - rd.w;
regs.p.n = bool(r & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.p.c = (r >= 0);
}
inline void sCPU::op_cpx_b() {
int32 r = regs.x.l - rd.l;
regs.p.n = bool(r & 0x80);
regs.p.z = ((uint8)r == 0);
regs.p.c = (r >= 0);
}
inline void sCPU::op_cpx_w() {
int32 r = regs.x.w - rd.w;
regs.p.n = bool(r & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.p.c = (r >= 0);
}
inline void sCPU::op_cpy_b() {
int32 r = regs.y.l - rd.l;
regs.p.n = bool(r & 0x80);
regs.p.z = ((uint8)r == 0);
regs.p.c = (r >= 0);
}
inline void sCPU::op_cpy_w() {
int32 r = regs.y.w - rd.w;
regs.p.n = bool(r & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.p.c = (r >= 0);
}
inline void sCPU::op_eor_b() {
regs.a.l ^= rd.l;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
inline void sCPU::op_eor_w() {
regs.a.w ^= rd.w;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
inline void sCPU::op_lda_b() {
regs.a.l = rd.l;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
inline void sCPU::op_lda_w() {
regs.a.w = rd.w;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
inline void sCPU::op_ldx_b() {
regs.x.l = rd.l;
regs.p.n = bool(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
}
inline void sCPU::op_ldx_w() {
regs.x.w = rd.w;
regs.p.n = bool(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
inline void sCPU::op_ldy_b() {
regs.y.l = rd.l;
regs.p.n = bool(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
}
inline void sCPU::op_ldy_w() {
regs.y.w = rd.w;
regs.p.n = bool(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
}
inline void sCPU::op_ora_b() {
regs.a.l |= rd.l;
regs.p.n = bool(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
inline void sCPU::op_ora_w() {
regs.a.w |= rd.w;
regs.p.n = bool(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
inline void sCPU::op_sbc_b() {
int32 r;
if(regs.p.d) {
uint8 n0 = (regs.a.l ) & 15;
uint8 n1 = (regs.a.l >> 4) & 15;
n0 -= ((rd.l ) & 15) + !regs.p.c;
n1 -= ((rd.l >> 4) & 15);
if(n0 > 9) {
n0 += 10;
n1--;
}
if(n1 > 9) {
n1 += 10;
regs.p.c = 0;
} else {
regs.p.c = 1;
}
r = (n1 << 4) | (n0);
} else {
r = regs.a.l - rd.l - !regs.p.c;
regs.p.c = (r >= 0);
}
regs.p.n = bool(r & 0x80);
regs.p.v = bool((regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
regs.p.z = ((uint8)r == 0);
regs.a.l = r;
}
inline void sCPU::op_sbc_w() {
int32 r;
if(regs.p.d) {
uint8 n0 = (regs.a.w ) & 15;
uint8 n1 = (regs.a.w >> 4) & 15;
uint8 n2 = (regs.a.w >> 8) & 15;
uint8 n3 = (regs.a.w >> 12) & 15;
n0 -= ((rd.w ) & 15) + !regs.p.c;
n1 -= ((rd.w >> 4) & 15);
n2 -= ((rd.w >> 8) & 15);
n3 -= ((rd.w >> 12) & 15);
if(n0 > 9) {
n0 += 10;
n1--;
}
if(n1 > 9) {
n1 += 10;
n2--;
}
if(n2 > 9) {
n2 += 10;
n3--;
}
if(n3 > 9) {
n3 += 10;
regs.p.c = 0;
} else {
regs.p.c = 1;
}
r = (n3 << 12) | (n2 << 8) | (n1 << 4) | (n0);
} else {
r = regs.a.w - rd.w - !regs.p.c;
regs.p.c = (r >= 0);
}
regs.p.n = bool(r & 0x8000);
regs.p.v = bool((regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.a.w = r;
}
//op_rmw
inline void sCPU::op_inc_b() {
rd.l++;
regs.p.n = bool(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void sCPU::op_inc_w() {
rd.w++;
regs.p.n = bool(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void sCPU::op_dec_b() {
rd.l--;
regs.p.n = bool(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void sCPU::op_dec_w() {
rd.w--;
regs.p.n = bool(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void sCPU::op_asl_b() {
regs.p.c = bool(rd.l & 0x80);
rd.l <<= 1;
regs.p.n = bool(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void sCPU::op_asl_w() {
regs.p.c = bool(rd.w & 0x8000);
rd.w <<= 1;
regs.p.n = bool(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void sCPU::op_lsr_b() {
regs.p.c = rd.l & 1;
rd.l >>= 1;
regs.p.n = bool(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void sCPU::op_lsr_w() {
regs.p.c = rd.w & 1;
rd.w >>= 1;
regs.p.n = bool(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void sCPU::op_rol_b() {
uint16 c = regs.p.c;
regs.p.c = bool(rd.l & 0x80);
rd.l <<= 1;
rd.l |= c;
regs.p.n = bool(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void sCPU::op_rol_w() {
uint16 c = regs.p.c;
regs.p.c = bool(rd.w & 0x8000);
rd.w <<= 1;
rd.w |= c;
regs.p.n = bool(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void sCPU::op_ror_b() {
uint16 c = (regs.p.c)?0x80:0;
regs.p.c = rd.l & 1;
rd.l >>= 1;
rd.l |= c;
regs.p.n = bool(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void sCPU::op_ror_w() {
uint16 c = (regs.p.c)?0x8000:0;
regs.p.c = rd.w & 1;
rd.w >>= 1;
rd.w |= c;
regs.p.n = bool(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void sCPU::op_trb_b() {
regs.p.z = ((rd.l & regs.a.l) == 0);
rd.l &= ~regs.a.l;
}
inline void sCPU::op_trb_w() {
regs.p.z = ((rd.w & regs.a.w) == 0);
rd.w &= ~regs.a.w;
}
inline void sCPU::op_tsb_b() {
regs.p.z = ((rd.l & regs.a.l) == 0);
rd.l |= regs.a.l;
}
inline void sCPU::op_tsb_w() {
regs.p.z = ((rd.w & regs.a.w) == 0);
rd.w |= regs.a.w;
}

View File

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

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