Compare commits

..

7 Commits
v018 ... v019

Author SHA1 Message Date
byuu
1ebdb69516 Update to bsnes v019 release.
I´m releasing bsnes v0.019 today. This version contains Bandai Sufami Turbo support, new IRQ emulation code, and some various bugfixes.
Unfortunately, this release is not entirely cause for celebration. Due to fatal errors in Microsoft´s "enterprise class" c++ compiler package, I am no longer able to compile bsnes with profile guided optimizations. I have tested v0.018 with and without these optimizations, and the difference is a 40% speedup when PGO is used, even more significant than I had previously believed. However, bsnes has now become too complex for Visual C++ to handle. Unfortunately, there is nothing I can do about this, except wait for Microsoft to fix their compiler.
(Warning: this paragraph contains personal opinions, skip it if you can´t handle that) As if this wasn´t enough, I´m now doing my best to wean my dependence from Microsoft´s line of operating systems, as I´m particularly concerned about the black box nature of Vista and its´ DRM control mechanisms. This isn´t a road I wish to begin traveling down, and thusly have no interest in upgrading to future versions of Windows. Therefore, as of late, I´ve been writing a UI wrapper that will allow me to code applications that are truly platform independent. The biggest goal for this library is to design a GUI for bsnes that runs virtually identically on both Windows and Linux/BSD. This is mostly complete, however there were many tricks I used in bsnes using the win32 API that I simply cannot do with GTK+ on Linux/BSD, such as the memory editor window subclassing. I will be porting bsnes to use this new UI wrapper, and in turn this will lessen the attractiveness / functionality of the bsnes UI to a certain degree.
Perhaps the most devastating news is that I am still contemplating the idea of designing a dot-based PPU renderer for bsnes. As if the loss of PGO wasn´t bad enough, this will likely eat away an unimaginable level of performance as well. I can only estimate the speed loss being between 100-500%. Yes, it will be that bad. And despite weeks of planning, I cannot think of a way to allow a scanline-based and dot-based renderer to coexist as selectable options, given their massive differences in implementation.
And let´s not even joke about SA-1 or SuperFX support ... those processors are each four to eight times more powerful than the SNES´ main CPU.
All of these speed losses will basically make bsnes mostly irrelevant as an alternative to ZSNES, SNES9x et al. Although I believe I really came close to a viable alternative with v0.018, I know that I cannot both create a mainstream emulator, as well as keep with my original goal to emulate the SNES as accurately as possible.
The past few months have been very tough for me; trying to decide which of the above two goals to pursue. I´ve still not absolutely made up my mind. But for now, I´ve been sitting on a mostly untouched version of bsnes for the last few months, and have decided to release it to the public, profile guided optimizations be damned.
I´m once again asking for help, if anyone can figure out why bsnes won´t compile with PGO support, please let me know. I´d very much like to get one last PGO build of bsnes released before starting on a dot-based PPU renderer. But given the usual response I get from these requests for help, I´d suggest no one getting their hopes up that bsnes will ever be as fast as it once was again.
The new version can be downloaded at the usual place. I´m leaving v0.018 up, as it may very well be the last stable, fast version of bsnes ever released.
2007-01-01 21:04:34 +00:00
byuu
add0f74387 Update to bsnes v018r10? release.
Ok, Sufami Turbo is finished. Now I just need to add back in
cheat/patch loading, and that should do for src/cart modifications for
a while.
             Maybe I'll add split ROM support while I'm at it just for
fun.

             There's now _some_ safety code regarding ST loading, but
it's not all there. Specifically, if a file fails to load, then you
won't get any errors, the game will just not work, obviously. I now
protect against loading oversized ROMs and SRAM files.

The database now lists each Sufami Turbo cart only once, and the cart
loading code handles matching up two ROMs from the database. It is
also now possible to play ST games with invalid checksums, so eg
translations/hacks of these games should now be possible, however
unlikely.

             FF:MQ (E) is fixed now too, so we're back to
FAVOR_ACCURACY in WIP builds again.

 A little more src/cart polishing and I'm going to start documenting
all that's known about IRQs, and try and figure out how they work once
and for all (hahah, yeah right -- I give it 2-3 weeks after fixing it
again before more problems are found).

[No archive available]
2006-11-07 08:55:00 +00:00
byuu
b20f70f333 Update to bsnes v018r09? release.
Ok, the new WIP is extremely fragile with ST stuff, but it should work
if you're careful.

             It took a _lot_ of rewriting to get those damn dual carts
booting. Right now, everything but the SD Gundam games are in the
database. I need to think of a way of combining those. So, the only
other dualable game is SD Ultra Battle - Ultraman Densetsu + Seven
Densetsu. Otherwise, test with just one ST cartridge at a time.

Anyway, it's definitely a work in progress, so be gentle with it. You
need "stbios.bin" in bsnes.cfg::path.bios for it to work. It probably
won't even give you an error if it isn't there.

             Suggestions for how to layout the file menu are welcome.

[No archive available]
2006-11-06 07:51:00 +00:00
byuu
9aebf7bc6b Update to bsnes v018r08? release.
Ok, the new WIP adds ppu.hack.obj_cache = [true/false], and renames
the scanline render pos to ppu.hack.scanline_render_position = [dec].

             OBJ cache defaults to off now, as two bugs are better
than four.

 Made SDP a bit more friendly to view now. I may port that style over
to my main website, too. Specifically the non fixed width part.

[No archive available]
2006-11-03 07:58:00 +00:00
byuu
a7bf219d5d Update to bsnes v018r07? release.
> Overall, I have a small list of possibles. Will wait until after
> R-Type to explore.




               Damn :(
 I don't think the R-Type III fix will correct anything else. But,
cross your fingers I guess. The new WIP fixes the aforementioned game.

 My SNES tests seem to indicate that writing #$20 to $4200 when
VCOUNTER==VIRQ will trigger an IRQ, even after an IRQ has already
fired on said line. My tests today indicate that it will not trigger
an IRQ under the above circumstances when the I flag is set. I don't
know why, it's the only thing other than the final IRQ trigger test
that cares what the I flag is set to. I'm not happy with the fix, but
it's the only explanation I can come up with, and all IRQ sensitive
games are running, as well all IRQ tests are still passing. So for
now, it'll have to do.

 I'm going to attempt to document all of SNES IRQs and see if I can
figure out a more simple method of emulating them, but I'm not
hopeful.

 I also removed the "guessed" entries from my database. I've decided
not to add anything unless we definitively know its' PCB ID, or in the
case of ST games, if it doesn't have one.

 Lastly, rewrote my SDP page on my site. It now uses XHTML 1.0 + pure
CSS2, so it should be a little easier on the eyes and a lot easier to
write documentation pages for.

[No archive available]
2006-11-01 09:05:00 +00:00
byuu
04118be59a Update to bsnes v018r04 release.
Ok, _please_ be courteous to my webhost and only download this WIP if
you're going to test it on a processor that hasn't been tested thus
far.

             byuu.org/files/bsnes_v018_wip4.zip
             byuu.org/files/bsnes_tests.zip

 This has two separate builds. Neither have PGO, SSE, SSE2, ZIP or JMA
support. They are identical except for the FAVOR_ flag define and
title of the program.

             FAVOR_ACCURACY [bsnes_accurate.exe]:
             - Always tests OAM RTO flags even on skipped frames
             - Tests NMI/IRQ trigger every clock cycle

             FAVOR_SPEED [bsnes_fast.exe]:
             - Only tests OAM RTO flags on rendered frames (always
with no frameskipping)
             - Tests NMI/IRQ trigger using ranges

 If you'd like to test, please run demo_mode3.smc on both versions of
bsnes, turn off speed regulation, and report the framerate both with a
frameskip of zero and a frameskip of nine (max), along with your
processor speed.

 The other test ROMs are just to verify that IRQ behavior is still
reliable in both versions. A blue screen indicates passing, they all
pass on both versions. Don't expect test_* ROMs to pass on other
emulators, but demo_* ones should.

             Example (my main PC):
             AMD Athlon 3500+

             Accurate:
             - 121.5 fps w/o frameskipping
             - 171 fps w/max frameskipping

             Fast:
             - 146.5 fps w/o frameskipping
             - 271.5 fps w/max frameskipping

             -----

             As you can see, there are _major_ speed differences on my
A64. Personally, I'm all for accuracy, but I also want people to
actually be able to use this program in the interim. Perhaps in the
future when a low end computer is a current low-end Core 2 Duo, we can
remove all of the "speedhack" code. And in the meantime, the full 100%
precision is there for people who have the CPU power to afford it.

             -----

             If anyone wants to try and help, heh.
 src/cpu/scpu/timing/irqtiming_accurate.cpp and
src/cpu/scpu/timing/irqtiming_fast.cpp are the two versions of the IRQ
testing code. If you see any ways to optimize either (preferrably the
former, obviously), I'd greatly appreciate it. Understand that both
the CPU counters (VCOUNTER, HCLOCK) and the IRQ timing positions
(VIRQPOS, HIRQPOS) can wrap not only the horizontal clock position
(1362->0), but the vertical position as well (261->0). And also that
they are "misaligned" by 10 clocks (which is really more of an
internal CPU IC delay thing, we aren't entirely sure why the
difference is there). You probably shouldn't mess with the code if you
don't understand the implications of this on eg range testing :/
2006-10-20 03:53:34 +00:00
byuu
f24d17859f Update to bsnes v018r01? release.
I've written a new scheduler for bsnes to take 100% full advantage of
cooperative multithreading. Now, bsnes only performs jumps directly
from one thread to another (CPU->SMP instead of CPU->main->SMP), and
even then only when absolutely needed (eg CPU is accessing SMP when
CPU is currently ahead of SMP).
This unfortunately makes bCPU and bSMP no longer compile. However, it
does yield some impressive speed gains. From 109fps to 125fps.
             By comparison, bsnes v0.017 yielded 128fps with my test
ROM.
 The speed gain though is dependant upon how utilized the CPU<>SMP
communication is, the difference in speed between v0.017 and my WIP
can be anywhere between 1% and 10%, with the WIP always being slower.
 The better news is that this is still without IRQs fully optimized. I
don't know how easy it will be to optimize these, if it's even doable
at all... but if I can, that would yield another very important speed
increase, making the next release the fastest ever. Here's to hoping.
 The bad news though is that cothreading's advantages are pretty much
maxed out completely now. Don't expect any future leaps in performance
from this. Still, overall... a 40% total speed increase and double the
processor synchronization precision was definitely worth the effort,
even for the potential loss of savestates.

 The scheduler should also make sPPU much faster when and if that's
ever started upon, but that's still going to take a very significant
speed hit over bPPU.

 One last benefit of the scheduler is that the new synchronization
method isn't limited to only two clocks. I can now easily add another
clock, eg for SFX/SA-1. Not that I'll be emulating either of those
within the next year or two, though. Just saying...

 I might also make two schedulers, one for cothreaded cores and one
for non-cothreaded cores. One thing is for certain though, I won't be
writing schedulers for every combination of cothreaded<>non-cothreaded
cores (there's 4 of them, CPU, SMP, PPU and DSP). And this will also
rule out run-time polymorphism's compile-time option, so expect that
to change to a compile-time only setting, meaning possibly two
versions of bsnes in the future.

 Now then, I also fixed up S-CPU emulation mode opcodes. Direct page
wrapping, stack wrapping with native mode opcodes and processor status
flag fixes. No games use emulation mode, but accuracy is always nice.

[No archive available]
2006-10-18 05:33:00 +00:00
194 changed files with 3436 additions and 19076 deletions

35
license.txt Normal file
View File

@@ -0,0 +1,35 @@
bsnes License:
--------------
You are free to redistribute this software, and its source code; provided
there is no charge for the software, nor any charge for the medium used to
distribute the software. You are also free to use and modify the source code
as you desire for personal use only. No publically-released derivative works
of this 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:
---------------------------------
The Simple DirectMedia Layer (SDL for short) is a cross-platform library
designed to make it easy to write multi-media software, such as games and
emulators.
The Simple DirectMedia Layer library source code is available from:
http://www.libsdl.org/
This library is distributed under the terms of the GNU LGPL:
http://www.gnu.org/copyleft/lesser.html
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, the cooperative multithreading library used by bsnes, 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.

98
readme.txt Normal file
View File

@@ -0,0 +1,98 @@
bsnes
Version 0.019
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 Limitations
-----------------
S-CPU
- Invalid DMA / HDMA transfers (eg WRAM<>WRAM) not fully emulated
- 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
Super Gameboy
Cartridge passthrough used for playing Gameboy games
Unsupported controllers
-----------------------
Mouse
Super Scope
Justifier
Multitap (4-port)
Multitap (5-port)

View File

@@ -1,4 +1,4 @@
#define BSNES_VERSION "0.018" #define BSNES_VERSION "0.019"
#define BSNES_TITLE "bsnes v" BSNES_VERSION #define BSNES_TITLE "bsnes v" BSNES_VERSION
#define MEMCORE bMemBus #define MEMCORE bMemBus
@@ -14,10 +14,10 @@
#define CHEAT_SYSTEM #define CHEAT_SYSTEM
//enable GZ, ZIP format support //enable GZ, ZIP format support
#define GZIP_SUPPORT //#define GZIP_SUPPORT
//enable JMA support //enable JMA support
#define JMA_SUPPORT //#define JMA_SUPPORT
//snes core polymorphism //snes core polymorphism
//(allow runtime cpu/smp/dsp/ppu/bus selection, ~10% speed hit) //(allow runtime cpu/smp/dsp/ppu/bus selection, ~10% speed hit)
@@ -34,6 +34,7 @@
#endif #endif
#include "lib/libbase.h" #include "lib/libbase.h"
#include "lib/libsort.h"
#include "lib/libco_x86.h" #include "lib/libco_x86.h"
#include "lib/libarray.h" #include "lib/libarray.h"
#include "lib/libvector.h" #include "lib/libvector.h"

View File

@@ -1,9 +1,20 @@
#include "../base.h" #include "../base.h"
#include "database.cpp" #include "database.cpp"
#include "cart_file.cpp"
#include "cart_header.cpp"
Cartridge cartridge; Cartridge cartridge;
void Cartridge::read_dbi() { #include "cart_normal.cpp"
#include "cart_st.cpp"
#include "cart_stdual.cpp"
void Cartridge::load_begin(uint cart_type) {
if(loaded() == true)return;
info.type = cart_type;
info.srtc = false; info.srtc = false;
info.sdd1 = false; info.sdd1 = false;
info.c4 = false; info.c4 = false;
@@ -13,372 +24,89 @@ void Cartridge::read_dbi() {
info.dsp1_mapper = 0; info.dsp1_mapper = 0;
info.header_index = 0x7fc0; info.header_index = 0xffc0;
info.mapper = PCB; info.mapper = PCB;
strcpy(info.name, dbi.name); strcpy(info.name, "");
strcpy(info.pcb, dbi.pcb); strcpy(info.pcb, "");
info.region = NTSC; info.region = NTSC;
info.cart_mmio = false; info.cart_mmio = false;
info.rom_size = dbi.rom; info.rom_size = 0;
info.ram_size = dbi.ram; info.ram_size = 0;
}
void Cartridge::read_header() { file.count = 0;
info.srtc = false; for(int i = 0; i < 8; i++) {
info.sdd1 = false; strcpy(file.rom_name[i], "");
info.c4 = false; strcpy(file.ram_name[i], "");
info.dsp1 = false; file.rom_size[i] = 0;
info.dsp2 = false; file.ram_size[i] = 0;
info.obc1 = false; file.rom_data[i] = 0;
file.ram_data[i] = 0;
info.dsp1_mapper = 0;
if(info.header_index == 0x7fc0 && info.rom_size >= 0x401000) {
info.mapper = EXLOROM;
strcpy(info.pcb, "UNL-EXLOROM");
} else if(info.header_index == 0x7fc0 && rom[info.header_index + MAPPER] == 0x32) {
info.mapper = EXLOROM;
strcpy(info.pcb, "UNL-EXLOROM");
} else if(info.header_index == 0x7fc0) {
info.mapper = LOROM;
strcpy(info.pcb, "UNL-LOROM");
} else if(info.header_index == 0xffc0) {
info.mapper = HIROM;
strcpy(info.pcb, "UNL-HIROM");
} else { //info.header_index == 0x40ffc0
info.mapper = EXHIROM;
strcpy(info.pcb, "UNL-EXHIROM");
}
uint8 mapper = rom[info.header_index + MAPPER];
uint8 rom_type = rom[info.header_index + ROM_TYPE];
if(mapper == 0x35 && rom_type == 0x55) {
info.srtc = true;
}
if(mapper == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
info.sdd1 = true;
}
if(mapper == 0x20 && rom_type == 0xf3) {
info.c4 = true;
}
if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) {
info.dsp1 = true;
}
if(mapper == 0x30 && rom_type == 0x05) {
info.dsp1 = true;
}
if(mapper == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) {
info.dsp1 = true;
}
if(info.dsp1 == true) {
if((mapper & 0x2f) == 0x20 && info.rom_size <= 0x100000) {
info.dsp1_mapper = DSP1_LOROM_1MB;
} else if((mapper & 0x2f) == 0x20) {
info.dsp1_mapper = DSP1_LOROM_2MB;
} else if((mapper & 0x2f) == 0x21) {
info.dsp1_mapper = DSP1_HIROM;
}
}
if(mapper == 0x20 && rom_type == 0x05) {
info.dsp2 = true;
}
if(mapper == 0x30 && rom_type == 0x25) {
info.obc1 = true;
}
info.cart_mmio = info.c4 | info.dsp1 | info.dsp2 | info.obc1;
if(rom[info.header_index + SRAM_SIZE] & 7) {
info.ram_size = 1024 << (rom[info.header_index + SRAM_SIZE] & 7);
} else {
info.ram_size = 0;
}
memcpy(&info.name, &rom[info.header_index + CART_NAME], 21);
info.name[21] = 0;
for(int i = 0; i < 22; i++) {
if(info.name[i] & 0x80) {
info.name[i] = '?';
}
} }
} }
void Cartridge::find_header() { void Cartridge::load(const char *rom_fn) {
int32 score_lo = 0, if(!rom_fn || !*rom_fn)return;
score_hi = 0,
score_ex = 0;
if(info.rom_size < 0x010000) { char fn[4096], ram_fn[4096];
//cart too small to be anything but lorom strcpy(fn, rom_fn);
info.header_index = 0x007fc0; //correct folder slashes
return;
}
if((rom[0x7fc0 + MAPPER] & ~0x10) == 0x20)score_lo++;
if((rom[0xffc0 + MAPPER] & ~0x10) == 0x21)score_hi++;
if(rom[0x7fc0 + ROM_TYPE] < 0x08)score_lo++;
if(rom[0xffc0 + ROM_TYPE] < 0x08)score_hi++;
if(rom[0x7fc0 + ROM_SIZE] < 0x10)score_lo++;
if(rom[0xffc0 + ROM_SIZE] < 0x10)score_hi++;
if(rom[0x7fc0 + SRAM_SIZE] < 0x08)score_lo++;
if(rom[0xffc0 + SRAM_SIZE] < 0x08)score_hi++;
if(rom[0x7fc0 + REGION] < 14)score_lo++;
if(rom[0xffc0 + REGION] < 14)score_hi++;
if(rom[0x7fc0 + LICENSE] < 3)score_lo++;
if(rom[0xffc0 + LICENSE] < 3)score_hi++;
if(rom[0x7fc0 + RESH] & 0x80)score_lo += 2;
if(rom[0xffc0 + RESH] & 0x80)score_hi += 2;
uint16 cksum, icksum;
cksum = rom[0x7fc0 + CKSUM] | (rom[0x7fc0 + CKSUM + 1] << 8);
icksum = rom[0x7fc0 + ICKSUM] | (rom[0x7fc0 + ICKSUM + 1] << 8);
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
score_lo += 8;
}
cksum = rom[0xffc0 + CKSUM] | (rom[0xffc0 + CKSUM + 1] << 8);
icksum = rom[0xffc0 + ICKSUM] | (rom[0xffc0 + ICKSUM + 1] << 8);
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
score_hi += 8;
}
if(info.rom_size < 0x401000) {
score_ex = 0;
} else {
if(rom[0x7fc0 + MAPPER] == 0x32)score_lo++;
else score_ex += 16;
}
if(score_lo >= score_hi && score_lo >= score_ex) {
info.header_index = 0x007fc0;
} else if(score_hi >= score_ex) {
info.header_index = 0x00ffc0;
} else {
info.header_index = 0x40ffc0;
}
}
void Cartridge::load_sram() {
if(info.ram_size == 0) {
sram = 0;
return;
}
FileReader ff(sram_fn);
if(!ff.ready()) {
sram = (uint8*)malloc(info.ram_size);
memset(sram, 0xff, info.ram_size);
return;
}
sram = ff.read(info.ram_size);
}
void Cartridge::save_sram() {
if(info.ram_size == 0)return;
FileWriter ff(sram_fn);
if(!ff.ready())return;
ff.write(sram, info.ram_size);
}
void Cartridge::load_rom(Reader &rf) {
uint size = rf.size();
bool header = ((size & 0x7fff) == 512);
info.rom_size = size - (header ? 512 : 0);
if(info.rom_size & 0x7fff) {
info.rom_size += 0x8000 - (info.rom_size & 0x7fff);
}
uint8 *base_rom = rf.read(info.rom_size + (header ? 512 : 0));
if(header) {
memcpy(rom_header, base_rom, 512);
} else {
memset(rom_header, 0x00, 512);
}
rom = (uint8*)malloc(info.rom_size);
memcpy(rom, base_rom + (header ? 512 : 0), info.rom_size);
SafeFree(base_rom);
info.crc32 = 0xffffffff;
for(int32 i = 0; i < info.rom_size; i++) {
info.crc32 = crc32_adjust(info.crc32, rom[i]);
}
info.crc32 = ~info.crc32;
}
void Cartridge::patch_rom(Reader &rf) {
UPS<ramfile, ramfile, ramfile> ups;
uint patchsize = rf.size();
uint8 *patchdata = rf.read();
fopen(ups.original, 0, file::mode_writeread);
fopen(ups.modified, 0, file::mode_writeread);
fopen(ups.patch.fp, 0, file::mode_writeread);
fwrite(ups.original, rom, info.rom_size);
fwrite(ups.patch.fp, patchdata, patchsize);
if(ups.apply() == true) {
info.crc32 = ups.modified_crc32;
info.rom_size = ups.modified_filesize;
rom = (uint8*)realloc(rom, info.rom_size);
fseek(ups.modified, 0, file::seek_start);
fread(ups.modified, rom, info.rom_size);
}
}
bool Cartridge::load(const char *fn) {
if(cart_loaded == true)return false;
if(strlen(fn) < 3)return false;
dprintf("* Loading \"%s\"...", fn);
strcpy(rom_fn, fn);
switch(Reader::detect(rom_fn)) {
case Reader::RF_NORMAL: {
FileReader ff(rom_fn);
if(!ff.ready()) {
alert("Error loading image file (%s)!", rom_fn);
return false;
}
load_rom(ff);
} break;
#ifdef GZIP_SUPPORT
case Reader::RF_GZ: {
GZReader gf(rom_fn);
if(!gf.ready()) {
alert("Error loading image file (%s)!", rom_fn);
return false;
}
load_rom(gf);
} break;
case Reader::RF_ZIP: {
ZipReader zf(rom_fn);
load_rom(zf);
} break;
#endif
#ifdef JMA_SUPPORT
case Reader::RF_JMA: {
try {
JMAReader jf(rom_fn);
load_rom(jf);
} catch(JMA::jma_errors jma_error) {
alert("Error loading image file (%s)!", rom_fn);
return false;
}
} break;
#endif
}
//remove ROM extension
strcpy(sram_fn, fn);
for(int i = strlen(fn) - 1; i >= 0; i--) { for(int i = strlen(fn) - 1; i >= 0; i--) {
if(sram_fn[i] == '.') { if(fn[i] == '\\')fn[i] = '/';
sram_fn[i] = 0; }
uint i = file.count++;
strcpy(file.rom_name[i], fn);
strcpy(fn, rom_fn);
//remove ROM extension
for(int i = strlen(fn) - 1; i >= 0; i--) {
if(fn[i] == '.') {
fn[i] = 0;
break; break;
} }
} }
//add SRAM extension if(i == 0) {
strcat(sram_fn, "."); strcpy(file.patch_name, fn);
strcat(sram_fn, config::fs.save_ext.sget()); strcat(file.patch_name, ".ups");
}
strcpy(fn, strptr(config::file_updatepath(fn, config::path.save)));
if(i == 0) {
strcpy(file.cheat_name, fn);
strcat(file.cheat_name, ".cht");
}
strcpy(file.ram_name[i], fn);
strcat(file.ram_name[i], ".");
strcat(file.ram_name[i], config::path.save_ext);
}
stringarray save_path; bool Cartridge::load_end() {
strcpy(save_path, config::fs.save_path.sget()); for(int i = 0; i < file.count; i++) {
replace(save_path, "\\", "/"); load_file(file.rom_name[i], file.rom_data[i], file.rom_size[i]);
if(strlen(save_path) && !strend(save_path, "/")) { strcat(save_path, "/"); }
if(strlen(save_path) != 0) {
//override default path (current directory)
stringarray new_fn, parts;
strcpy(new_fn, sram_fn);
replace(new_fn, "\\", "/");
split(parts, "/", new_fn);
//add new SRAM path
strcpy(new_fn, save_path);
//append fs.base_path if fs.sram_path is not fully-qualified path
if(strbegin(new_fn, "./") == true) {
strltrim(new_fn, "./");
strcpy(new_fn[1], new_fn[0]);
strcpy(new_fn[0], config::fs.base_path.sget());
strcat(new_fn[0], new_fn[1]);
}
//finally, append SRAM file name
strcat(new_fn, parts[count(parts) - 1]);
strcpy(sram_fn, strptr(new_fn));
} }
//load cheat file if it exists if(fexists(file.cheat_name) == true) {
strcpy(cheat_fn, sram_fn); cheat.clear();
strrtrim(cheat_fn, config::fs.save_ext.sget()); cheat.load(file.cheat_name);
strrtrim(cheat_fn, ".");
strcat(cheat_fn, ".cht");
if(fexists(cheat_fn) == true) {
FileReader ff(cheat_fn);
cheat.load(ff);
} }
//load patch file if it exists switch(info.type) {
strcpy(patch_fn, sram_fn); case CART_NORMAL: {
strrtrim(patch_fn, config::fs.save_ext.sget()); load_rom_normal();
strrtrim(patch_fn, "."); load_ram_normal();
strcat(patch_fn, ".ups"); } break;
case CART_ST: {
if(fexists(patch_fn) == true) { load_rom_st();
FileReader ff(patch_fn); load_ram_st();
patch_rom(ff); } break;
case CART_STDUAL: {
load_rom_stdual();
load_ram_stdual();
} break;
} }
#ifdef GZIP_SUPPORT
else {
strrtrim(patch_fn, ".ups");
strcat(patch_fn, ".upz");
if(fexists(patch_fn) == true) {
ZipReader zf(patch_fn);
patch_rom(zf);
}
}
#endif
if(read_database() == true) {
read_dbi();
} else {
find_header();
read_header();
}
load_sram();
cart_loaded = true; cart_loaded = true;
r_mem->load_cart(); r_mem->load_cart();
return true; return true;
} }
@@ -388,13 +116,23 @@ bool Cartridge::unload() {
r_mem->unload_cart(); r_mem->unload_cart();
if(sram) { save_sram(); } switch(info.type) {
SafeFree(rom); case CART_NORMAL: {
SafeFree(sram); save_ram_normal();
} break;
case CART_ST: {
save_ram_st();
} break;
case CART_STDUAL: {
save_ram_stdual();
} break;
}
if(cheat.count() > 0 || fexists(cheat_fn)) { SafeFree(rom);
FileWriter ff(cheat_fn); SafeFree(ram);
cheat.save(ff);
if(cheat.count() > 0 || fexists(file.cheat_name) == true) {
cheat.save(file.cheat_name);
cheat.clear(); cheat.clear();
} }
@@ -407,8 +145,8 @@ Cartridge::Cartridge() {
cart_loaded = false; cart_loaded = false;
rom = 0; rom = 0;
sram = 0; ram = 0;
} }
Cartridge::~Cartridge() { Cartridge::~Cartridge() {

View File

@@ -15,10 +15,15 @@ db_item dbi;
// //
bool cart_loaded; enum {
char rom_fn[4096], sram_fn[4096], cheat_fn[4096], patch_fn[4096]; CART_NORMAL,
CART_ST,
CART_STDUAL,
};
uint8 rom_header[512], *rom, *sram; bool cart_loaded;
uint8 rom_header[512], *rom, *ram;
enum { enum {
//header fields //header fields
@@ -26,7 +31,7 @@ enum {
MAPPER = 0x15, MAPPER = 0x15,
ROM_TYPE = 0x16, ROM_TYPE = 0x16,
ROM_SIZE = 0x17, ROM_SIZE = 0x17,
SRAM_SIZE = 0x18, RAM_SIZE = 0x18,
REGION = 0x19, REGION = 0x19,
LICENSE = 0x1a, LICENSE = 0x1a,
VERSION = 0x1b, VERSION = 0x1b,
@@ -53,6 +58,17 @@ enum {
}; };
struct { struct {
uint count;
char cheat_name[4096], patch_name[4096];
char rom_name[8][4096], ram_name[8][4096];
uint rom_size[8], ram_size[8];
uint8 *rom_data[8], *ram_data[8];
} file;
struct {
uint type;
//cart information
uint32 crc32; uint32 crc32;
char name[128]; char name[128];
char pcb[32]; char pcb[32];
@@ -78,15 +94,28 @@ struct {
uint header_index; uint header_index;
} info; } info;
void load_rom(Reader &rf); bool load_file(const char *fn, uint8 *&data, uint &size);
void patch_rom(Reader &rf); bool save_file(const char *fn, uint8 *data, uint size);
void load_sram();
void save_sram(); void load_rom_normal();
void read_dbi(); void load_ram_normal();
void save_ram_normal();
void load_rom_st();
void load_ram_st();
void save_ram_st();
void load_rom_stdual();
void load_ram_stdual();
void save_ram_stdual();
void find_header(); void find_header();
void read_header(); void read_header();
bool loaded() { return cart_loaded; } bool loaded() { return cart_loaded; }
bool load(const char *fn); void load_begin(uint cart_type);
void load(const char *rom_fn);
bool load_end();
bool unload(); bool unload();
Cartridge(); Cartridge();

61
src/cart/cart_file.cpp Normal file
View File

@@ -0,0 +1,61 @@
bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size) {
dprintf("* Loading \"%s\"...", fn);
if(fexists(fn) == false) {
return false;
}
switch(Reader::detect(fn)) {
case Reader::RF_NORMAL: {
FileReader ff(fn);
if(!ff.ready()) {
alert("Error loading image file (%s)!", fn);
return false;
}
size = ff.size();
data = ff.read();
} break;
#ifdef GZIP_SUPPORT
case Reader::RF_GZ: {
GZReader gf(fn);
if(!gf.ready()) {
alert("Error loading image file (%s)!", fn);
return false;
}
size = gf.size();
data = gf.read();
} break;
case Reader::RF_ZIP: {
ZipReader zf(fn);
size = zf.size();
data = zf.read();
} break;
#endif
#ifdef JMA_SUPPORT
case Reader::RF_JMA: {
try {
JMAReader jf(fn);
size = jf.size();
data = jf.read();
} catch(JMA::jma_errors jma_error) {
alert("Error loading image file (%s)!", fn);
return false;
}
} break;
#endif
}
return true;
}
bool Cartridge::save_file(const char *fn, uint8 *data, uint size) {
FileWriter ff(fn);
if(!ff.ready())return false;
ff.write(data, size);
return true;
}

149
src/cart/cart_header.cpp Normal file
View File

@@ -0,0 +1,149 @@
void Cartridge::read_header() {
info.srtc = false;
info.sdd1 = false;
info.c4 = false;
info.dsp1 = false;
info.dsp2 = false;
info.obc1 = false;
info.dsp1_mapper = 0;
if(info.header_index == 0x7fc0 && info.rom_size >= 0x401000) {
info.mapper = EXLOROM;
strcpy(info.pcb, "UNL-EXLOROM");
} else if(info.header_index == 0x7fc0 && rom[info.header_index + MAPPER] == 0x32) {
info.mapper = EXLOROM;
strcpy(info.pcb, "UNL-EXLOROM");
} else if(info.header_index == 0x7fc0) {
info.mapper = LOROM;
strcpy(info.pcb, "UNL-LOROM");
} else if(info.header_index == 0xffc0) {
info.mapper = HIROM;
strcpy(info.pcb, "UNL-HIROM");
} else { //info.header_index == 0x40ffc0
info.mapper = EXHIROM;
strcpy(info.pcb, "UNL-EXHIROM");
}
uint8 mapper = rom[info.header_index + MAPPER];
uint8 rom_type = rom[info.header_index + ROM_TYPE];
if(mapper == 0x35 && rom_type == 0x55) {
info.srtc = true;
}
if(mapper == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
info.sdd1 = true;
}
if(mapper == 0x20 && rom_type == 0xf3) {
info.c4 = true;
}
if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) {
info.dsp1 = true;
}
if(mapper == 0x30 && rom_type == 0x05) {
info.dsp1 = true;
}
if(mapper == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) {
info.dsp1 = true;
}
if(info.dsp1 == true) {
if((mapper & 0x2f) == 0x20 && info.rom_size <= 0x100000) {
info.dsp1_mapper = DSP1_LOROM_1MB;
} else if((mapper & 0x2f) == 0x20) {
info.dsp1_mapper = DSP1_LOROM_2MB;
} else if((mapper & 0x2f) == 0x21) {
info.dsp1_mapper = DSP1_HIROM;
}
}
if(mapper == 0x20 && rom_type == 0x05) {
info.dsp2 = true;
}
if(mapper == 0x30 && rom_type == 0x25) {
info.obc1 = true;
}
info.cart_mmio = info.c4 | info.dsp1 | info.dsp2 | info.obc1;
if(rom[info.header_index + RAM_SIZE] & 7) {
info.ram_size = 1024 << (rom[info.header_index + RAM_SIZE] & 7);
} else {
info.ram_size = 0;
}
memcpy(&info.name, &rom[info.header_index + CART_NAME], 21);
info.name[21] = 0;
for(int i = 0; i < 22; i++) {
if(info.name[i] & 0x80) {
info.name[i] = '?';
}
}
}
void Cartridge::find_header() {
int32 score_lo = 0,
score_hi = 0,
score_ex = 0;
if(info.rom_size < 0x010000) {
//cart too small to be anything but lorom
info.header_index = 0x007fc0;
return;
}
if((rom[0x7fc0 + MAPPER] & ~0x10) == 0x20)score_lo++;
if((rom[0xffc0 + MAPPER] & ~0x10) == 0x21)score_hi++;
if(rom[0x7fc0 + ROM_TYPE] < 0x08)score_lo++;
if(rom[0xffc0 + ROM_TYPE] < 0x08)score_hi++;
if(rom[0x7fc0 + ROM_SIZE] < 0x10)score_lo++;
if(rom[0xffc0 + ROM_SIZE] < 0x10)score_hi++;
if(rom[0x7fc0 + RAM_SIZE] < 0x08)score_lo++;
if(rom[0xffc0 + RAM_SIZE] < 0x08)score_hi++;
if(rom[0x7fc0 + REGION] < 14)score_lo++;
if(rom[0xffc0 + REGION] < 14)score_hi++;
if(rom[0x7fc0 + LICENSE] < 3)score_lo++;
if(rom[0xffc0 + LICENSE] < 3)score_hi++;
if(rom[0x7fc0 + RESH] & 0x80)score_lo += 2;
if(rom[0xffc0 + RESH] & 0x80)score_hi += 2;
uint16 cksum, icksum;
cksum = rom[0x7fc0 + CKSUM] | (rom[0x7fc0 + CKSUM + 1] << 8);
icksum = rom[0x7fc0 + ICKSUM] | (rom[0x7fc0 + ICKSUM + 1] << 8);
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
score_lo += 8;
}
cksum = rom[0xffc0 + CKSUM] | (rom[0xffc0 + CKSUM + 1] << 8);
icksum = rom[0xffc0 + ICKSUM] | (rom[0xffc0 + ICKSUM + 1] << 8);
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
score_hi += 8;
}
if(info.rom_size < 0x401000) {
score_ex = 0;
} else {
if(rom[0x7fc0 + MAPPER] == 0x32)score_lo++;
else score_ex += 16;
}
if(score_lo >= score_hi && score_lo >= score_ex) {
info.header_index = 0x007fc0;
} else if(score_hi >= score_ex) {
info.header_index = 0x00ffc0;
} else {
info.header_index = 0x40ffc0;
}
}

66
src/cart/cart_normal.cpp Normal file
View File

@@ -0,0 +1,66 @@
void Cartridge::load_rom_normal() {
uint size = 0;
for(int i = 0; i < file.count; i++) {
size += file.rom_size[i] - (((file.rom_size[i] & 0x7fff) == 512) ? 512 : 0);
}
info.rom_size = size;
rom = (uint8*)malloc(info.rom_size);
memset(rom, 0, info.rom_size);
uint offset = 0;
for(int i = 0; i < file.count; i++) {
uint8 *data = file.rom_data[i] + (((file.rom_size[i] & 0x7fff) == 512) ? 512 : 0);
uint size = file.rom_size[i] - (((file.rom_size[i] & 0x7fff) == 512) ? 512 : 0);
memcpy(rom + offset, data, size);
offset += size;
safe_free(file.rom_data[i]);
}
info.crc32 = crc32_calculate(rom, info.rom_size);
if(read_database() == true) {
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 = 0xffc0;
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;
} else {
find_header();
read_header();
}
}
void Cartridge::load_ram_normal() {
if(info.ram_size == 0) {
ram = 0;
return;
}
ram = (uint8*)malloc(info.ram_size);
memset(ram, 0xff, info.ram_size);
if(load_file(file.ram_name[0], file.ram_data[0], file.ram_size[0]) == true) {
memcpy(ram, file.ram_data[0], min(info.ram_size, file.ram_size[0]));
safe_free(file.ram_data[0]);
}
}
void Cartridge::save_ram_normal() {
if(info.ram_size == 0)return;
save_file(file.ram_name[0], ram, info.ram_size);
}

45
src/cart/cart_st.cpp Normal file
View File

@@ -0,0 +1,45 @@
void Cartridge::load_rom_st() {
uint8 *data;
uint size;
string bios = config::file_updatepath("stbios.bin", config::path.bios);
info.rom_size = 0x200000;
rom = (uint8*)malloc(info.rom_size);
memset(rom, 0, info.rom_size);
load_file(strptr(bios), data, size);
memcpy(rom, data, min(size, 0x040000));
safe_free(data);
memcpy(rom + 0x100000, file.rom_data[0], min(file.rom_size[0], 0x100000));
safe_free(file.rom_data[0]);
//
strcpy(info.name, "???");
strcpy(info.pcb, "STC-SOLO");
info.mapper = PCB;
info.region = NTSC;
info.rom_size = 0x200000;
info.ram_size = 0x020000;
//
info.crc32 = crc32_calculate(rom + 0x100000, file.rom_size[0]);
if(read_database() == true) {
strcpy(info.name, dbi.name);
}
}
void Cartridge::load_ram_st() {
ram = (uint8*)malloc(info.ram_size);
memset(ram, 0xff, info.ram_size);
if(load_file(file.ram_name[0], file.ram_data[0], file.ram_size[0]) == true) {
memcpy(ram, file.ram_data[0], min(file.ram_size[0], 0x020000));
safe_free(file.ram_data[0]);
}
}
void Cartridge::save_ram_st() {
save_file(file.ram_name[0], ram, 0x020000);
}

66
src/cart/cart_stdual.cpp Normal file
View File

@@ -0,0 +1,66 @@
void Cartridge::load_rom_stdual() {
uint8 *data;
uint size;
string bios = config::file_updatepath("stbios.bin", config::path.bios);
info.rom_size = 0x300000;
rom = (uint8*)malloc(info.rom_size);
memset(rom, 0, info.rom_size);
load_file(strptr(bios), data, size);
memcpy(rom, data, min(size, 0x040000));
safe_free(data);
memcpy(rom + 0x100000, file.rom_data[0], min(file.rom_size[0], 0x100000));
safe_free(file.rom_data[0]);
memcpy(rom + 0x200000, file.rom_data[1], min(file.rom_size[1], 0x100000));
safe_free(file.rom_data[1]);
char name_a[4096], name_b[4096];
strcpy(name_a, "???");
strcpy(name_b, "???");
//
info.mapper = PCB;
info.region = NTSC;
info.rom_size = 0x300000;
info.ram_size = 0x040000;
//
info.crc32 = crc32_calculate(rom + 0x100000, file.rom_size[0]);
if(read_database() == true) {
strcpy(name_a, dbi.name);
}
info.crc32 = crc32_calculate(rom + 0x200000, file.rom_size[1]);
if(read_database() == true) {
strcpy(name_b, dbi.name);
}
//
info.crc32 = 0;
strcpy(info.name, name_a);
strcat(info.name, " + ");
strcat(info.name, name_b);
strcpy(info.pcb, "STC-DUAL");
}
void Cartridge::load_ram_stdual() {
ram = (uint8*)malloc(info.ram_size);
memset(ram, 0xff, info.ram_size);
if(load_file(file.ram_name[0], file.ram_data[0], file.ram_size[0]) == true) {
memcpy(ram + 0x000000, file.ram_data[0], min(file.ram_size[0], 0x020000));
safe_free(file.ram_data[0]);
}
if(load_file(file.ram_name[1], file.ram_data[1], file.ram_size[1]) == true) {
memcpy(ram + 0x020000, file.ram_data[1], min(file.ram_size[1], 0x020000));
safe_free(file.ram_data[1]);
}
}
void Cartridge::save_ram_stdual() {
save_file(file.ram_name[0], ram + 0x000000, 0x020000);
save_file(file.ram_name[1], ram + 0x020000, 0x020000);
}

Binary file not shown.

View File

@@ -1,32 +1,98 @@
[0xbb5c4238]
name = "Bishoujo Senshi Sailor Moon Sailor Stars - Fuwa Fuwa Panic 2 (Japan)"
pcb = "STC-????"
rom = 8mbit
ram = 32kbit
[0x8eb753f3]
name = "Crayon Shin-chan - Nagagutsu Dobon!! (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x7aedd703] [0x7aedd703]
name = "Der Langrisser (Japan) [!]" name = "Der Langrisser (Japan) [!]"
pcb = "SHVC-1A3M-30" pcb = "SHVC-1A3M-30"
rom = 16mbit rom = 16mbit
ram = 64kbit ram = 64kbit
[0x35f9eecc]
name = "Der Langrisser (Japan) (V1.1)"
pcb = "SHVC-1A3M-30" ;unverified (guess)
rom = 16mbit
ram = 64kbit
[0x19bdcb19] [0x19bdcb19]
name = "Derby Stallion '96 (Japan) [!]" name = "Derby Stallion '96 (Japan) [!]"
pcb = "BSC-1A5M-01" pcb = "BSC-1A5M-01"
rom = 24mbit rom = 24mbit
ram = 256kbit ram = 256kbit
[0x4296500d]
name = "Gegege no Kitarou - Youkai Donjara (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 16kbit
[0x14c66fca]
name = "Gekisou Sentai Car Rangers (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x32b2b3dd]
name = "Poi Poi Ninja World (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x9684526d] [0x9684526d]
name = "Romancing SaGa (Japan) (V1.1) [!]" name = "Romancing SaGa (Japan) (V1.1) [!]"
pcb = "SHVC-1A3B-12" pcb = "SHVC-1A3B-12"
rom = 8mbit rom = 8mbit
ram = 64kbit ram = 64kbit
[0x675b6382] [0xafd74dcb]
name = "RPG Tsukuru 2 (Japan)" name = "SD Gundam Generation A - Ichinen Sensouki (Japan)"
pcb = "BSC-1A7M-01" ;unverified pcb = "STC-????"
rom = 16mbit rom = 4mbit
ram = 512kbit ram = 8kbit
[0x48ecae44]
name = "SD Gundam Generation B - Grips Senki (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x72b4235f]
name = "SD Gundam Generation C - Axis Senki (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x792d884c]
name = "SD Gundam Generation D - Babylonia Kenkoku Senki (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0xefd3a865]
name = "SD Gundam Generation E - Zanskar Senki (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0xc5dfa8fd]
name = "SD Gundam Generation F - Colony Kakutouki (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x43ad5a45]
name = "SD Ultra Battle - Seven Densetsu (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0x04939d14]
name = "SD Ultra Battle - Ultra Densetsu (Japan)"
pcb = "STC-????"
rom = 4mbit
ram = 8kbit
[0xa5c0045e] [0xa5c0045e]
name = "Secret of Evermore (USA) [!]" name = "Secret of Evermore (USA) [!]"

View File

@@ -8,7 +8,7 @@
FILE *fp; FILE *fp;
uint decode_size(substring &str) { uint decode_size(string &str) {
//hex encoding //hex encoding
if(strbegin(str, "0x")) { if(strbegin(str, "0x")) {
strltrim(str, "0x"); strltrim(str, "0x");
@@ -31,8 +31,8 @@ uint decode_size(substring &str) {
return strdec(str); return strdec(str);
} }
void build_block(substring &block) { void build_block(string &block) {
string line, hashpart, part; stringarray line, hashpart, part;
split(line, "\n", block); split(line, "\n", block);
if(strbegin(line[0], "[") == false) { if(strbegin(line[0], "[") == false) {
@@ -58,26 +58,26 @@ db_item dbi;
strset(line[i], pos, 0); strset(line[i], pos, 0);
} }
if(strmatch(line[i], ""))continue; if(line[i] == "")continue;
split(part, "=", line[i]); split(part, "=", line[i]);
strunquote(part[1]); strunquote(part[1]);
if(strmatch(part[0], "name")) { if(part[0] == "name") {
strncpy(dbi.name, strptr(part[1]), 128); strncpy(dbi.name, strptr(part[1]), 128);
dbi.name[128] = 0; dbi.name[128] = 0;
} }
if(strmatch(part[0], "pcb")) { if(part[0] == "pcb") {
strncpy(dbi.pcb, strptr(part[1]), 32); strncpy(dbi.pcb, strptr(part[1]), 32);
dbi.pcb[31] = 0; dbi.pcb[31] = 0;
} }
if(strmatch(part[0], "rom")) { if(part[0] == "rom") {
dbi.rom = decode_size(part[1]); dbi.rom = decode_size(part[1]);
} }
if(strmatch(part[0], "ram")) { if(part[0] == "ram") {
dbi.ram = decode_size(part[1]); dbi.ram = decode_size(part[1]);
} }
} }
@@ -89,7 +89,7 @@ db_item dbi;
} }
void build_database() { void build_database() {
string data, block; stringarray data, block;
if(strfread(data, "cartdb.txt") == false)return; if(strfread(data, "cartdb.txt") == false)return;
fp = fopen("cart.db", "wb"); fp = fopen("cart.db", "wb");

View File

@@ -268,7 +268,8 @@ void Cheat::disable(uint32 n) {
* cheat file manipulation routines * cheat file manipulation routines
*****/ *****/
bool Cheat::load(Reader &rf) { bool Cheat::load(const char *fn) {
FileReader rf(fn);
if(!rf.ready())return false; if(!rf.ready())return false;
uint8 *raw_data = rf.read(); uint8 *raw_data = rf.read();
@@ -299,7 +300,8 @@ stringarray data, line;
return true; return true;
} }
bool Cheat::save(Writer &wf) { bool Cheat::save(const char *fn) {
FileWriter wf(fn);
if(!wf.ready())return false; if(!wf.ready())return false;
string data; string data;

View File

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

View File

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

View File

@@ -2,24 +2,52 @@ Config config_file;
namespace config { namespace config {
Setting FS::base_path(0, "fs.base_path", string file_updatepath(const char *req_file, const char *req_path) {
"Directory that bsnes resides in", ""); string file(req_file);
Setting FS::rom_path(&config_file, "fs.rom_path", replace(file, "\\", "/");
"Default path to look for ROM files in (\"\" = use default directory)", ""); if(!req_path || strlen(req_path) == 0) { return file; }
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", string path(req_path);
replace(path, "\\", "/");
if(!strend(path, "/")) { strcat(path, "/"); }
if(strbegin(path, "./")) {
strltrim(path, "./");
string temp;
strcpy(temp, config::path.base);
strcat(temp, path);
strcpy(path, temp);
}
stringarray part;
split(part, "/", file);
strcat(path, part[count(part) - 1]);
return path;
}
Setting Path::base(0, "fs.base_path",
"Path that bsnes resides in", "");
Setting Path::rom(&config_file, "path.rom",
"Default path to look for ROM files in (\"\" = use default directory)", "");
Setting Path::save(&config_file, "path.save",
"Default path for all save RAM and cheat files (\"\" = use current directory)", "");
Setting Path::bios(&config_file, "path.bios",
"Path where BIOS file(s) are located\n"
"Supported BIOS files:\n"
"stbios.bin - Bandai Sufami Turbo"
"", "./bios");
Setting Path::save_ext(&config_file, "path.save_ext",
"Extension to be used for all save RAM files", "srm"); "Extension to be used for all save RAM files", "srm");
Setting 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); "Use precalculated TV-style gamma ramp", true, Setting::BOOL);
Setting SNES::sepia(&config_file, "snes.colorfilter.sepia", Setting SNES::sepia(&config_file, "snes.colorfilter.sepia",
"Convert color to sepia tone", false, Setting::TRUE_FALSE); "Convert color to sepia tone", false, Setting::BOOL);
Setting SNES::grayscale(&config_file, "snes.colorfilter.grayscale", Setting SNES::grayscale(&config_file, "snes.colorfilter.grayscale",
"Convert color to grayscale tone", false, Setting::TRUE_FALSE); "Convert color to grayscale tone", false, Setting::BOOL);
Setting SNES::invert(&config_file, "snes.colorfilter.invert", Setting SNES::invert(&config_file, "snes.colorfilter.invert",
"Invert output image colors", false, Setting::TRUE_FALSE); "Invert output image colors", false, Setting::BOOL);
Setting SNES::contrast(&config_file, "snes.colorfilter.contrast", Setting SNES::contrast(&config_file, "snes.colorfilter.contrast",
"Contrast", 0, Setting::DEC); "Contrast", 0, Setting::DEC);
Setting SNES::brightness(&config_file, "snes.colorfilter.brightness", Setting SNES::brightness(&config_file, "snes.colorfilter.brightness",
@@ -30,10 +58,10 @@ Setting SNES::gamma(&config_file, "snes.colorfilter.gamma",
Setting SNES::ntsc_merge_fields(&config_file, "snes.ntsc_merge_fields", Setting SNES::ntsc_merge_fields(&config_file, "snes.ntsc_merge_fields",
"Merge fields in NTSC video filter\n" "Merge fields in NTSC video filter\n"
"Set to true if using filter at any refresh rate other than 60hz\n" "Set to true if using filter at any refresh rate other than 60hz\n"
"", true, Setting::TRUE_FALSE); "", true, Setting::BOOL);
Setting SNES::mute(&config_file, "snes.mute", "Mutes SNES audio output when enabled", Setting SNES::mute(&config_file, "snes.mute", "Mutes SNES audio output when enabled",
false, Setting::TRUE_FALSE); false, Setting::BOOL);
Setting SNES::controller_port0(&config_file, "snes.controller_port_1", Setting SNES::controller_port0(&config_file, "snes.controller_port_1",
"Controller attached to SNES port 1", ::SNES::DEVICEID_JOYPAD1, Setting::DEC); "Controller attached to SNES port 1", ::SNES::DEVICEID_JOYPAD1, Setting::DEC);
@@ -43,31 +71,37 @@ Setting SNES::controller_port1(&config_file, "snes.controller_port_2",
Setting CPU::ntsc_clock_rate(&config_file, "cpu.ntsc_clock_rate", Setting CPU::ntsc_clock_rate(&config_file, "cpu.ntsc_clock_rate",
"NTSC S-CPU clock rate (in hz)", 21477272, Setting::DEC); "NTSC S-CPU clock rate (in hz)", 21477272, Setting::DEC);
Setting CPU::pal_clock_rate(&config_file, "cpu.pal_clock_rate", Setting CPU::pal_clock_rate(&config_file, "cpu.pal_clock_rate",
"PAL S-CPU clock rate (in hz)", 21241370, Setting::DEC); "PAL S-CPU clock rate (in hz)", 21281370, Setting::DEC);
Setting CPU::hdma_enable(0, "cpu.hdma_enable", Setting CPU::hdma_enable(0, "cpu.hdma_enable",
"Enable HDMA effects", true, Setting::TRUE_FALSE); "Enable HDMA effects", true, Setting::BOOL);
Setting SMP::ntsc_clock_rate(&config_file, "smp.ntsc_clock_rate", Setting SMP::ntsc_clock_rate(&config_file, "smp.ntsc_clock_rate",
"NTSC S-SMP clock rate (in hz)", 24576000, Setting::DEC); "NTSC S-SMP clock rate (in hz)", 24606720, Setting::DEC);
Setting SMP::pal_clock_rate(&config_file, "smp.pal_clock_rate", Setting SMP::pal_clock_rate(&config_file, "smp.pal_clock_rate",
"PAL S-SMP clock rate (in hz)", 24576000, Setting::DEC); "PAL S-SMP clock rate (in hz)", 24606720, Setting::DEC);
Setting PPU::render_scanline_position(&config_file, "ppu.render_scanline_position", Setting PPU::Hack::render_scanline_position(&config_file, "ppu.hack.render_scanline_position",
"Approximate HCLOCK position to render at for scanline-based renderers", "Approximate HCLOCK position to render at for scanline-based renderers",
256, Setting::DEC); 512, Setting::DEC);
Setting PPU::opt_enable(0, "ppu.opt_enable", "Enable offset-per-tile effects", true, Setting::TRUE_FALSE); Setting PPU::Hack::obj_cache(&config_file, "ppu.hack.obj_cache",
"Cache OAM OBJ attributes one scanline before rendering\n"
"This is technically closer to the actual operation of the SNES,\n"
"but can cause problems in many games if enabled",
false, Setting::BOOL);
Setting PPU::bg1_pri0_enable(0, "ppu.bg1_pri0_enable", "Enable BG1 Priority 0", true, Setting::TRUE_FALSE); Setting PPU::opt_enable(0, "ppu.opt_enable", "Enable offset-per-tile effects", true, Setting::BOOL);
Setting PPU::bg1_pri1_enable(0, "ppu.bg1_pri1_enable", "Enable BG1 Priority 1", true, Setting::TRUE_FALSE); Setting PPU::bg1_pri0_enable(0, "ppu.bg1_pri0_enable", "Enable BG1 Priority 0", true, Setting::BOOL);
Setting PPU::bg2_pri0_enable(0, "ppu.bg2_pri0_enable", "Enable BG2 Priority 0", true, Setting::TRUE_FALSE); Setting PPU::bg1_pri1_enable(0, "ppu.bg1_pri1_enable", "Enable BG1 Priority 1", true, Setting::BOOL);
Setting PPU::bg2_pri1_enable(0, "ppu.bg2_pri1_enable", "Enable BG2 Priority 1", true, Setting::TRUE_FALSE); Setting PPU::bg2_pri0_enable(0, "ppu.bg2_pri0_enable", "Enable BG2 Priority 0", true, Setting::BOOL);
Setting PPU::bg3_pri0_enable(0, "ppu.bg3_pri0_enable", "Enable BG3 Priority 0", true, Setting::TRUE_FALSE); Setting PPU::bg2_pri1_enable(0, "ppu.bg2_pri1_enable", "Enable BG2 Priority 1", true, Setting::BOOL);
Setting PPU::bg3_pri1_enable(0, "ppu.bg3_pri1_enable", "Enable BG3 Priority 1", true, Setting::TRUE_FALSE); Setting PPU::bg3_pri0_enable(0, "ppu.bg3_pri0_enable", "Enable BG3 Priority 0", true, Setting::BOOL);
Setting PPU::bg4_pri0_enable(0, "ppu.bg4_pri0_enable", "Enable BG4 Priority 0", true, Setting::TRUE_FALSE); Setting PPU::bg3_pri1_enable(0, "ppu.bg3_pri1_enable", "Enable BG3 Priority 1", true, Setting::BOOL);
Setting PPU::bg4_pri1_enable(0, "ppu.bg4_pri1_enable", "Enable BG4 Priority 1", true, Setting::TRUE_FALSE); Setting PPU::bg4_pri0_enable(0, "ppu.bg4_pri0_enable", "Enable BG4 Priority 0", true, Setting::BOOL);
Setting PPU::oam_pri0_enable(0, "ppu.oam_pri0_enable", "Enable OAM Priority 0", true, Setting::TRUE_FALSE); Setting PPU::bg4_pri1_enable(0, "ppu.bg4_pri1_enable", "Enable BG4 Priority 1", true, Setting::BOOL);
Setting PPU::oam_pri1_enable(0, "ppu.oam_pri1_enable", "Enable OAM Priority 1", true, Setting::TRUE_FALSE); Setting PPU::oam_pri0_enable(0, "ppu.oam_pri0_enable", "Enable OAM Priority 0", true, Setting::BOOL);
Setting PPU::oam_pri2_enable(0, "ppu.oam_pri2_enable", "Enable OAM Priority 2", true, Setting::TRUE_FALSE); Setting PPU::oam_pri1_enable(0, "ppu.oam_pri1_enable", "Enable OAM Priority 1", true, Setting::BOOL);
Setting PPU::oam_pri3_enable(0, "ppu.oam_pri3_enable", "Enable OAM Priority 3", true, Setting::TRUE_FALSE); Setting PPU::oam_pri2_enable(0, "ppu.oam_pri2_enable", "Enable OAM Priority 2", true, Setting::BOOL);
Setting PPU::oam_pri3_enable(0, "ppu.oam_pri3_enable", "Enable OAM Priority 3", true, Setting::BOOL);
}; };

View File

@@ -2,10 +2,12 @@ extern Config config_file;
namespace config { namespace config {
extern struct FS { string file_updatepath(const char *, const char *);
static Setting base_path, rom_path, save_path;
extern struct Path {
static Setting base, rom, save, bios;
static Setting save_ext; static Setting save_ext;
} fs; } path;
extern struct SNES { extern struct SNES {
static Setting gamma_ramp, sepia, grayscale, invert, contrast, brightness, gamma; static Setting gamma_ramp, sepia, grayscale, invert, contrast, brightness, gamma;
@@ -25,9 +27,12 @@ extern struct SMP {
} smp; } smp;
extern struct PPU { extern struct PPU {
static Setting render_scanline_position; struct Hack {
static Setting opt_enable; static Setting render_scanline_position;
static Setting obj_cache;
} hack;
static Setting opt_enable;
static Setting bg1_pri0_enable, bg1_pri1_enable; static Setting bg1_pri0_enable, bg1_pri1_enable;
static Setting bg2_pri0_enable, bg2_pri1_enable; static Setting bg2_pri0_enable, bg2_pri1_enable;
static Setting bg3_pri0_enable, bg3_pri1_enable; static Setting bg3_pri0_enable, bg3_pri1_enable;

View File

@@ -1,97 +0,0 @@
#include "../../base.h"
#include "core/core.cpp"
#include "memory/memory.cpp"
#include "dma/dma.cpp"
#include "timing/timing.cpp"
#include "bcpu_exec.cpp"
#include "bcpu_mmio.cpp"
#include "bcpu_int.cpp"
uint8 bCPU::pio_status() { return status.pio; }
void bCPU::run() {
if(run_state.hdma) {
exec_hdma();
return;
}
if(run_state.dma) {
exec_dma();
return;
}
if(status.cycle_pos == 0) { //interrupts only trigger on opcode edges
if(run_state.irq && !run_state.stp) {
run_state.irq = false;
if(time.nmi_pending == true) {
time.nmi_pending = false;
aa.w = (regs.e == false) ? 0xffea : 0xfffa;
} else if(time.irq_pending == true) {
time.irq_pending = false;
aa.w = (regs.e == false) ? 0xffee : 0xfffe;
}
irq_run();
}
}
exec_cycle();
}
void bCPU::power() {
region = snes->region();
regs.a = regs.x = regs.y = 0x0000;
regs.s = 0x01ff;
reset();
}
void bCPU::reset() {
//reset vector location
regs.pc.d = 0;
regs.pc.l = r_mem->read(0xfffc);
regs.pc.h = r_mem->read(0xfffd);
//registers are not fully reset by SNES
regs.x.h = 0x00;
regs.y.h = 0x00;
regs.s.h = 0x01;
regs.d = 0x0000;
regs.db = 0x00;
regs.p = 0x34;
regs.e = 1;
regs.mdr = 0x00;
time_reset();
mmio_reset();
dma_reset();
run_state.hdma = false;
run_state.dma = false;
run_state.irq = false;
run_state.wai = false;
run_state.stp = false;
status.cycle_pos = 0;
status.cycle_count = 0;
status.cycles_executed = 0;
apu_port[0] = 0x00;
apu_port[1] = 0x00;
apu_port[2] = 0x00;
apu_port[3] = 0x00;
frame();
//initial latch values for $213c/$213d
//[x]0035 : [y]0000 (53.0 -> 212) [lda $2137]
//[x]0038 : [y]0000 (56.5 -> 226) [nop : lda $2137]
add_cycles(186);
}
bCPU::bCPU() {
init_op_tables();
}
bCPU::~bCPU() {}

View File

@@ -1,165 +0,0 @@
class bCPU : public CPU {
public:
#include "core/core.h"
#include "memory/memory.h"
#include "dma/dma.h"
#include "timing/timing.h"
enum { NTSC = 0, PAL = 1 };
uint8 region;
enum {
DMASTATE_DMASYNC,
DMASTATE_DMASYNC2,
DMASTATE_DMASYNC3,
DMASTATE_RUN,
DMASTATE_CPUSYNC,
HDMASTATE_IDMASYNC,
HDMASTATE_IDMASYNC2,
HDMASTATE_IDMASYNC3,
HDMASTATE_ICPUSYNC,
HDMASTATE_DMASYNC,
HDMASTATE_DMASYNC2,
HDMASTATE_DMASYNC3,
HDMASTATE_RUN,
HDMASTATE_CPUSYNC
};
struct {
bool hdma;
bool dma;
bool irq;
bool stp;
bool wai;
} run_state;
struct {
uint8 cycle_pos, cycle_count;
uint8 opcode;
uint32 cycles_executed;
uint8 dma_state, hdma_state;
uint32 dma_cycle_count, hdma_cycle_count;
//$4207-$420a
uint16 virq_trigger, hirq_trigger;
//$2181-$2183
uint32 wram_addr;
//$4016-$4017
bool joypad_strobe_latch;
uint8 joypad1_read_pos, joypad2_read_pos;
//$4200
bool nmi_enabled;
bool hirq_enabled, virq_enabled;
bool auto_joypad_poll;
//$4201
uint8 pio;
//$4202-$4203
uint8 mul_a, mul_b;
//$4204-$4206
uint16 div_a;
uint8 div_b;
//$4207-$420a
uint16 hirq_pos, virq_pos;
//$4214-$4216
uint16 r4214;
uint16 r4216;
} status;
inline bool hdma_test();
inline bool nmi_test();
inline bool irq_test();
inline uint8 pio_status();
inline void run();
inline uint32 clocks_executed();
inline void power();
inline void reset();
inline void irq_run();
//mmio commands
void mmio_reset();
uint8 mmio_r2180();
uint8 mmio_r4016();
uint8 mmio_r4017();
uint8 mmio_r4210();
uint8 mmio_r4211();
uint8 mmio_r4212();
uint8 mmio_r4213();
uint8 mmio_r4214();
uint8 mmio_r4215();
uint8 mmio_r4216();
uint8 mmio_r4217();
uint8 mmio_r4218();
uint8 mmio_r4219();
uint8 mmio_r421a();
uint8 mmio_r421b();
uint8 mmio_r43x0(uint8 i);
uint8 mmio_r43x1(uint8 i);
uint8 mmio_r43x2(uint8 i);
uint8 mmio_r43x3(uint8 i);
uint8 mmio_r43x4(uint8 i);
uint8 mmio_r43x5(uint8 i);
uint8 mmio_r43x6(uint8 i);
uint8 mmio_r43x7(uint8 i);
uint8 mmio_r43x8(uint8 i);
uint8 mmio_r43x9(uint8 i);
uint8 mmio_r43xa(uint8 i);
uint8 mmio_r43xb(uint8 i);
void mmio_w2180(uint8 value);
void mmio_w2181(uint8 value);
void mmio_w2182(uint8 value);
void mmio_w2183(uint8 value);
void mmio_w4016(uint8 value);
void mmio_w4200(uint8 value);
void mmio_w4201(uint8 value);
void mmio_w4202(uint8 value);
void mmio_w4203(uint8 value);
void mmio_w4204(uint8 value);
void mmio_w4205(uint8 value);
void mmio_w4206(uint8 value);
void mmio_w4207(uint8 value);
void mmio_w4208(uint8 value);
void mmio_w4209(uint8 value);
void mmio_w420a(uint8 value);
void mmio_w420b(uint8 value);
void mmio_w420c(uint8 value);
void mmio_w420d(uint8 value);
void mmio_w43x0(uint8 value, uint8 i);
void mmio_w43x1(uint8 value, uint8 i);
void mmio_w43x2(uint8 value, uint8 i);
void mmio_w43x3(uint8 value, uint8 i);
void mmio_w43x4(uint8 value, uint8 i);
void mmio_w43x5(uint8 value, uint8 i);
void mmio_w43x6(uint8 value, uint8 i);
void mmio_w43x7(uint8 value, uint8 i);
void mmio_w43x8(uint8 value, uint8 i);
void mmio_w43x9(uint8 value, uint8 i);
void mmio_w43xa(uint8 value, uint8 i);
void mmio_w43xb(uint8 value, uint8 i);
uint8 mmio_read (uint16 addr);
void mmio_write(uint16 addr, uint8 data);
enum { CYCLE_OPREAD, CYCLE_READ, CYCLE_WRITE, CYCLE_IO };
inline void pre_exec_cycle();
inline void exec_hdma();
inline void exec_dma();
inline void exec_cycle();
inline void last_cycle();
inline bool in_opcode();
bCPU();
~bCPU();
};

View File

@@ -1,163 +0,0 @@
void bCPU::last_cycle() {
time.nmi_pending |= nmi_test();
time.irq_pending |= irq_test();
run_state.irq = (time.nmi_pending || time.irq_pending);
}
void bCPU::pre_exec_cycle() {
if(!run_state.dma && !run_state.hdma)return;
int c, z;
if(run_state.hdma) {
switch(status.hdma_state) {
case HDMASTATE_ICPUSYNC:
case HDMASTATE_CPUSYNC:
c = status.cycle_count;
z = c - (status.hdma_cycle_count % c);
if(!z)z = c;
add_cycles(z);
run_state.hdma = false;
break;
}
}
if(run_state.dma) {
switch(status.dma_state) {
case DMASTATE_CPUSYNC:
c = status.cycle_count;
z = c - (status.dma_cycle_count % c);
if(!z)z = c;
add_cycles(z);
run_state.dma = false;
break;
}
}
}
void bCPU::exec_hdma() {
int n;
static int z;
switch(status.hdma_state) {
case HDMASTATE_IDMASYNC:
status.hdma_cycle_count = 0;
z = 0;
if(!run_state.dma) {
exec_cycle();
status.hdma_state = HDMASTATE_IDMASYNC2;
} else {
status.hdma_state = HDMASTATE_IDMASYNC3;
}
break;
case HDMASTATE_IDMASYNC2:
n = 8 - dma_counter() + 8;
add_cycles(n);
status.hdma_cycle_count += n;
status.hdma_state = HDMASTATE_IDMASYNC3;
break;
case HDMASTATE_IDMASYNC3:
hdma_init();
if(!run_state.dma) {
status.hdma_state = HDMASTATE_ICPUSYNC;
} else {
run_state.hdma = false;
}
break;
case HDMASTATE_ICPUSYNC:
exec_cycle();
break;
case HDMASTATE_DMASYNC:
status.hdma_cycle_count = 0;
z = 0;
if(!run_state.dma) {
exec_cycle();
status.hdma_state = HDMASTATE_DMASYNC2;
} else {
status.hdma_state = HDMASTATE_DMASYNC3;
}
break;
case HDMASTATE_DMASYNC2:
n = 8 - dma_counter() + 8;
add_cycles(n);
status.hdma_cycle_count += n;
status.hdma_state = HDMASTATE_DMASYNC3;
break;
case HDMASTATE_DMASYNC3:
if(channel[z].hdma_line_counter) {
add_cycles(8);
status.hdma_cycle_count += 8;
}
if(++z < 8)break;
status.hdma_state = HDMASTATE_RUN;
break;
case HDMASTATE_RUN:
hdma_run(); //updates status.hdma_cycle_count
if(!run_state.dma) {
status.hdma_state = HDMASTATE_CPUSYNC;
} else {
run_state.hdma = false;
}
break;
case HDMASTATE_CPUSYNC:
exec_cycle();
break;
}
}
void bCPU::exec_dma() {
int n;
static int z;
switch(status.dma_state) {
case DMASTATE_DMASYNC:
exec_cycle();
status.dma_state = DMASTATE_DMASYNC2;
break;
case DMASTATE_DMASYNC2:
n = 8 - dma_counter() + 8;
add_cycles(n);
status.dma_cycle_count = n;
z = 0;
status.dma_state = DMASTATE_DMASYNC3;
break;
case DMASTATE_DMASYNC3:
if(channel[z].dma_enabled == true) {
add_cycles(8);
status.dma_cycle_count += 8;
}
if(++z < 8)break;
status.dma_state = DMASTATE_RUN;
break;
case DMASTATE_RUN:
dma_run(); //updates status.dma_cycle_count
cycle_edge();
break;
case DMASTATE_CPUSYNC:
exec_cycle();
break;
}
}
void bCPU::exec_cycle() {
if(status.cycle_pos) {
(this->*optbl[status.opcode])();
#ifdef DEBUGGER
if(status.cycle_pos == 0) {
snes->notify(SNES::CPU_EXEC_OPCODE_END);
}
#endif
return;
}
//on first cycle?
#ifdef DEBUGGER
snes->notify(SNES::CPU_EXEC_OPCODE_BEGIN);
#endif
status.opcode = op_readpc();
status.cycle_pos = 1;
}
//only return true when we are on an opcode edge
bool bCPU::in_opcode() {
return (status.cycle_pos != 0);
}

View File

@@ -1,50 +0,0 @@
void bCPU::irq_run() {
mem_read(regs.pc.d);
cpu_io();
if(!regs.e)op_writestack(regs.pc.b);
op_writestack(regs.pc.h);
op_writestack(regs.pc.l);
op_writestack(regs.e ? (regs.p & ~0x10) : regs.p);
rd.l = op_readaddr(aa.w + 0);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
rd.h = op_readaddr(aa.w + 1);
regs.pc.w = rd.w;
#ifdef DEBUGGER
//let debugger know the new IRQ opcode address
snes->notify(SNES::CPU_EXEC_OPCODE_END);
#endif
}
bool bCPU::nmi_test() {
if(time.nmi_transition == 0)return false;
time.nmi_transition = 0;
run_state.wai = false;
return true;
}
bool bCPU::irq_test() {
if(time.irq_transition == 1)goto _true;
if(time.irq_read == 0) {
if(time.irq_line == 1 && (irq_trigger_pos_match(0) || irq_trigger_pos_match(2))) {
return false;
}
goto _true;
}
if(time.irq_line == 0) {
time.irq_line = 1;
goto _true;
}
return false;
_true:
time.irq_transition = 0;
run_state.wai = false;
return (regs.p.i) ? false : true;
}

View File

@@ -1,650 +0,0 @@
void bCPU::mmio_reset() {
//$2181-$2183
status.wram_addr = 0x000000;
//$4016-$4017
status.joypad_strobe_latch = 0;
status.joypad1_read_pos = 0;
status.joypad2_read_pos = 0;
//$4200
status.nmi_enabled = false;
status.hirq_enabled = false;
status.virq_enabled = false;
status.auto_joypad_poll = false;
//$4201
status.pio = 0xff;
//$4202-$4203
status.mul_a = 0xff;
status.mul_b = 0xff;
//$4204-$4206
status.div_a = 0xffff;
status.div_b = 0xff;
//$4207-$420a
status.hirq_pos = 0x01ff;
status.virq_pos = 0x01ff;
//$4214-$4217
status.r4214 = 0x0000;
status.r4216 = 0x0000;
}
//WMDATA
uint8 bCPU::mmio_r2180() {
uint8 r;
r = r_mem->read(0x7e0000 | status.wram_addr);
status.wram_addr++;
status.wram_addr &= 0x01ffff;
return r;
}
//JOYSER0
//7-2 = MDR
//1-0 = Joypad serial data
/* The joypad contains a small bit shifter that has 16 bits.
* Reading from 4016 reads one bit from this buffer, then moves
* the buffer left one, and adds a '1' to the rightmost bit.
* Writing a one to $4016 will fill the buffer with the current
* joypad button states, and lock the bit shifter at position
* zero. All reads will be the first buffer state, or 'B'.
* A zero must be written back to $4016 to unlock the buffer,
* so that reads will increment the bit shifting position.
*/
uint8 bCPU::mmio_r4016() {
uint8 r;
r = regs.mdr & 0xfc;
if(status.joypad_strobe_latch == 1) {
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_B);
} else {
switch(status.joypad1_read_pos) {
case 0: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_B); break;
case 1: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_Y); break;
case 2: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_SELECT); break;
case 3: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_START); break;
case 4: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_UP); break;
case 5: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_DOWN); break;
case 6: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_LEFT); break;
case 7: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_RIGHT); break;
case 8: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_A); break;
case 9: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_X); break;
case 10: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_L); break;
case 11: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_R); break;
case 12: break;
case 13: break;
case 14: break;
case 15: break; //bits 12-15 always return 0
//all subsequent reads return joypad connection status
case 16: r |= 1; break; //joypad connected bit
}
if(++status.joypad1_read_pos > 16)status.joypad1_read_pos = 16;
}
return r;
}
//JOYSER1
//7-5 = MDR
//4-2 = Always 1 (pins are connected to GND)
//1-0 = Joypad serial data
uint8 bCPU::mmio_r4017() {
uint8 r;
r = regs.mdr & 0xe0;
r |= 0x1c;
if(status.joypad_strobe_latch == 1) {
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_B);
} else {
switch(status.joypad2_read_pos) {
case 0: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_B); break;
case 1: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_Y); break;
case 2: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_SELECT); break;
case 3: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_START); break;
case 4: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_UP); break;
case 5: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_DOWN); break;
case 6: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_LEFT); break;
case 7: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_RIGHT); break;
case 8: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_A); break;
case 9: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_X); break;
case 10: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_L); break;
case 11: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_R); break;
case 12: break;
case 13: break;
case 14: break;
case 15: break; //bits 12-15 always return 0
//all subsequent reads return joypad connection status
case 16: r |= 1; break; //joypad connected bit
}
if(++status.joypad2_read_pos > 16)status.joypad2_read_pos = 16;
}
return r;
}
//RDNMI
//7 = NMI acknowledge
//6-4 = MDR
//3-0 = CPU (5a22) version
uint8 bCPU::mmio_r4210() {
uint8 r;
r = regs.mdr & 0x70;
r |= uint8(!time.nmi_read) << 7;
if(!nmi_trigger_pos_match(0) && !nmi_trigger_pos_match(2)) {
time.nmi_read = 1;
}
r |= (cpu_version & 0x0f);
return r;
}
//TIMEUP
//7 = IRQ acknowledge
//6-0 = MDR
uint8 bCPU::mmio_r4211() {
uint8 r;
r = regs.mdr & 0x7f;
r |= uint8(!time.irq_read) << 7;
if(!irq_trigger_pos_match(0) && !irq_trigger_pos_match(2)) {
time.irq_read = 1;
time.irq_line = 1;
time.irq_transition = 0;
}
return r;
}
//HVBJOY
//7 = in vblank
//6 = in hblank
//5-1 = MDR
//0 = joypad ready
uint8 bCPU::mmio_r4212() {
uint8 r;
r = regs.mdr & 0x3e;
uint16 vs = overscan() ? 240 : 225;
//auto joypad polling
if(time.v >= vs && time.v <= (vs + 2))r |= 0x01;
//hblank
if(time.hc <= 2 || time.hc >= 1096)r |= 0x40;
//vblank
if(time.v >= vs)r |= 0x80;
return r;
}
//RDIO
uint8 bCPU::mmio_r4213() {
return status.pio;
}
//RDDIVL
uint8 bCPU::mmio_r4214() {
return status.r4214;
}
//RDDIVH
uint8 bCPU::mmio_r4215() {
return status.r4214 >> 8;
}
//RDMPYL
uint8 bCPU::mmio_r4216() {
return status.r4216;
}
//RDMPYH
uint8 bCPU::mmio_r4217() {
return status.r4216 >> 8;
}
//JOY1L
uint8 bCPU::mmio_r4218() {
uint8 r = 0x00;
uint16 v = vcounter();
if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled
//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_A) << 7;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_X) << 6;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_L) << 5;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_R) << 4;
return r;
}
//JOY1H
uint8 bCPU::mmio_r4219() {
uint8 r = 0x00;
uint16 v = vcounter();
if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled
//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_B) << 7;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_Y) << 6;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_SELECT) << 5;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_START) << 4;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_UP) << 3;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_DOWN) << 2;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_LEFT) << 1;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_RIGHT);
return r;
}
//JOY2L
uint8 bCPU::mmio_r421a() {
uint8 r = 0x00;
uint16 v = vcounter();
if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled
//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_A) << 7;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_X) << 6;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_L) << 5;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_R) << 4;
return r;
}
//JOY2H
uint8 bCPU::mmio_r421b() {
uint8 r = 0x00;
uint16 v = vcounter();
if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled
//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_B) << 7;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_Y) << 6;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_SELECT) << 5;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_START) << 4;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_UP) << 3;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_DOWN) << 2;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_LEFT) << 1;
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_RIGHT);
return r;
}
//DMAPx
uint8 bCPU::mmio_r43x0(uint8 i) {
return channel[i].dmap;
}
//BBADx
uint8 bCPU::mmio_r43x1(uint8 i) {
return channel[i].destaddr;
}
//A1TxL
uint8 bCPU::mmio_r43x2(uint8 i) {
return channel[i].srcaddr;
}
//A1TxH
uint8 bCPU::mmio_r43x3(uint8 i) {
return channel[i].srcaddr >> 8;
}
//A1Bx
uint8 bCPU::mmio_r43x4(uint8 i) {
return channel[i].srcbank;
}
//DASxL
uint8 bCPU::mmio_r43x5(uint8 i) {
return channel[i].xfersize;
}
//DASxH
uint8 bCPU::mmio_r43x6(uint8 i) {
return channel[i].xfersize >> 8;
}
//DASBx
uint8 bCPU::mmio_r43x7(uint8 i) {
return channel[i].hdma_ibank;
}
//A2AxL
uint8 bCPU::mmio_r43x8(uint8 i) {
return channel[i].hdma_addr;
}
//A2AxH
uint8 bCPU::mmio_r43x9(uint8 i) {
return channel[i].hdma_addr >> 8;
}
//NTRLx
uint8 bCPU::mmio_r43xa(uint8 i) {
return channel[i].hdma_line_counter;
}
//???
uint8 bCPU::mmio_r43xb(uint8 i) {
return channel[i].hdma_unknown;
}
uint8 bCPU::mmio_read(uint16 addr) {
//APU
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
return r_smp->port_read(addr & 3);
}
//HDMA
if((addr & 0xff80) == 0x4300) { //$4300-$437f
uint i = (addr >> 4) & 7;
switch(addr & 0xf) {
case 0x0: return mmio_r43x0(i);
case 0x1: return mmio_r43x1(i);
case 0x2: return mmio_r43x2(i);
case 0x3: return mmio_r43x3(i);
case 0x4: return mmio_r43x4(i);
case 0x5: return mmio_r43x5(i);
case 0x6: return mmio_r43x6(i);
case 0x7: return mmio_r43x7(i);
case 0x8: return mmio_r43x8(i);
case 0x9: return mmio_r43x9(i);
case 0xa: return mmio_r43xa(i);
case 0xb: return mmio_r43xb(i);
case 0xc: return regs.mdr; //unmapped
case 0xd: return regs.mdr; //unmapped
case 0xe: return regs.mdr; //unmapped
case 0xf: return mmio_r43xb(i); //mirror of 43xb
}
}
switch(addr) {
case 0x2180: return mmio_r2180(); //WMDATA
case 0x4016: return mmio_r4016(); //JOYSER0
case 0x4017: return mmio_r4017(); //JOYSER1
case 0x4210: return mmio_r4210(); //RDNMI
case 0x4211: return mmio_r4211(); //TIMEUP
case 0x4212: return mmio_r4212(); //HVBJOY
case 0x4213: return mmio_r4213(); //RDIO
case 0x4214: return mmio_r4214(); //RDDIVL
case 0x4215: return mmio_r4215(); //RDDIVH
case 0x4216: return mmio_r4216(); //RDMPYL
case 0x4217: return mmio_r4217(); //RDMPYH
case 0x4218: return mmio_r4218(); //JOY1L
case 0x4219: return mmio_r4219(); //JOY1H
case 0x421a: return mmio_r421a(); //JOY2L
case 0x421b: return mmio_r421b(); //JOY2H
case 0x421c: return 0x00;
case 0x421d: return 0x00;
case 0x421e: return 0x00;
case 0x421f: return 0x00;
}
return regs.mdr;
}
//WMDATA
void bCPU::mmio_w2180(uint8 value) {
r_mem->write(0x7e0000 | status.wram_addr, value);
status.wram_addr++;
status.wram_addr &= 0x01ffff;
}
//WMADDL
void bCPU::mmio_w2181(uint8 value) {
status.wram_addr = (status.wram_addr & 0xffff00) | value;
status.wram_addr &= 0x01ffff;
}
//WMADDM
void bCPU::mmio_w2182(uint8 value) {
status.wram_addr = (status.wram_addr & 0xff00ff) | (value << 8);
status.wram_addr &= 0x01ffff;
}
//WMADDH
void bCPU::mmio_w2183(uint8 value) {
status.wram_addr = (status.wram_addr & 0x00ffff) | (value << 16);
status.wram_addr &= 0x01ffff;
}
//JOYSER0
//bit 0 is shared between JOYSER0 and JOYSER1, therefore
//strobing $4016.d0 affects both controller port latches.
//$4017 bit 0 writes are ignored.
void bCPU::mmio_w4016(uint8 value) {
status.joypad_strobe_latch = bool(value & 1);
if(status.joypad_strobe_latch == 1) {
snes->poll_input();
status.joypad1_read_pos = 0;
status.joypad2_read_pos = 0;
}
}
//NMITIMEN
void bCPU::mmio_w4200(uint8 value) {
status.nmi_enabled = bool(value & 0x80);
status.virq_enabled = bool(value & 0x20);
status.hirq_enabled = bool(value & 0x10);
status.auto_joypad_poll = bool(value & 0x01);
if(time.nmi_read == 0) {
if(time.nmi_line == 1 && !status.nmi_enabled == 0) {
time.nmi_transition = 1;
}
time.nmi_line = !status.nmi_enabled;
}
if(status.virq_enabled == false && status.hirq_enabled == false) {
time.irq_line = 1;
time.irq_read = 1;
time.irq_transition = 0;
}
update_interrupts();
}
//WRIO
void bCPU::mmio_w4201(uint8 value) {
if((status.pio & 0x80) && !(value & 0x80)) {
r_ppu->latch_counters();
}
status.pio = value;
}
//WRMPYA
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;
}
//WRDIVL
void bCPU::mmio_w4204(uint8 value) {
status.div_a = (status.div_a & 0xff00) | (value);
}
//WRDIVH
void bCPU::mmio_w4205(uint8 value) {
status.div_a = (status.div_a & 0x00ff) | (value << 8);
}
//WRDIVB
void bCPU::mmio_w4206(uint8 value) {
status.div_b = value;
status.r4214 = (status.div_b) ? status.div_a / status.div_b : 0xffff;
status.r4216 = (status.div_b) ? status.div_a % status.div_b : status.div_a;
}
//HTIMEL
void bCPU::mmio_w4207(uint8 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)) & 0x01ff;
update_interrupts();
}
//VTIMEL
void bCPU::mmio_w4209(uint8 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)) & 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;
status.dma_state = DMASTATE_DMASYNC;
}
for(int i = 0; i < 8; i++) {
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;
}
}
//HDMAEN
void bCPU::mmio_w420c(uint8 value) {
for(int i = 0; i < 8; i++) {
channel[i].hdma_enabled = bool(value & (1 << i));
}
}
//MEMSEL
void bCPU::mmio_w420d(uint8 value) {
r_mem->set_speed(value & 1);
}
//DMAPx
void bCPU::mmio_w43x0(uint8 value, uint8 i) {
channel[i].dmap = value;
channel[i].direction = bool(value & 0x80);
channel[i].hdma_indirect = bool(value & 0x40);
channel[i].incmode = (value & 0x10) ? -1 : 1;
channel[i].fixedxfer = bool(value & 0x08);
channel[i].xfermode = value & 7;
}
//BBADx
void bCPU::mmio_w43x1(uint8 value, uint8 i) {
channel[i].destaddr = value;
}
//A1TxL
void bCPU::mmio_w43x2(uint8 value, uint8 i) {
channel[i].srcaddr = (channel[i].srcaddr & 0xff00) | value;
}
//A1TxH
void bCPU::mmio_w43x3(uint8 value, uint8 i) {
channel[i].srcaddr = (channel[i].srcaddr & 0x00ff) | (value << 8);
}
//A1Bx
void bCPU::mmio_w43x4(uint8 value, uint8 i) {
channel[i].srcbank = value;
}
//DASxL
void bCPU::mmio_w43x5(uint8 value, uint8 i) {
channel[i].xfersize = (channel[i].xfersize & 0xff00) | value;
}
//DASxH
void bCPU::mmio_w43x6(uint8 value, uint8 i) {
channel[i].xfersize = (channel[i].xfersize & 0x00ff) | (value << 8);
}
//DASBx
void bCPU::mmio_w43x7(uint8 value, uint8 i) {
channel[i].hdma_ibank = value;
}
//A2AxL
void bCPU::mmio_w43x8(uint8 value, uint8 i) {
channel[i].hdma_addr = (channel[i].hdma_addr & 0xff00) | value;
}
//A2AxH
void bCPU::mmio_w43x9(uint8 value, uint8 i) {
channel[i].hdma_addr = (channel[i].hdma_addr & 0x00ff) | (value << 8);
}
//NTRLx
void bCPU::mmio_w43xa(uint8 value, uint8 i) {
channel[i].hdma_line_counter = value;
}
//???
void bCPU::mmio_w43xb(uint8 value, uint8 i) {
channel[i].hdma_unknown = value;
}
void bCPU::mmio_write(uint16 addr, uint8 data) {
//APU
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
port_write(addr & 3, data);
return;
}
//HDMA
if((addr & 0xff80) == 0x4300) { //$4300-$437f
uint i = (addr >> 4) & 7;
switch(addr & 0xf) {
case 0x0: mmio_w43x0(data, i); return;
case 0x1: mmio_w43x1(data, i); return;
case 0x2: mmio_w43x2(data, i); return;
case 0x3: mmio_w43x3(data, i); return;
case 0x4: mmio_w43x4(data, i); return;
case 0x5: mmio_w43x5(data, i); return;
case 0x6: mmio_w43x6(data, i); return;
case 0x7: mmio_w43x7(data, i); return;
case 0x8: mmio_w43x8(data, i); return;
case 0x9: mmio_w43x9(data, i); return;
case 0xa: mmio_w43xa(data, i); return;
case 0xb: mmio_w43xb(data, i); return;
case 0xc: return; //unmapped
case 0xd: return; //unmapped
case 0xe: return; //unmapped
case 0xf: mmio_w43xb(data, i); return; //mirror of 43xb
}
}
switch(addr) {
case 0x2180: mmio_w2180(data); return; //WMDATA
case 0x2181: mmio_w2181(data); return; //WMADDL
case 0x2182: mmio_w2182(data); return; //WMADDM
case 0x2183: mmio_w2183(data); return; //WMADDH
case 0x4016: mmio_w4016(data); return; //JOYSER0
case 0x4017: return; //unmapped
case 0x4200: mmio_w4200(data); return; //NMITIMEN
case 0x4201: mmio_w4201(data); return; //WRIO
case 0x4202: mmio_w4202(data); return; //WRMPYA
case 0x4203: mmio_w4203(data); return; //WRMPYB
case 0x4204: mmio_w4204(data); return; //WRDIVL
case 0x4205: mmio_w4205(data); return; //WRDIVH
case 0x4206: mmio_w4206(data); return; //WRDIVB
case 0x4207: mmio_w4207(data); return; //HTIMEL
case 0x4208: mmio_w4208(data); return; //HTIMEH
case 0x4209: mmio_w4209(data); return; //VTIMEL
case 0x420a: mmio_w420a(data); return; //VTIMEH
case 0x420b: mmio_w420b(data); return; //DMAEN
case 0x420c: mmio_w420c(data); return; //HDMAEN
case 0x420d: mmio_w420d(data); return; //MEMSEL
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,160 +0,0 @@
bcc(0x90, !regs.p.c),
bcs(0xb0, regs.p.c),
bne(0xd0, !regs.p.z),
beq(0xf0, regs.p.z),
bpl(0x10, !regs.p.n),
bmi(0x30, regs.p.n),
bvc(0x50, !regs.p.v),
bvs(0x70, regs.p.v) {
1:if(!$1)last_cycle();
rd.l = op_readpc();
if($1) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
end;
}
2:cpu_c6(aa.w);
3:last_cycle();
cpu_io();
}
bra(0x80) {
1:rd.l = op_readpc();
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
2:cpu_c6(aa.w);
3:last_cycle();
cpu_io();
}
brl(0x82) {
1:rd.l = op_readpc();
2:rd.h = op_readpc();
3:last_cycle();
cpu_io();
regs.pc.w = regs.pc.d + (int16)rd.w;
}
jmp_addr(0x4c) {
1:rd.l = op_readpc();
2:last_cycle();
rd.h = op_readpc();
regs.pc.w = rd.w;
}
jmp_long(0x5c) {
1:rd.l = op_readpc();
2:rd.h = op_readpc();
3:last_cycle();
rd.b = op_readpc();
regs.pc.d = rd.d & 0xffffff;
}
jmp_iaddr(0x6c) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:rd.l = op_readaddr(aa.w);
4:last_cycle();
rd.h = op_readaddr(aa.w + 1);
regs.pc.w = rd.w;
}
jmp_iaddrx(0x7c) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_io();
4:rd.l = op_readpbr(aa.w + regs.x.w);
5:last_cycle();
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
}
jmp_iladdr(0xdc) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:rd.l = op_readaddr(aa.w);
4:rd.h = op_readaddr(aa.w + 1);
5:last_cycle();
rd.b = op_readaddr(aa.w + 2);
regs.pc.d = rd.d & 0xffffff;
}
jsr_addr(0x20) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_io();
4:regs.pc.w--;
op_writestack(regs.pc.h);
5:last_cycle();
op_writestack(regs.pc.l);
regs.pc.w = aa.w;
}
jsr_long(0x22) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_writestack(regs.pc.b);
4:cpu_io();
5:aa.b = op_readpc();
6:regs.pc.w--;
op_writestack(regs.pc.h);
7:last_cycle();
op_writestack(regs.pc.l);
regs.pc.d = aa.d & 0xffffff;
}
jsr_iaddrx(0xfc) {
1:aa.l = op_readpc();
2:op_writestack(regs.pc.h);
3:op_writestack(regs.pc.l);
4:aa.h = op_readpc();
5:cpu_io();
6:rd.l = op_readpbr(aa.w + regs.x.w);
7:last_cycle();
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
}
rti(0x40) {
1:cpu_io();
2:cpu_io();
3:regs.p = op_readstack();
if(regs.e)regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
4:rd.l = op_readstack();
5:if(regs.e)last_cycle();
rd.h = op_readstack();
if(regs.e) {
regs.pc.w = rd.w;
end;
}
6:last_cycle();
rd.b = op_readstack();
regs.pc.d = rd.d & 0xffffff;
}
rts(0x60) {
1:cpu_io();
2:cpu_io();
3:rd.l = op_readstack();
4:rd.h = op_readstack();
5:last_cycle();
cpu_io();
regs.pc.w = rd.w;
regs.pc.w++;
}
rtl(0x6b) {
1:cpu_io();
2:cpu_io();
3:rd.l = op_readstack();
4:rd.h = op_readstack();
5:last_cycle();
rd.b = op_readstack();
regs.pc.d = rd.d & 0xffffff;
regs.pc.w++;
}

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,185 +0,0 @@
inc(0x1a, regs.p.m, a),
inx(0xe8, regs.p.x, x),
iny(0xc8, regs.p.x, y) {
1:last_cycle();
cpu_io();
if($1) {
regs.$2.l++;
regs.p.n = !!(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0);
} else {
regs.$2.w++;
regs.p.n = !!(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0);
}
}
dec(0x3a, regs.p.m, a),
dex(0xca, regs.p.x, x),
dey(0x88, regs.p.x, y) {
1:last_cycle();
cpu_io();
if($1) {
regs.$2.l--;
regs.p.n = !!(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0);
} else {
regs.$2.w--;
regs.p.n = !!(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0);
}
}
asl(0x0a) {
1:last_cycle();
cpu_io();
if(regs.p.m) {
regs.p.c = !!(regs.a.l & 0x80);
regs.a.l <<= 1;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = !!(regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
lsr(0x4a) {
1:last_cycle();
cpu_io();
if(regs.p.m) {
regs.p.c = regs.a.l & 1;
regs.a.l >>= 1;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = regs.a.w & 1;
regs.a.w >>= 1;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
rol(0x2a) {
1:last_cycle();
cpu_io();
uint16 c = regs.p.c;
if(regs.p.m) {
regs.p.c = !!(regs.a.l & 0x80);
regs.a.l <<= 1;
regs.a.l |= c;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = !!(regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.a.w |= c;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
ror(0x6a) {
1:last_cycle();
cpu_io();
uint16 c;
if(regs.p.m) {
c = (regs.p.c)?0x80:0;
regs.p.c = regs.a.l & 1;
regs.a.l >>= 1;
regs.a.l |= c;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
c = (regs.p.c)?0x8000:0;
regs.p.c = regs.a.w & 1;
regs.a.w >>= 1;
regs.a.w |= c;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
inc_addr(0xee, inc),
dec_addr(0xce, dec),
asl_addr(0x0e, asl),
lsr_addr(0x4e, lsr),
rol_addr(0x2e, rol),
ror_addr(0x6e, ror),
trb_addr(0x1c, trb),
tsb_addr(0x0c, tsb) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:rd.l = op_readdbr(aa.w);
if(regs.p.m)skip;
4:rd.h = op_readdbr(aa.w + 1);
5:cpu_io();
if(regs.p.m) { op_$1_b(); skip; }
else op_$1_w();
6:op_writedbr(aa.w + 1, rd.h);
7:last_cycle();
op_writedbr(aa.w, rd.l);
}
inc_addrx(0xfe, inc),
dec_addrx(0xde, dec),
asl_addrx(0x1e, asl),
lsr_addrx(0x5e, lsr),
rol_addrx(0x3e, rol),
ror_addrx(0x7e, ror) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:cpu_io();
4:rd.l = op_readdbr(aa.w + regs.x.w);
if(regs.p.m)skip;
5:rd.h = op_readdbr(aa.w + regs.x.w + 1);
6:cpu_io();
if(regs.p.m) { op_$1_b(); skip; }
else op_$1_w();
7:op_writedbr(aa.w + regs.x.w + 1, rd.h);
8:last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
}
inc_dp(0xe6, inc),
dec_dp(0xc6, dec),
asl_dp(0x06, asl),
lsr_dp(0x46, lsr),
rol_dp(0x26, rol),
ror_dp(0x66, ror),
trb_dp(0x14, trb),
tsb_dp(0x04, tsb) {
1:dp = op_readpc();
2:cpu_c2();
3:rd.l = op_readdp(dp);
if(regs.p.m)skip;
4:rd.h = op_readdp(dp + 1);
5:cpu_io();
if(regs.p.m) { op_$1_b(); skip; }
else op_$1_w();
6:op_writedp(dp + 1, rd.h);
7:last_cycle();
op_writedp(dp, rd.l);
}
inc_dpx(0xf6, inc),
dec_dpx(0xd6, dec),
asl_dpx(0x16, asl),
lsr_dpx(0x56, lsr),
rol_dpx(0x36, rol),
ror_dpx(0x76, ror) {
1:dp = op_readpc();
2:cpu_c2();
3:cpu_io();
4:rd.l = op_readdp(dp + regs.x.w);
if(regs.p.m)skip;
5:rd.h = op_readdp(dp + regs.x.w + 1);
6:cpu_io();
if(regs.p.m) { op_$1_b(); skip; }
else op_$1_w();
7:op_writedp(dp + regs.x.w + 1, rd.h);
8:last_cycle();
op_writedp(dp + regs.x.w, rd.l);
}

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,61 +0,0 @@
struct {
uint32 read_index; //set to 0 at beginning of DMA/HDMA
//$420b
bool dma_enabled;
//$420c
bool hdma_enabled;
//$43x0
uint8 dmap;
bool direction;
bool hdma_indirect;
int8 incmode;
bool fixedxfer;
uint8 xfermode;
//$43x1
uint8 destaddr;
//$43x2-$43x3
uint16 srcaddr;
//$43x4
uint8 srcbank;
//$43x5-$43x6
union {
uint16 xfersize;
uint16 hdma_iaddr;
};
//$43x7
uint8 hdma_ibank;
//$43x8-$43x9
uint16 hdma_addr;
//$43xa
uint8 hdma_line_counter;
//$43xb/$43xf
uint8 hdma_unknown;
//hdma-specific
bool hdma_completed; //for this frame
bool hdma_do_transfer;
uint8 hdma_current_channel;
uint8 hdma_current_pos;
} channel[8];
inline void dma_transfer_byte(bool direction, uint8 bbus, uint32 abus);
inline uint8 dma_bbus(uint8 i, uint8 index);
inline void dma_add_cycles(uint32 cycles);
inline void hdma_add_cycles(uint32 cycles);
inline void dma_run();
inline void hdma_run();
inline void hdma_init();
inline void hdma_update(uint8 i);
inline uint8 hdma_enabled_channels();
inline uint8 hdma_active_channels();
inline void hdmainit_activate();
inline void hdma_activate();
inline void dma_cputommio(uint8 i, uint8 index);
inline void dma_mmiotocpu(uint8 i, uint8 index);
inline void dma_write(uint8 i, uint8 index);
inline uint32 dma_addr(uint8 i);
inline uint32 hdma_addr(uint8 i);
inline uint32 hdma_iaddr(uint8 i);
inline void dma_reset();

View File

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

View File

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

View File

@@ -1,338 +0,0 @@
/* Notes about PAL timing:
* As I do not have PAL hardware to run timing tests on, I've
* had to guess on a lot of things. Below is how I've arrived
* at various calculations:
*
* NTSC timing crystal: ~21477272hz
* PAL timing crystal: ~21281370hz
* NTSC ~60fps, PAL ~50fps
* NTSC ~262 lines/frame, PAL ~312 lines/frame
* NTSC 21477272 / (262 * 60) = ~1366 cycles/line
* PAL 21281370 / (312 * 50) = ~1364 cycles/line
*
* As the cycles/line are very close between the two systems,
* I have left the known NTSC anomalies intact for PAL timing.
* In reality, some of these may not exist, and some may be
* slightly different.
*
* [known]
* - DRAM refresh occurs at about the same time every
* scanline on PAL units (per Overload).
* [unknown]
* - Are dots 323/327 still 2 cycles longer than the
* other dots?
* - Is scanline 240 on non-interlace odd frames still
* 4 cycles short?
*/
uint16 bCPU::vcounter() { return time.v; }
uint16 bCPU::hclock() { return time.hc; }
bool bCPU::interlace() { return time.interlace; }
bool bCPU::interlace_field() { return time.interlace_field; }
bool bCPU::overscan() { return time.overscan; }
uint16 bCPU::region_scanlines() { return time.region_scanlines; }
void bCPU::set_interlace(bool r) { time.interlace = r; update_interrupts(); }
void bCPU::set_overscan (bool r) { time.overscan = r; update_interrupts(); }
uint8 bCPU::dma_counter() { return (time.dma_counter + time.hc) & 6; }
uint16 bCPU::hcounter() {
if(time.v == 240 && time.interlace == false && time.interlace_field == 1) {
return time.hc >> 2;
}
return (time.hc - ((time.hc > 1292) << 1) - ((time.hc > 1310) << 1)) >> 2;
}
bool bCPU::nmi_trigger_pos_match(uint32 offset) {
uint16 v = overscan() ? 240 : 225;
uint16 hc = 2 + offset;
return (time.v == v && time.hc == hc);
}
bool bCPU::irq_trigger_pos_match(uint32 offset) {
uint16 v = status.virq_pos;
uint16 hc = (status.hirq_enabled) ? status.hirq_pos : 0;
uint16 vlimit = region_scanlines() >> 1;
//positions that can never be latched
//region_scanlines() = 525/NTSC, 625/PAL
//PAL results are unverified on hardware
if(v == 240 && hc == 339 && interlace() == false && interlace_field() == 1)return false;
if(v == (vlimit - 1) && hc == 339 && interlace() == false)return false;
if(v == vlimit && interlace() == false)return false;
if(v == vlimit && hc == 339)return false;
if(v > vlimit)return false;
if(hc > 339)return false;
hc = (hc != 0) ? ((hc << 2) + 14) : 10;
hc += offset;
if(hc >= time.line_cycles) {
hc -= time.line_cycles;
if(++v >= time.frame_lines) {
v = 0;
}
}
if((status.virq_enabled == true && time.v == v) || status.virq_enabled == false) {
return (time.hc == hc);
}
return false;
}
void bCPU::update_nmi() {
if(time.v == (overscan() ? 240 : 225)) {
time.nmi_read_trigger_pos = 2;
time.nmi_line_trigger_pos = 6;
} else {
time.nmi_read_trigger_pos = -64;
time.nmi_line_trigger_pos = -64;
}
}
void bCPU::update_irq() {
int vpos = status.virq_pos;
int hpos = (status.hirq_enabled) ? status.hirq_pos : 0;
int vlimit = region_scanlines() >> 1;
//positions that can never be latched
//region_scanlines() = 262/NTSC, 312/PAL
//PAL results are unverified on hardware
if(vpos == 240 && hpos == 339 && interlace() == false && interlace_field() == 1)goto _nolatch;
if(vpos == (vlimit - 1) && hpos == 339 && interlace() == false)goto _nolatch;
if(vpos == vlimit && interlace() == false)goto _nolatch;
if(vpos == vlimit && hpos == 339)goto _nolatch;
if(vpos > vlimit)goto _nolatch;
if(hpos > 339)goto _nolatch;
hpos = (hpos != 0) ? ((hpos << 2) + 14) : 10;
if(hpos >= time.line_cycles) {
hpos -= time.line_cycles;
if(++vpos >= time.frame_lines) {
vpos = 0;
}
}
if((status.virq_enabled == true && time.v == vpos) || status.virq_enabled == false) {
time.irq_read_trigger_pos = hpos;
} else {
time.irq_read_trigger_pos = -64;
}
hpos += 4;
if(hpos >= time.line_cycles) {
hpos -= time.line_cycles;
if(++vpos >= time.frame_lines) {
vpos = 0;
}
}
if((status.virq_enabled == true && time.v == vpos) || status.virq_enabled == false) {
time.irq_line_trigger_pos = hpos;
} else {
time.irq_line_trigger_pos = -64;
}
return;
_nolatch:
time.irq_read_trigger_pos = -64;
time.irq_line_trigger_pos = -64;
}
void bCPU::update_interrupts() {
update_nmi();
update_irq();
}
void bCPU::poll_interrupts(int cycles) {
int16 hc, hc_end;
if(time.hc == 0) {
hc = -1;
hc_end = cycles;
} else {
hc = time.hc;
hc_end = time.hc + cycles;
}
if(hc < time.nmi_read_trigger_pos && time.nmi_read_trigger_pos <= hc_end) {
//nmi_read can go low even with NMI interrupts disabled in $4200.d7
time.nmi_read = 0;
}
if(hc < time.nmi_line_trigger_pos && time.nmi_line_trigger_pos <= hc_end) {
if(status.nmi_enabled == true) {
if(time.nmi_line == 1) {
time.nmi_transition = 1;
}
time.nmi_line = 0;
}
}
if(hc < time.irq_read_trigger_pos && time.irq_read_trigger_pos <= hc_end) {
if(status.virq_enabled == true || status.hirq_enabled == true) {
time.irq_read = 0;
}
}
if(hc < time.irq_line_trigger_pos && time.irq_line_trigger_pos <= hc_end) {
if(status.virq_enabled == true || status.hirq_enabled == true) {
time.irq_line = 0;
time.irq_transition = 1;
}
}
}
uint32 bCPU::clocks_executed() {
uint32 r = status.cycles_executed;
status.cycles_executed = 0;
return r;
}
void bCPU::cycle_edge() {
if(time.line_rendered == false) {
if(time.hc >= 192) {
time.line_rendered = true;
r_ppu->render_scanline();
}
}
if(time.hdmainit_triggered == false) {
if(time.hc >= time.hdmainit_trigger_pos || time.v) {
time.hdmainit_triggered = true;
hdmainit_activate();
}
}
if(time.hdma_triggered == false) {
//hdma_triggered only set to false for v <= (overscan ? 239 : 224)
if(time.hc >= 1106) {
time.hdma_triggered = true;
hdma_activate();
}
}
}
void bCPU::add_cycles(int cycles) {
status.cycles_executed += cycles;
poll_interrupts(cycles);
if(time.hc + cycles >= time.line_cycles) {
cycles = (time.hc + cycles) - time.line_cycles;
time.hc = 0;
scanline();
poll_interrupts(cycles);
}
time.hc += cycles;
if(time.dram_refreshed == false) {
if(time.hc >= time.dram_refresh_pos) {
time.dram_refreshed = true;
add_cycles(40);
return;
}
}
}
void bCPU::scanline() {
if(++time.v >= time.frame_lines) {
frame();
}
time.dma_counter += time.line_cycles;
if(time.v == 240 && time.interlace == false && time.interlace_field == 1) {
time.line_cycles = 1360;
} else {
time.line_cycles = 1364;
}
time.dram_refreshed = false;
time.line_rendered =
time.hdma_triggered = (time.v <= (!overscan() ? 224 : 239)) ? false : true;
r_ppu->scanline();
snes->scanline();
update_interrupts();
if(vcounter() == (!overscan() ? 227 : 242) && status.auto_joypad_poll == true) {
snes->poll_input();
//When the SNES auto-polls the joypads, it writes 1, then 0 to
//$4016, then reads from each 16 times to get the joypad state
//information. As a result, the joypad read positions are set
//to 16 after such a poll. Position 16 is the controller
//connected status bit.
status.joypad1_read_pos = 16;
status.joypad2_read_pos = 16;
}
}
void bCPU::frame() {
time.nmi_read = 1;
time.nmi_line = 1;
time.nmi_transition = 0;
time.v = 0;
time.interlace_field ^= 1;
if(interlace() == true && interlace_field() == 0) {
time.frame_lines = (time.region_scanlines >> 1) + 1;
} else {
time.frame_lines = (time.region_scanlines >> 1);
}
if(cpu_version == 2) {
time.hdmainit_trigger_pos = 12 + dma_counter();
} else {
time.hdmainit_trigger_pos = 12 + 8 - dma_counter();
}
time.hdmainit_triggered = false;
r_ppu->frame();
snes->frame();
}
void bCPU::time_reset() {
time.v = 0;
time.hc = 0;
//upon SNES reset, start at scanline 0 non-interlace
time.interlace = 0;
time.interlace_field = 0;
time.overscan = false;
time.line_cycles = 1364;
time.dram_refreshed = false;
time.dram_refresh_pos = (cpu_version == 2) ? 538 : 530;
time.dma_counter = 0;
//set at V=0,H=0
time.hdmainit_trigger_pos = 0;
time.hdmainit_triggered = true;
time.hdma_triggered = false;
time.nmi_pending = false;
time.irq_pending = false;
time.nmi_line = time.nmi_read = 1;
time.irq_line = time.irq_read = 1;
time.nmi_transition = 0;
time.irq_transition = 0;
update_interrupts();
switch(region) {
case NTSC:
time.region_scanlines = 525;
break;
case PAL:
time.region_scanlines = 625;
break;
}
time.frame_lines = time.region_scanlines >> 1;
}

View File

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

View File

@@ -1,6 +1,9 @@
#include "cpuregs.h" #include "cpuregs.h"
class CPU : public MMIO { class CPU : public MMIO {
public:
virtual void enter() = 0;
public: public:
//CPU version number //CPU version number
//* 1 and 2 are known //* 1 and 2 are known
@@ -30,9 +33,6 @@ CPURegs regs;
FLAG_Z = 0x02, FLAG_C = 0x01 FLAG_Z = 0x02, FLAG_C = 0x01
}; };
virtual uint8 pio_status() = 0; virtual uint8 pio_status() = 0;
virtual void main() {}
virtual void run() = 0;
virtual uint32 clocks_executed() = 0;
virtual void scanline() = 0; virtual void scanline() = 0;
virtual void frame() = 0; virtual void frame() = 0;
virtual void power() = 0; virtual void power() = 0;

View File

@@ -71,6 +71,5 @@ CPURegFlags p;
uint8 db; uint8 db;
uint8 mdr; uint8 mdr;
bool e; bool e;
bool acc_8b, idx_8b; CPURegs() : db(0), mdr(0x00), e(false) {}
CPURegs() : db(0), mdr(0x00), e(false), acc_8b(true), idx_8b(true) {}
}; };

View File

@@ -1,6 +1,6 @@
#include "opfn.cpp" #include "opfn.cpp"
void sCPU::main() { void sCPU::enter() {
for(;;) { for(;;) {
if(event.irq) { if(event.irq) {
event.irq = false; event.irq = false;
@@ -27,10 +27,6 @@ void sCPU::main() {
} }
status.in_opcode = false; status.in_opcode = false;
#ifdef FAVOR_SPEED
co_return();
#endif
} }
} }

View File

@@ -3,10 +3,9 @@
CPUReg24 aa, rd; CPUReg24 aa, rd;
uint8 dp, sp; uint8 dp, sp;
inline void main(); void op_irq();
inline void op_irq();
inline bool in_opcode() { return status.in_opcode; } inline bool in_opcode() { return status.in_opcode; }
//op_read //op_read
void op_adc_b(); void op_adc_b();

View File

@@ -15,7 +15,7 @@ xba(0xeb) {
regs.a.l ^= regs.a.h; regs.a.l ^= regs.a.h;
regs.a.h ^= regs.a.l; regs.a.h ^= regs.a.l;
regs.a.l ^= regs.a.h; regs.a.l ^= regs.a.h;
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} }
@@ -27,10 +27,12 @@ mvp(0x44, --) {
rd.l = op_readlong((sp << 16) | regs.x.w); rd.l = op_readlong((sp << 16) | regs.x.w);
4:op_writelong((dp << 16) | regs.y.w, rd.l); 4:op_writelong((dp << 16) | regs.y.w, rd.l);
5:op_io(); 5:op_io();
if(regs.idx_8b) { if(regs.p.x) {
regs.x.l $1; regs.y.l $1; regs.x.l $1;
regs.y.l $1;
} else { } else {
regs.x.w $1; regs.y.w $1; regs.x.w $1;
regs.y.w $1;
} }
6:last_cycle(); 6:last_cycle();
op_io(); op_io();
@@ -56,10 +58,7 @@ cop(0x02, 0xfff4, 0xfff5, 0xffe4, 0xffe5) {
stp(0xdb) { stp(0xdb) {
1:op_io(); 1:op_io();
2:last_cycle(); 2:last_cycle();
while(1) { while(1) { op_io(); }
op_io();
co_return();
}
} }
wai(0xcb) { wai(0xcb) {
@@ -70,20 +69,20 @@ wai(0xcb) {
3:while(event.wai) { 3:while(event.wai) {
last_cycle(); last_cycle();
op_io(); op_io();
co_return();
} }
} }
xce(0xfb) { xce(0xfb) {
1:last_cycle(); 1:last_cycle();
op_io(); op_io();
bool c = regs.p.c; bool carry = regs.p.c;
regs.p.c = regs.e; regs.p.c = regs.e;
regs.e = c; regs.e = carry;
if(regs.e)regs.s.h = 0x01; if(regs.e) {
regs.acc_8b = (regs.e || regs.p.m); regs.p |= 0x30;
regs.idx_8b = (regs.e || regs.p.x); regs.s.h = 0x01;
if(regs.idx_8b) { }
if(regs.p.x) {
regs.x.h = 0x00; regs.x.h = 0x00;
regs.y.h = 0x00; regs.y.h = 0x00;
} }
@@ -107,29 +106,28 @@ sep(0xe2, |=) {
2:last_cycle(); 2:last_cycle();
op_io(); op_io();
regs.p $1 rd.l; regs.p $1 rd.l;
regs.acc_8b = (regs.e || regs.p.m); if(regs.e)regs.p |= 0x30;
regs.idx_8b = (regs.e || regs.p.x); if(regs.p.x) {
if(regs.idx_8b) {
regs.x.h = 0x00; regs.x.h = 0x00;
regs.y.h = 0x00; regs.y.h = 0x00;
} }
} }
tax(0xaa, regs.idx_8b, x, a), tax(0xaa, regs.p.x, x, a),
tay(0xa8, regs.idx_8b, y, a), tay(0xa8, regs.p.x, y, a),
txa(0x8a, regs.acc_8b, a, x), txa(0x8a, regs.p.m, a, x),
txy(0x9b, regs.idx_8b, y, x), txy(0x9b, regs.p.x, y, x),
tya(0x98, regs.acc_8b, a, y), tya(0x98, regs.p.m, a, y),
tyx(0xbb, regs.idx_8b, x, y) { tyx(0xbb, regs.p.x, x, y) {
1:last_cycle(); 1:last_cycle();
op_io(); op_io();
if($1) { if($1) {
regs.$2.l = regs.$3.l; regs.$2.l = regs.$3.l;
regs.p.n = bool(regs.$2.l & 0x80); regs.p.n = !!(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0); regs.p.z = (regs.$2.l == 0);
} else { } else {
regs.$2.w = regs.$3.w; regs.$2.w = regs.$3.w;
regs.p.n = bool(regs.$2.w & 0x8000); regs.p.n = !!(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0); regs.p.z = (regs.$2.w == 0);
} }
} }
@@ -138,7 +136,7 @@ tcd(0x5b) {
1:last_cycle(); 1:last_cycle();
op_io(); op_io();
regs.d.w = regs.a.w; regs.d.w = regs.a.w;
regs.p.n = bool(regs.d.w & 0x8000); regs.p.n = !!(regs.d.w & 0x8000);
regs.p.z = (regs.d.w == 0); regs.p.z = (regs.d.w == 0);
} }
@@ -153,7 +151,7 @@ tdc(0x7b) {
1:last_cycle(); 1:last_cycle();
op_io(); op_io();
regs.a.w = regs.d.w; regs.a.w = regs.d.w;
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
@@ -162,10 +160,10 @@ tsc(0x3b) {
op_io(); op_io();
regs.a.w = regs.s.w; regs.a.w = regs.s.w;
if(regs.e) { if(regs.e) {
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} else { } else {
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
} }
@@ -173,13 +171,13 @@ tsc(0x3b) {
tsx(0xba) { tsx(0xba) {
1:last_cycle(); 1:last_cycle();
op_io(); op_io();
if(regs.idx_8b) { if(regs.p.x) {
regs.x.l = regs.s.l; regs.x.l = regs.s.l;
regs.p.n = bool(regs.x.l & 0x80); regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0); regs.p.z = (regs.x.l == 0);
} else { } else {
regs.x.w = regs.s.w; regs.x.w = regs.s.w;
regs.p.n = bool(regs.x.w & 0x8000); regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0); regs.p.z = (regs.x.w == 0);
} }
} }
@@ -194,16 +192,23 @@ txs(0x9a) {
} }
} }
pha(0x48, regs.acc_8b, a), pha(0x48, regs.p.m, a),
phx(0xda, regs.idx_8b, x), phx(0xda, regs.p.x, x),
phy(0x5a, regs.idx_8b, y), phy(0x5a, regs.p.x, y) {
phd(0x0b, 0, d) {
1:op_io(); 1:op_io();
2:if(!$1)op_writestack(regs.$2.h); 2:if(!$1)op_writestack(regs.$2.h);
3:last_cycle(); 3:last_cycle();
op_writestack(regs.$2.l); op_writestack(regs.$2.l);
} }
phd(0x0b) {
1:op_io();
2:op_writestackn(regs.d.h);
3:last_cycle();
op_writestackn(regs.d.l);
if(regs.e)regs.s.h = 0x01;
}
phb(0x8b, regs.db), phb(0x8b, regs.db),
phk(0x4b, regs.pc.b), phk(0x4b, regs.pc.b),
php(0x08, regs.p) { php(0x08, regs.p) {
@@ -212,31 +217,41 @@ php(0x08, regs.p) {
op_writestack($1); op_writestack($1);
} }
pla(0x68, regs.acc_8b, a), pla(0x68, regs.p.m, a),
plx(0xfa, regs.idx_8b, x), plx(0xfa, regs.p.x, x),
ply(0x7a, regs.idx_8b, y), ply(0x7a, regs.p.x, y) {
pld(0x2b, 0, d) {
1:op_io(); 1:op_io();
2:op_io(); 2:op_io();
3:if($1)last_cycle(); 3:if($1)last_cycle();
regs.$2.l = op_readstack(); regs.$2.l = op_readstack();
if($1) { if($1) {
regs.p.n = bool(regs.$2.l & 0x80); regs.p.n = !!(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0); regs.p.z = (regs.$2.l == 0);
end; end;
} }
4:last_cycle(); 4:last_cycle();
regs.$2.h = op_readstack(); regs.$2.h = op_readstack();
regs.p.n = bool(regs.$2.w & 0x8000); regs.p.n = !!(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0); regs.p.z = (regs.$2.w == 0);
} }
pld(0x2b) {
1:op_io();
2:op_io();
3:regs.d.l = op_readstackn();
4:last_cycle();
regs.d.h = op_readstackn();
regs.p.n = !!(regs.d.w & 0x8000);
regs.p.z = (regs.d.w == 0);
if(regs.e)regs.s.h = 0x01;
}
plb(0xab) { plb(0xab) {
1:op_io(); 1:op_io();
2:op_io(); 2:op_io();
3:last_cycle(); 3:last_cycle();
regs.db = op_readstack(); regs.db = op_readstack();
regs.p.n = bool(regs.db & 0x80); regs.p.n = !!(regs.db & 0x80);
regs.p.z = (regs.db == 0); regs.p.z = (regs.db == 0);
} }
@@ -245,9 +260,8 @@ plp(0x28) {
2:op_io(); 2:op_io();
3:last_cycle(); 3:last_cycle();
regs.p = op_readstack(); regs.p = op_readstack();
regs.acc_8b = (regs.e || regs.p.m); if(regs.e)regs.p |= 0x30;
regs.idx_8b = (regs.e || regs.p.x); if(regs.p.x) {
if(regs.idx_8b) {
regs.x.h = 0x00; regs.x.h = 0x00;
regs.y.h = 0x00; regs.y.h = 0x00;
} }
@@ -256,9 +270,10 @@ plp(0x28) {
pea(0xf4) { pea(0xf4) {
1:aa.l = op_readpc(); 1:aa.l = op_readpc();
2:aa.h = op_readpc(); 2:aa.h = op_readpc();
3:op_writestack(aa.h); 3:op_writestackn(aa.h);
4:last_cycle(); 4:last_cycle();
op_writestack(aa.l); op_writestackn(aa.l);
if(regs.e)regs.s.h = 0x01;
} }
pei(0xd4) { pei(0xd4) {
@@ -266,9 +281,10 @@ pei(0xd4) {
2:op_io_cond2(); 2:op_io_cond2();
3:aa.l = op_readdp(dp); 3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1); 4:aa.h = op_readdp(dp + 1);
5:op_writestack(aa.h); 5:op_writestackn(aa.h);
6:last_cycle(); 6:last_cycle();
op_writestack(aa.l); op_writestackn(aa.l);
if(regs.e)regs.s.h = 0x01;
} }
per(0x62) { per(0x62) {
@@ -276,7 +292,8 @@ per(0x62) {
2:aa.h = op_readpc(); 2:aa.h = op_readpc();
3:op_io(); 3:op_io();
rd.w = regs.pc.d + (int16)aa.w; rd.w = regs.pc.d + (int16)aa.w;
4:op_writestack(rd.h); 4:op_writestackn(rd.h);
5:last_cycle(); 5:last_cycle();
op_writestack(rd.l); op_writestackn(rd.l);
if(regs.e)regs.s.h = 0x01;
} }

View File

@@ -18,7 +18,7 @@ case 0xeb: {
regs.a.l ^= regs.a.h; regs.a.l ^= regs.a.h;
regs.a.h ^= regs.a.l; regs.a.h ^= regs.a.l;
regs.a.l ^= regs.a.h; regs.a.l ^= regs.a.h;
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} break; } break;
@@ -30,10 +30,12 @@ case 0x54: {
rd.l = op_readlong((sp << 16) | regs.x.w); rd.l = op_readlong((sp << 16) | regs.x.w);
op_writelong((dp << 16) | regs.y.w, rd.l); op_writelong((dp << 16) | regs.y.w, rd.l);
op_io(); op_io();
if(regs.idx_8b) { if(regs.p.x) {
regs.x.l ++; regs.y.l ++; regs.x.l ++;
regs.y.l ++;
} else { } else {
regs.x.w ++; regs.y.w ++; regs.x.w ++;
regs.y.w ++;
} }
last_cycle(); last_cycle();
op_io(); op_io();
@@ -48,10 +50,12 @@ case 0x44: {
rd.l = op_readlong((sp << 16) | regs.x.w); rd.l = op_readlong((sp << 16) | regs.x.w);
op_writelong((dp << 16) | regs.y.w, rd.l); op_writelong((dp << 16) | regs.y.w, rd.l);
op_io(); op_io();
if(regs.idx_8b) { if(regs.p.x) {
regs.x.l --; regs.y.l --; regs.x.l --;
regs.y.l --;
} else { } else {
regs.x.w --; regs.y.w --; regs.x.w --;
regs.y.w --;
} }
last_cycle(); last_cycle();
op_io(); op_io();
@@ -94,10 +98,7 @@ case 0x02: {
case 0xdb: { case 0xdb: {
op_io(); op_io();
last_cycle(); last_cycle();
while(1) { while(1) { op_io(); }
op_io();
co_return();
}
} break; } break;
//wai //wai
@@ -109,7 +110,6 @@ case 0xcb: {
while(event.wai) { while(event.wai) {
last_cycle(); last_cycle();
op_io(); op_io();
co_return();
} }
} break; } break;
@@ -117,13 +117,14 @@ case 0xcb: {
case 0xfb: { case 0xfb: {
last_cycle(); last_cycle();
op_io(); op_io();
bool c = regs.p.c; bool carry = regs.p.c;
regs.p.c = regs.e; regs.p.c = regs.e;
regs.e = c; regs.e = carry;
if(regs.e)regs.s.h = 0x01; if(regs.e) {
regs.acc_8b = (regs.e || regs.p.m); regs.p |= 0x30;
regs.idx_8b = (regs.e || regs.p.x); regs.s.h = 0x01;
if(regs.idx_8b) { }
if(regs.p.x) {
regs.x.h = 0x00; regs.x.h = 0x00;
regs.y.h = 0x00; regs.y.h = 0x00;
} }
@@ -184,9 +185,8 @@ case 0xc2: {
last_cycle(); last_cycle();
op_io(); op_io();
regs.p &=~ rd.l; regs.p &=~ rd.l;
regs.acc_8b = (regs.e || regs.p.m); if(regs.e)regs.p |= 0x30;
regs.idx_8b = (regs.e || regs.p.x); if(regs.p.x) {
if(regs.idx_8b) {
regs.x.h = 0x00; regs.x.h = 0x00;
regs.y.h = 0x00; regs.y.h = 0x00;
} }
@@ -198,9 +198,8 @@ case 0xe2: {
last_cycle(); last_cycle();
op_io(); op_io();
regs.p |= rd.l; regs.p |= rd.l;
regs.acc_8b = (regs.e || regs.p.m); if(regs.e)regs.p |= 0x30;
regs.idx_8b = (regs.e || regs.p.x); if(regs.p.x) {
if(regs.idx_8b) {
regs.x.h = 0x00; regs.x.h = 0x00;
regs.y.h = 0x00; regs.y.h = 0x00;
} }
@@ -210,13 +209,13 @@ case 0xe2: {
case 0xaa: { case 0xaa: {
last_cycle(); last_cycle();
op_io(); op_io();
if(regs.idx_8b) { if(regs.p.x) {
regs.x.l = regs.a.l; regs.x.l = regs.a.l;
regs.p.n = bool(regs.x.l & 0x80); regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0); regs.p.z = (regs.x.l == 0);
} else { } else {
regs.x.w = regs.a.w; regs.x.w = regs.a.w;
regs.p.n = bool(regs.x.w & 0x8000); regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0); regs.p.z = (regs.x.w == 0);
} }
} break; } break;
@@ -225,13 +224,13 @@ case 0xaa: {
case 0xa8: { case 0xa8: {
last_cycle(); last_cycle();
op_io(); op_io();
if(regs.idx_8b) { if(regs.p.x) {
regs.y.l = regs.a.l; regs.y.l = regs.a.l;
regs.p.n = bool(regs.y.l & 0x80); regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0); regs.p.z = (regs.y.l == 0);
} else { } else {
regs.y.w = regs.a.w; regs.y.w = regs.a.w;
regs.p.n = bool(regs.y.w & 0x8000); regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0); regs.p.z = (regs.y.w == 0);
} }
} break; } break;
@@ -240,13 +239,13 @@ case 0xa8: {
case 0x8a: { case 0x8a: {
last_cycle(); last_cycle();
op_io(); op_io();
if(regs.acc_8b) { if(regs.p.m) {
regs.a.l = regs.x.l; regs.a.l = regs.x.l;
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} else { } else {
regs.a.w = regs.x.w; regs.a.w = regs.x.w;
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
} break; } break;
@@ -255,13 +254,13 @@ case 0x8a: {
case 0x9b: { case 0x9b: {
last_cycle(); last_cycle();
op_io(); op_io();
if(regs.idx_8b) { if(regs.p.x) {
regs.y.l = regs.x.l; regs.y.l = regs.x.l;
regs.p.n = bool(regs.y.l & 0x80); regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0); regs.p.z = (regs.y.l == 0);
} else { } else {
regs.y.w = regs.x.w; regs.y.w = regs.x.w;
regs.p.n = bool(regs.y.w & 0x8000); regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0); regs.p.z = (regs.y.w == 0);
} }
} break; } break;
@@ -270,13 +269,13 @@ case 0x9b: {
case 0x98: { case 0x98: {
last_cycle(); last_cycle();
op_io(); op_io();
if(regs.acc_8b) { if(regs.p.m) {
regs.a.l = regs.y.l; regs.a.l = regs.y.l;
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} else { } else {
regs.a.w = regs.y.w; regs.a.w = regs.y.w;
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
} break; } break;
@@ -285,13 +284,13 @@ case 0x98: {
case 0xbb: { case 0xbb: {
last_cycle(); last_cycle();
op_io(); op_io();
if(regs.idx_8b) { if(regs.p.x) {
regs.x.l = regs.y.l; regs.x.l = regs.y.l;
regs.p.n = bool(regs.x.l & 0x80); regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0); regs.p.z = (regs.x.l == 0);
} else { } else {
regs.x.w = regs.y.w; regs.x.w = regs.y.w;
regs.p.n = bool(regs.x.w & 0x8000); regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0); regs.p.z = (regs.x.w == 0);
} }
} break; } break;
@@ -301,7 +300,7 @@ case 0x5b: {
last_cycle(); last_cycle();
op_io(); op_io();
regs.d.w = regs.a.w; regs.d.w = regs.a.w;
regs.p.n = bool(regs.d.w & 0x8000); regs.p.n = !!(regs.d.w & 0x8000);
regs.p.z = (regs.d.w == 0); regs.p.z = (regs.d.w == 0);
} break; } break;
@@ -318,7 +317,7 @@ case 0x7b: {
last_cycle(); last_cycle();
op_io(); op_io();
regs.a.w = regs.d.w; regs.a.w = regs.d.w;
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} break; } break;
@@ -328,10 +327,10 @@ case 0x3b: {
op_io(); op_io();
regs.a.w = regs.s.w; regs.a.w = regs.s.w;
if(regs.e) { if(regs.e) {
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} else { } else {
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
} break; } break;
@@ -340,13 +339,13 @@ case 0x3b: {
case 0xba: { case 0xba: {
last_cycle(); last_cycle();
op_io(); op_io();
if(regs.idx_8b) { if(regs.p.x) {
regs.x.l = regs.s.l; regs.x.l = regs.s.l;
regs.p.n = bool(regs.x.l & 0x80); regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0); regs.p.z = (regs.x.l == 0);
} else { } else {
regs.x.w = regs.s.w; regs.x.w = regs.s.w;
regs.p.n = bool(regs.x.w & 0x8000); regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0); regs.p.z = (regs.x.w == 0);
} }
} break; } break;
@@ -365,7 +364,7 @@ case 0x9a: {
//pha //pha
case 0x48: { case 0x48: {
op_io(); op_io();
if(!regs.acc_8b)op_writestack(regs.a.h); if(!regs.p.m)op_writestack(regs.a.h);
last_cycle(); last_cycle();
op_writestack(regs.a.l); op_writestack(regs.a.l);
} break; } break;
@@ -373,7 +372,7 @@ case 0x48: {
//phx //phx
case 0xda: { case 0xda: {
op_io(); op_io();
if(!regs.idx_8b)op_writestack(regs.x.h); if(!regs.p.x)op_writestack(regs.x.h);
last_cycle(); last_cycle();
op_writestack(regs.x.l); op_writestack(regs.x.l);
} break; } break;
@@ -381,7 +380,7 @@ case 0xda: {
//phy //phy
case 0x5a: { case 0x5a: {
op_io(); op_io();
if(!regs.idx_8b)op_writestack(regs.y.h); if(!regs.p.x)op_writestack(regs.y.h);
last_cycle(); last_cycle();
op_writestack(regs.y.l); op_writestack(regs.y.l);
} break; } break;
@@ -389,9 +388,10 @@ case 0x5a: {
//phd //phd
case 0x0b: { case 0x0b: {
op_io(); op_io();
if(!0)op_writestack(regs. d.h); op_writestackn(regs.d.h);
last_cycle(); last_cycle();
op_writestack(regs. d.l); op_writestackn(regs.d.l);
if(regs.e)regs.s.h = 0x01;
} break; } break;
//phb //phb
@@ -419,16 +419,16 @@ case 0x08: {
case 0x68: { case 0x68: {
op_io(); op_io();
op_io(); op_io();
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
regs.a.l = op_readstack(); regs.a.l = op_readstack();
if(regs.acc_8b) { if(regs.p.m) {
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
break; break;
} }
last_cycle(); last_cycle();
regs.a.h = op_readstack(); regs.a.h = op_readstack();
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} break; } break;
@@ -436,16 +436,16 @@ case 0x68: {
case 0xfa: { case 0xfa: {
op_io(); op_io();
op_io(); op_io();
if(regs.idx_8b)last_cycle(); if(regs.p.x)last_cycle();
regs.x.l = op_readstack(); regs.x.l = op_readstack();
if(regs.idx_8b) { if(regs.p.x) {
regs.p.n = bool(regs.x.l & 0x80); regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0); regs.p.z = (regs.x.l == 0);
break; break;
} }
last_cycle(); last_cycle();
regs.x.h = op_readstack(); regs.x.h = op_readstack();
regs.p.n = bool(regs.x.w & 0x8000); regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0); regs.p.z = (regs.x.w == 0);
} break; } break;
@@ -453,16 +453,16 @@ case 0xfa: {
case 0x7a: { case 0x7a: {
op_io(); op_io();
op_io(); op_io();
if(regs.idx_8b)last_cycle(); if(regs.p.x)last_cycle();
regs.y.l = op_readstack(); regs.y.l = op_readstack();
if(regs.idx_8b) { if(regs.p.x) {
regs.p.n = bool(regs.y.l & 0x80); regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0); regs.p.z = (regs.y.l == 0);
break; break;
} }
last_cycle(); last_cycle();
regs.y.h = op_readstack(); regs.y.h = op_readstack();
regs.p.n = bool(regs.y.w & 0x8000); regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0); regs.p.z = (regs.y.w == 0);
} break; } break;
@@ -470,17 +470,12 @@ case 0x7a: {
case 0x2b: { case 0x2b: {
op_io(); op_io();
op_io(); op_io();
if(0)last_cycle(); regs.d.l = op_readstackn();
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(); last_cycle();
regs. d.h = op_readstack(); regs.d.h = op_readstackn();
regs.p.n = bool(regs. d.w & 0x8000); regs.p.n = !!(regs.d.w & 0x8000);
regs.p.z = (regs. d.w == 0); regs.p.z = (regs.d.w == 0);
if(regs.e)regs.s.h = 0x01;
} break; } break;
//plb //plb
@@ -489,7 +484,7 @@ case 0xab: {
op_io(); op_io();
last_cycle(); last_cycle();
regs.db = op_readstack(); regs.db = op_readstack();
regs.p.n = bool(regs.db & 0x80); regs.p.n = !!(regs.db & 0x80);
regs.p.z = (regs.db == 0); regs.p.z = (regs.db == 0);
} break; } break;
@@ -499,9 +494,8 @@ case 0x28: {
op_io(); op_io();
last_cycle(); last_cycle();
regs.p = op_readstack(); regs.p = op_readstack();
regs.acc_8b = (regs.e || regs.p.m); if(regs.e)regs.p |= 0x30;
regs.idx_8b = (regs.e || regs.p.x); if(regs.p.x) {
if(regs.idx_8b) {
regs.x.h = 0x00; regs.x.h = 0x00;
regs.y.h = 0x00; regs.y.h = 0x00;
} }
@@ -511,9 +505,10 @@ case 0x28: {
case 0xf4: { case 0xf4: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
op_writestack(aa.h); op_writestackn(aa.h);
last_cycle(); last_cycle();
op_writestack(aa.l); op_writestackn(aa.l);
if(regs.e)regs.s.h = 0x01;
} break; } break;
//pei //pei
@@ -522,9 +517,10 @@ case 0xd4: {
op_io_cond2(); op_io_cond2();
aa.l = op_readdp(dp); aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1); aa.h = op_readdp(dp + 1);
op_writestack(aa.h); op_writestackn(aa.h);
last_cycle(); last_cycle();
op_writestack(aa.l); op_writestackn(aa.l);
if(regs.e)regs.s.h = 0x01;
} break; } break;
//per //per
@@ -533,8 +529,9 @@ case 0x62: {
aa.h = op_readpc(); aa.h = op_readpc();
op_io(); op_io();
rd.w = regs.pc.d + (int16)aa.w; rd.w = regs.pc.d + (int16)aa.w;
op_writestack(rd.h); op_writestackn(rd.h);
last_cycle(); last_cycle();
op_writestack(rd.l); op_writestackn(rd.l);
if(regs.e)regs.s.h = 0x01;
} break; } break;

View File

@@ -48,7 +48,7 @@ jmp_long(0x5c) {
2:rd.h = op_readpc(); 2:rd.h = op_readpc();
3:last_cycle(); 3:last_cycle();
rd.b = op_readpc(); rd.b = op_readpc();
regs.pc.d = uclip<24>(rd.d); regs.pc.d = rd.d & 0xffffff;
} }
jmp_iaddr(0x6c) { jmp_iaddr(0x6c) {
@@ -77,7 +77,7 @@ jmp_iladdr(0xdc) {
4:rd.h = op_readaddr(aa.w + 1); 4:rd.h = op_readaddr(aa.w + 1);
5:last_cycle(); 5:last_cycle();
rd.b = op_readaddr(aa.w + 2); rd.b = op_readaddr(aa.w + 2);
regs.pc.d = uclip<24>(rd.d); regs.pc.d = rd.d & 0xffffff;
} }
jsr_addr(0x20) { jsr_addr(0x20) {
@@ -94,35 +94,36 @@ jsr_addr(0x20) {
jsr_long(0x22) { jsr_long(0x22) {
1:aa.l = op_readpc(); 1:aa.l = op_readpc();
2:aa.h = op_readpc(); 2:aa.h = op_readpc();
3:op_writestack(regs.pc.b); 3:op_writestackn(regs.pc.b);
4:op_io(); 4:op_io();
5:aa.b = op_readpc(); 5:aa.b = op_readpc();
6:regs.pc.w--; 6:regs.pc.w--;
op_writestack(regs.pc.h); op_writestackn(regs.pc.h);
7:last_cycle(); 7:last_cycle();
op_writestack(regs.pc.l); op_writestackn(regs.pc.l);
regs.pc.d = uclip<24>(aa.d); regs.pc.d = aa.d & 0xffffff;
if(regs.e)regs.s.h = 0x01;
} }
jsr_iaddrx(0xfc) { jsr_iaddrx(0xfc) {
1:aa.l = op_readpc(); 1:aa.l = op_readpc();
2:op_writestack(regs.pc.h); 2:op_writestackn(regs.pc.h);
3:op_writestack(regs.pc.l); 3:op_writestackn(regs.pc.l);
4:aa.h = op_readpc(); 4:aa.h = op_readpc();
5:op_io(); 5:op_io();
6:rd.l = op_readpbr(aa.w + regs.x.w); 6:rd.l = op_readpbr(aa.w + regs.x.w);
7:last_cycle(); 7:last_cycle();
rd.h = op_readpbr(aa.w + regs.x.w + 1); rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w; regs.pc.w = rd.w;
if(regs.e)regs.s.h = 0x01;
} }
rti(0x40) { rti(0x40) {
1:op_io(); 1:op_io();
2:op_io(); 2:op_io();
3:regs.p = op_readstack(); 3:regs.p = op_readstack();
regs.acc_8b = (regs.e || regs.p.m); if(regs.e)regs.p |= 0x30;
regs.idx_8b = (regs.e || regs.p.x); if(regs.p.x) {
if(regs.idx_8b) {
regs.x.h = 0x00; regs.x.h = 0x00;
regs.y.h = 0x00; regs.y.h = 0x00;
} }
@@ -135,7 +136,7 @@ rti(0x40) {
} }
6:last_cycle(); 6:last_cycle();
rd.b = op_readstack(); rd.b = op_readstack();
regs.pc.d = uclip<24>(rd.d); regs.pc.d = rd.d & 0xffffff;
} }
rts(0x60) { rts(0x60) {
@@ -152,10 +153,11 @@ rts(0x60) {
rtl(0x6b) { rtl(0x6b) {
1:op_io(); 1:op_io();
2:op_io(); 2:op_io();
3:rd.l = op_readstack(); 3:rd.l = op_readstackn();
4:rd.h = op_readstack(); 4:rd.h = op_readstackn();
5:last_cycle(); 5:last_cycle();
rd.b = op_readstack(); rd.b = op_readstackn();
regs.pc.d = uclip<24>(rd.d); regs.pc.d = rd.d & 0xffffff;
regs.pc.w++; regs.pc.w++;
if(regs.e)regs.s.h = 0x01;
} }

View File

@@ -151,7 +151,7 @@ case 0x5c: {
rd.h = op_readpc(); rd.h = op_readpc();
last_cycle(); last_cycle();
rd.b = op_readpc(); rd.b = op_readpc();
regs.pc.d = uclip<24>(rd.d); regs.pc.d = rd.d & 0xffffff;
} break; } break;
//jmp_iaddr //jmp_iaddr
@@ -183,7 +183,7 @@ case 0xdc: {
rd.h = op_readaddr(aa.w + 1); rd.h = op_readaddr(aa.w + 1);
last_cycle(); last_cycle();
rd.b = op_readaddr(aa.w + 2); rd.b = op_readaddr(aa.w + 2);
regs.pc.d = uclip<24>(rd.d); regs.pc.d = rd.d & 0xffffff;
} break; } break;
//jsr_addr //jsr_addr
@@ -202,27 +202,29 @@ case 0x20: {
case 0x22: { case 0x22: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
op_writestack(regs.pc.b); op_writestackn(regs.pc.b);
op_io(); op_io();
aa.b = op_readpc(); aa.b = op_readpc();
regs.pc.w--; regs.pc.w--;
op_writestack(regs.pc.h); op_writestackn(regs.pc.h);
last_cycle(); last_cycle();
op_writestack(regs.pc.l); op_writestackn(regs.pc.l);
regs.pc.d = uclip<24>(aa.d); regs.pc.d = aa.d & 0xffffff;
if(regs.e)regs.s.h = 0x01;
} break; } break;
//jsr_iaddrx //jsr_iaddrx
case 0xfc: { case 0xfc: {
aa.l = op_readpc(); aa.l = op_readpc();
op_writestack(regs.pc.h); op_writestackn(regs.pc.h);
op_writestack(regs.pc.l); op_writestackn(regs.pc.l);
aa.h = op_readpc(); aa.h = op_readpc();
op_io(); op_io();
rd.l = op_readpbr(aa.w + regs.x.w); rd.l = op_readpbr(aa.w + regs.x.w);
last_cycle(); last_cycle();
rd.h = op_readpbr(aa.w + regs.x.w + 1); rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w; regs.pc.w = rd.w;
if(regs.e)regs.s.h = 0x01;
} break; } break;
//rti //rti
@@ -230,9 +232,8 @@ case 0x40: {
op_io(); op_io();
op_io(); op_io();
regs.p = op_readstack(); regs.p = op_readstack();
regs.acc_8b = (regs.e || regs.p.m); if(regs.e)regs.p |= 0x30;
regs.idx_8b = (regs.e || regs.p.x); if(regs.p.x) {
if(regs.idx_8b) {
regs.x.h = 0x00; regs.x.h = 0x00;
regs.y.h = 0x00; regs.y.h = 0x00;
} }
@@ -245,7 +246,7 @@ case 0x40: {
} }
last_cycle(); last_cycle();
rd.b = op_readstack(); rd.b = op_readstack();
regs.pc.d = uclip<24>(rd.d); regs.pc.d = rd.d & 0xffffff;
} break; } break;
//rts //rts
@@ -264,11 +265,12 @@ case 0x60: {
case 0x6b: { case 0x6b: {
op_io(); op_io();
op_io(); op_io();
rd.l = op_readstack(); rd.l = op_readstackn();
rd.h = op_readstack(); rd.h = op_readstackn();
last_cycle(); last_cycle();
rd.b = op_readstack(); rd.b = op_readstackn();
regs.pc.d = uclip<24>(rd.d); regs.pc.d = rd.d & 0xffffff;
regs.pc.w++; regs.pc.w++;
if(regs.e)regs.s.h = 0x01;
} break; } break;

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,31 +1,31 @@
inc(0x1a, regs.acc_8b, a), inc(0x1a, regs.p.m, a),
inx(0xe8, regs.idx_8b, x), inx(0xe8, regs.p.x, x),
iny(0xc8, regs.idx_8b, y) { iny(0xc8, regs.p.x, y) {
1:last_cycle(); 1:last_cycle();
op_io(); op_io();
if($1) { if($1) {
regs.$2.l++; regs.$2.l++;
regs.p.n = bool(regs.$2.l & 0x80); regs.p.n = !!(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0); regs.p.z = (regs.$2.l == 0);
} else { } else {
regs.$2.w++; regs.$2.w++;
regs.p.n = bool(regs.$2.w & 0x8000); regs.p.n = !!(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0); regs.p.z = (regs.$2.w == 0);
} }
} }
dec(0x3a, regs.acc_8b, a), dec(0x3a, regs.p.m, a),
dex(0xca, regs.idx_8b, x), dex(0xca, regs.p.x, x),
dey(0x88, regs.idx_8b, y) { dey(0x88, regs.p.x, y) {
1:last_cycle(); 1:last_cycle();
op_io(); op_io();
if($1) { if($1) {
regs.$2.l--; regs.$2.l--;
regs.p.n = bool(regs.$2.l & 0x80); regs.p.n = !!(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0); regs.p.z = (regs.$2.l == 0);
} else { } else {
regs.$2.w--; regs.$2.w--;
regs.p.n = bool(regs.$2.w & 0x8000); regs.p.n = !!(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0); regs.p.z = (regs.$2.w == 0);
} }
} }
@@ -33,15 +33,15 @@ dey(0x88, regs.idx_8b, y) {
asl(0x0a) { asl(0x0a) {
1:last_cycle(); 1:last_cycle();
op_io(); op_io();
if(regs.acc_8b) { if(regs.p.m) {
regs.p.c = bool(regs.a.l & 0x80); regs.p.c = !!(regs.a.l & 0x80);
regs.a.l <<= 1; regs.a.l <<= 1;
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} else { } else {
regs.p.c = bool(regs.a.w & 0x8000); regs.p.c = !!(regs.a.w & 0x8000);
regs.a.w <<= 1; regs.a.w <<= 1;
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
} }
@@ -49,15 +49,15 @@ asl(0x0a) {
lsr(0x4a) { lsr(0x4a) {
1:last_cycle(); 1:last_cycle();
op_io(); op_io();
if(regs.acc_8b) { if(regs.p.m) {
regs.p.c = regs.a.l & 1; regs.p.c = regs.a.l & 1;
regs.a.l >>= 1; regs.a.l >>= 1;
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} else { } else {
regs.p.c = regs.a.w & 1; regs.p.c = regs.a.w & 1;
regs.a.w >>= 1; regs.a.w >>= 1;
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
} }
@@ -66,17 +66,17 @@ rol(0x2a) {
1:last_cycle(); 1:last_cycle();
op_io(); op_io();
uint16 c = regs.p.c; uint16 c = regs.p.c;
if(regs.acc_8b) { if(regs.p.m) {
regs.p.c = bool(regs.a.l & 0x80); regs.p.c = !!(regs.a.l & 0x80);
regs.a.l <<= 1; regs.a.l <<= 1;
regs.a.l |= c; regs.a.l |= c;
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} else { } else {
regs.p.c = bool(regs.a.w & 0x8000); regs.p.c = !!(regs.a.w & 0x8000);
regs.a.w <<= 1; regs.a.w <<= 1;
regs.a.w |= c; regs.a.w |= c;
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
} }
@@ -85,19 +85,19 @@ ror(0x6a) {
1:last_cycle(); 1:last_cycle();
op_io(); op_io();
uint16 c; uint16 c;
if(regs.acc_8b) { if(regs.p.m) {
c = (regs.p.c)?0x80:0; c = (regs.p.c)?0x80:0;
regs.p.c = regs.a.l & 1; regs.p.c = regs.a.l & 1;
regs.a.l >>= 1; regs.a.l >>= 1;
regs.a.l |= c; regs.a.l |= c;
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} else { } else {
c = (regs.p.c)?0x8000:0; c = (regs.p.c)?0x8000:0;
regs.p.c = regs.a.w & 1; regs.p.c = regs.a.w & 1;
regs.a.w >>= 1; regs.a.w >>= 1;
regs.a.w |= c; regs.a.w |= c;
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
} }
@@ -113,9 +113,9 @@ tsb_addr(0x0c, tsb) {
1:aa.l = op_readpc(); 1:aa.l = op_readpc();
2:aa.h = op_readpc(); 2:aa.h = op_readpc();
3:rd.l = op_readdbr(aa.w); 3:rd.l = op_readdbr(aa.w);
4:if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1); 4:if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
5:op_io(); 5:op_io();
if(regs.acc_8b) { op_$1_b(); } if(regs.p.m) { op_$1_b(); }
else { op_$1_w(); else { op_$1_w();
6:op_writedbr(aa.w + 1, rd.h); } 6:op_writedbr(aa.w + 1, rd.h); }
7:last_cycle(); 7:last_cycle();
@@ -132,9 +132,9 @@ ror_addrx(0x7e, ror) {
2:aa.h = op_readpc(); 2:aa.h = op_readpc();
3:op_io(); 3:op_io();
4:rd.l = op_readdbr(aa.w + regs.x.w); 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); 5:if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1);
6:op_io(); 6:op_io();
if(regs.acc_8b) { op_$1_b(); } if(regs.p.m) { op_$1_b(); }
else { op_$1_w(); else { op_$1_w();
7:op_writedbr(aa.w + regs.x.w + 1, rd.h); } 7:op_writedbr(aa.w + regs.x.w + 1, rd.h); }
8:last_cycle(); 8:last_cycle();
@@ -152,9 +152,9 @@ tsb_dp(0x04, tsb) {
1:dp = op_readpc(); 1:dp = op_readpc();
2:op_io_cond2(); 2:op_io_cond2();
3:rd.l = op_readdp(dp); 3:rd.l = op_readdp(dp);
4:if(!regs.acc_8b)rd.h = op_readdp(dp + 1); 4:if(!regs.p.m)rd.h = op_readdp(dp + 1);
5:op_io(); 5:op_io();
if(regs.acc_8b) { op_$1_b(); } if(regs.p.m) { op_$1_b(); }
else { op_$1_w(); else { op_$1_w();
6:op_writedp(dp + 1, rd.h); } 6:op_writedp(dp + 1, rd.h); }
7:last_cycle(); 7:last_cycle();
@@ -171,9 +171,9 @@ ror_dpx(0x76, ror) {
2:op_io_cond2(); 2:op_io_cond2();
3:op_io(); 3:op_io();
4:rd.l = op_readdp(dp + regs.x.w); 4:rd.l = op_readdp(dp + regs.x.w);
5:if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1); 5:if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1);
6:op_io(); 6:op_io();
if(regs.acc_8b) { op_$1_b(); } if(regs.p.m) { op_$1_b(); }
else { op_$1_w(); else { op_$1_w();
7:op_writedp(dp + regs.x.w + 1, rd.h); } 7:op_writedp(dp + regs.x.w + 1, rd.h); }
8:last_cycle(); 8:last_cycle();

View File

@@ -2,13 +2,13 @@
case 0x1a: { case 0x1a: {
last_cycle(); last_cycle();
op_io(); op_io();
if(regs.acc_8b) { if(regs.p.m) {
regs.a.l++; regs.a.l++;
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} else { } else {
regs.a.w++; regs.a.w++;
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
} break; } break;
@@ -17,13 +17,13 @@ case 0x1a: {
case 0xe8: { case 0xe8: {
last_cycle(); last_cycle();
op_io(); op_io();
if(regs.idx_8b) { if(regs.p.x) {
regs.x.l++; regs.x.l++;
regs.p.n = bool(regs.x.l & 0x80); regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0); regs.p.z = (regs.x.l == 0);
} else { } else {
regs.x.w++; regs.x.w++;
regs.p.n = bool(regs.x.w & 0x8000); regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0); regs.p.z = (regs.x.w == 0);
} }
} break; } break;
@@ -32,13 +32,13 @@ case 0xe8: {
case 0xc8: { case 0xc8: {
last_cycle(); last_cycle();
op_io(); op_io();
if(regs.idx_8b) { if(regs.p.x) {
regs.y.l++; regs.y.l++;
regs.p.n = bool(regs.y.l & 0x80); regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0); regs.p.z = (regs.y.l == 0);
} else { } else {
regs.y.w++; regs.y.w++;
regs.p.n = bool(regs.y.w & 0x8000); regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0); regs.p.z = (regs.y.w == 0);
} }
} break; } break;
@@ -47,13 +47,13 @@ case 0xc8: {
case 0x3a: { case 0x3a: {
last_cycle(); last_cycle();
op_io(); op_io();
if(regs.acc_8b) { if(regs.p.m) {
regs.a.l--; regs.a.l--;
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} else { } else {
regs.a.w--; regs.a.w--;
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
} break; } break;
@@ -62,13 +62,13 @@ case 0x3a: {
case 0xca: { case 0xca: {
last_cycle(); last_cycle();
op_io(); op_io();
if(regs.idx_8b) { if(regs.p.x) {
regs.x.l--; regs.x.l--;
regs.p.n = bool(regs.x.l & 0x80); regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0); regs.p.z = (regs.x.l == 0);
} else { } else {
regs.x.w--; regs.x.w--;
regs.p.n = bool(regs.x.w & 0x8000); regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0); regs.p.z = (regs.x.w == 0);
} }
} break; } break;
@@ -77,13 +77,13 @@ case 0xca: {
case 0x88: { case 0x88: {
last_cycle(); last_cycle();
op_io(); op_io();
if(regs.idx_8b) { if(regs.p.x) {
regs.y.l--; regs.y.l--;
regs.p.n = bool(regs.y.l & 0x80); regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0); regs.p.z = (regs.y.l == 0);
} else { } else {
regs.y.w--; regs.y.w--;
regs.p.n = bool(regs.y.w & 0x8000); regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0); regs.p.z = (regs.y.w == 0);
} }
} break; } break;
@@ -92,15 +92,15 @@ case 0x88: {
case 0x0a: { case 0x0a: {
last_cycle(); last_cycle();
op_io(); op_io();
if(regs.acc_8b) { if(regs.p.m) {
regs.p.c = bool(regs.a.l & 0x80); regs.p.c = !!(regs.a.l & 0x80);
regs.a.l <<= 1; regs.a.l <<= 1;
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} else { } else {
regs.p.c = bool(regs.a.w & 0x8000); regs.p.c = !!(regs.a.w & 0x8000);
regs.a.w <<= 1; regs.a.w <<= 1;
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
} break; } break;
@@ -109,15 +109,15 @@ case 0x0a: {
case 0x4a: { case 0x4a: {
last_cycle(); last_cycle();
op_io(); op_io();
if(regs.acc_8b) { if(regs.p.m) {
regs.p.c = regs.a.l & 1; regs.p.c = regs.a.l & 1;
regs.a.l >>= 1; regs.a.l >>= 1;
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} else { } else {
regs.p.c = regs.a.w & 1; regs.p.c = regs.a.w & 1;
regs.a.w >>= 1; regs.a.w >>= 1;
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
} break; } break;
@@ -127,17 +127,17 @@ case 0x2a: {
last_cycle(); last_cycle();
op_io(); op_io();
uint16 c = regs.p.c; uint16 c = regs.p.c;
if(regs.acc_8b) { if(regs.p.m) {
regs.p.c = bool(regs.a.l & 0x80); regs.p.c = !!(regs.a.l & 0x80);
regs.a.l <<= 1; regs.a.l <<= 1;
regs.a.l |= c; regs.a.l |= c;
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} else { } else {
regs.p.c = bool(regs.a.w & 0x8000); regs.p.c = !!(regs.a.w & 0x8000);
regs.a.w <<= 1; regs.a.w <<= 1;
regs.a.w |= c; regs.a.w |= c;
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
} break; } break;
@@ -147,19 +147,19 @@ case 0x6a: {
last_cycle(); last_cycle();
op_io(); op_io();
uint16 c; uint16 c;
if(regs.acc_8b) { if(regs.p.m) {
c = (regs.p.c)?0x80:0; c = (regs.p.c)?0x80:0;
regs.p.c = regs.a.l & 1; regs.p.c = regs.a.l & 1;
regs.a.l >>= 1; regs.a.l >>= 1;
regs.a.l |= c; regs.a.l |= c;
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} else { } else {
c = (regs.p.c)?0x8000:0; c = (regs.p.c)?0x8000:0;
regs.p.c = regs.a.w & 1; regs.p.c = regs.a.w & 1;
regs.a.w >>= 1; regs.a.w >>= 1;
regs.a.w |= c; regs.a.w |= c;
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
} break; } break;
@@ -169,9 +169,9 @@ case 0xee: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
rd.l = op_readdbr(aa.w); rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1); if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_inc_b(); } if(regs.p.m) { op_inc_b(); }
else { op_inc_w(); else { op_inc_w();
op_writedbr(aa.w + 1, rd.h); } op_writedbr(aa.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -183,9 +183,9 @@ case 0xce: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
rd.l = op_readdbr(aa.w); rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1); if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_dec_b(); } if(regs.p.m) { op_dec_b(); }
else { op_dec_w(); else { op_dec_w();
op_writedbr(aa.w + 1, rd.h); } op_writedbr(aa.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -197,9 +197,9 @@ case 0x0e: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
rd.l = op_readdbr(aa.w); rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1); if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_asl_b(); } if(regs.p.m) { op_asl_b(); }
else { op_asl_w(); else { op_asl_w();
op_writedbr(aa.w + 1, rd.h); } op_writedbr(aa.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -211,9 +211,9 @@ case 0x4e: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
rd.l = op_readdbr(aa.w); rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1); if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_lsr_b(); } if(regs.p.m) { op_lsr_b(); }
else { op_lsr_w(); else { op_lsr_w();
op_writedbr(aa.w + 1, rd.h); } op_writedbr(aa.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -225,9 +225,9 @@ case 0x2e: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
rd.l = op_readdbr(aa.w); rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1); if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_rol_b(); } if(regs.p.m) { op_rol_b(); }
else { op_rol_w(); else { op_rol_w();
op_writedbr(aa.w + 1, rd.h); } op_writedbr(aa.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -239,9 +239,9 @@ case 0x6e: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
rd.l = op_readdbr(aa.w); rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1); if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_ror_b(); } if(regs.p.m) { op_ror_b(); }
else { op_ror_w(); else { op_ror_w();
op_writedbr(aa.w + 1, rd.h); } op_writedbr(aa.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -253,9 +253,9 @@ case 0x1c: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
rd.l = op_readdbr(aa.w); rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1); if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_trb_b(); } if(regs.p.m) { op_trb_b(); }
else { op_trb_w(); else { op_trb_w();
op_writedbr(aa.w + 1, rd.h); } op_writedbr(aa.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -267,9 +267,9 @@ case 0x0c: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
rd.l = op_readdbr(aa.w); rd.l = op_readdbr(aa.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1); if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_tsb_b(); } if(regs.p.m) { op_tsb_b(); }
else { op_tsb_w(); else { op_tsb_w();
op_writedbr(aa.w + 1, rd.h); } op_writedbr(aa.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -282,9 +282,9 @@ case 0xfe: {
aa.h = op_readpc(); aa.h = op_readpc();
op_io(); op_io();
rd.l = op_readdbr(aa.w + regs.x.w); rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1); if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_inc_b(); } if(regs.p.m) { op_inc_b(); }
else { op_inc_w(); else { op_inc_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); } op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -297,9 +297,9 @@ case 0xde: {
aa.h = op_readpc(); aa.h = op_readpc();
op_io(); op_io();
rd.l = op_readdbr(aa.w + regs.x.w); rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1); if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_dec_b(); } if(regs.p.m) { op_dec_b(); }
else { op_dec_w(); else { op_dec_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); } op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -312,9 +312,9 @@ case 0x1e: {
aa.h = op_readpc(); aa.h = op_readpc();
op_io(); op_io();
rd.l = op_readdbr(aa.w + regs.x.w); rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1); if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_asl_b(); } if(regs.p.m) { op_asl_b(); }
else { op_asl_w(); else { op_asl_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); } op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -327,9 +327,9 @@ case 0x5e: {
aa.h = op_readpc(); aa.h = op_readpc();
op_io(); op_io();
rd.l = op_readdbr(aa.w + regs.x.w); rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1); if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_lsr_b(); } if(regs.p.m) { op_lsr_b(); }
else { op_lsr_w(); else { op_lsr_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); } op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -342,9 +342,9 @@ case 0x3e: {
aa.h = op_readpc(); aa.h = op_readpc();
op_io(); op_io();
rd.l = op_readdbr(aa.w + regs.x.w); rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1); if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_rol_b(); } if(regs.p.m) { op_rol_b(); }
else { op_rol_w(); else { op_rol_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); } op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -357,9 +357,9 @@ case 0x7e: {
aa.h = op_readpc(); aa.h = op_readpc();
op_io(); op_io();
rd.l = op_readdbr(aa.w + regs.x.w); rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1); if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_ror_b(); } if(regs.p.m) { op_ror_b(); }
else { op_ror_w(); else { op_ror_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); } op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -371,9 +371,9 @@ case 0xe6: {
dp = op_readpc(); dp = op_readpc();
op_io_cond2(); op_io_cond2();
rd.l = op_readdp(dp); rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1); if(!regs.p.m)rd.h = op_readdp(dp + 1);
op_io(); op_io();
if(regs.acc_8b) { op_inc_b(); } if(regs.p.m) { op_inc_b(); }
else { op_inc_w(); else { op_inc_w();
op_writedp(dp + 1, rd.h); } op_writedp(dp + 1, rd.h); }
last_cycle(); last_cycle();
@@ -385,9 +385,9 @@ case 0xc6: {
dp = op_readpc(); dp = op_readpc();
op_io_cond2(); op_io_cond2();
rd.l = op_readdp(dp); rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1); if(!regs.p.m)rd.h = op_readdp(dp + 1);
op_io(); op_io();
if(regs.acc_8b) { op_dec_b(); } if(regs.p.m) { op_dec_b(); }
else { op_dec_w(); else { op_dec_w();
op_writedp(dp + 1, rd.h); } op_writedp(dp + 1, rd.h); }
last_cycle(); last_cycle();
@@ -399,9 +399,9 @@ case 0x06: {
dp = op_readpc(); dp = op_readpc();
op_io_cond2(); op_io_cond2();
rd.l = op_readdp(dp); rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1); if(!regs.p.m)rd.h = op_readdp(dp + 1);
op_io(); op_io();
if(regs.acc_8b) { op_asl_b(); } if(regs.p.m) { op_asl_b(); }
else { op_asl_w(); else { op_asl_w();
op_writedp(dp + 1, rd.h); } op_writedp(dp + 1, rd.h); }
last_cycle(); last_cycle();
@@ -413,9 +413,9 @@ case 0x46: {
dp = op_readpc(); dp = op_readpc();
op_io_cond2(); op_io_cond2();
rd.l = op_readdp(dp); rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1); if(!regs.p.m)rd.h = op_readdp(dp + 1);
op_io(); op_io();
if(regs.acc_8b) { op_lsr_b(); } if(regs.p.m) { op_lsr_b(); }
else { op_lsr_w(); else { op_lsr_w();
op_writedp(dp + 1, rd.h); } op_writedp(dp + 1, rd.h); }
last_cycle(); last_cycle();
@@ -427,9 +427,9 @@ case 0x26: {
dp = op_readpc(); dp = op_readpc();
op_io_cond2(); op_io_cond2();
rd.l = op_readdp(dp); rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1); if(!regs.p.m)rd.h = op_readdp(dp + 1);
op_io(); op_io();
if(regs.acc_8b) { op_rol_b(); } if(regs.p.m) { op_rol_b(); }
else { op_rol_w(); else { op_rol_w();
op_writedp(dp + 1, rd.h); } op_writedp(dp + 1, rd.h); }
last_cycle(); last_cycle();
@@ -441,9 +441,9 @@ case 0x66: {
dp = op_readpc(); dp = op_readpc();
op_io_cond2(); op_io_cond2();
rd.l = op_readdp(dp); rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1); if(!regs.p.m)rd.h = op_readdp(dp + 1);
op_io(); op_io();
if(regs.acc_8b) { op_ror_b(); } if(regs.p.m) { op_ror_b(); }
else { op_ror_w(); else { op_ror_w();
op_writedp(dp + 1, rd.h); } op_writedp(dp + 1, rd.h); }
last_cycle(); last_cycle();
@@ -455,9 +455,9 @@ case 0x14: {
dp = op_readpc(); dp = op_readpc();
op_io_cond2(); op_io_cond2();
rd.l = op_readdp(dp); rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1); if(!regs.p.m)rd.h = op_readdp(dp + 1);
op_io(); op_io();
if(regs.acc_8b) { op_trb_b(); } if(regs.p.m) { op_trb_b(); }
else { op_trb_w(); else { op_trb_w();
op_writedp(dp + 1, rd.h); } op_writedp(dp + 1, rd.h); }
last_cycle(); last_cycle();
@@ -469,9 +469,9 @@ case 0x04: {
dp = op_readpc(); dp = op_readpc();
op_io_cond2(); op_io_cond2();
rd.l = op_readdp(dp); rd.l = op_readdp(dp);
if(!regs.acc_8b)rd.h = op_readdp(dp + 1); if(!regs.p.m)rd.h = op_readdp(dp + 1);
op_io(); op_io();
if(regs.acc_8b) { op_tsb_b(); } if(regs.p.m) { op_tsb_b(); }
else { op_tsb_w(); else { op_tsb_w();
op_writedp(dp + 1, rd.h); } op_writedp(dp + 1, rd.h); }
last_cycle(); last_cycle();
@@ -484,9 +484,9 @@ case 0xf6: {
op_io_cond2(); op_io_cond2();
op_io(); op_io();
rd.l = op_readdp(dp + regs.x.w); rd.l = op_readdp(dp + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1); if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_inc_b(); } if(regs.p.m) { op_inc_b(); }
else { op_inc_w(); else { op_inc_w();
op_writedp(dp + regs.x.w + 1, rd.h); } op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -499,9 +499,9 @@ case 0xd6: {
op_io_cond2(); op_io_cond2();
op_io(); op_io();
rd.l = op_readdp(dp + regs.x.w); rd.l = op_readdp(dp + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1); if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_dec_b(); } if(regs.p.m) { op_dec_b(); }
else { op_dec_w(); else { op_dec_w();
op_writedp(dp + regs.x.w + 1, rd.h); } op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -514,9 +514,9 @@ case 0x16: {
op_io_cond2(); op_io_cond2();
op_io(); op_io();
rd.l = op_readdp(dp + regs.x.w); rd.l = op_readdp(dp + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1); if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_asl_b(); } if(regs.p.m) { op_asl_b(); }
else { op_asl_w(); else { op_asl_w();
op_writedp(dp + regs.x.w + 1, rd.h); } op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -529,9 +529,9 @@ case 0x56: {
op_io_cond2(); op_io_cond2();
op_io(); op_io();
rd.l = op_readdp(dp + regs.x.w); rd.l = op_readdp(dp + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1); if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_lsr_b(); } if(regs.p.m) { op_lsr_b(); }
else { op_lsr_w(); else { op_lsr_w();
op_writedp(dp + regs.x.w + 1, rd.h); } op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -544,9 +544,9 @@ case 0x36: {
op_io_cond2(); op_io_cond2();
op_io(); op_io();
rd.l = op_readdp(dp + regs.x.w); rd.l = op_readdp(dp + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1); if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_rol_b(); } if(regs.p.m) { op_rol_b(); }
else { op_rol_w(); else { op_rol_w();
op_writedp(dp + regs.x.w + 1, rd.h); } op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle(); last_cycle();
@@ -559,9 +559,9 @@ case 0x76: {
op_io_cond2(); op_io_cond2();
op_io(); op_io();
rd.l = op_readdp(dp + regs.x.w); rd.l = op_readdp(dp + regs.x.w);
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1); if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1);
op_io(); op_io();
if(regs.acc_8b) { op_ror_b(); } if(regs.p.m) { op_ror_b(); }
else { op_ror_w(); else { op_ror_w();
op_writedp(dp + regs.x.w + 1, rd.h); } op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle(); last_cycle();

View File

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

View File

@@ -2,9 +2,9 @@
case 0x8d: { case 0x8d: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
op_writedbr(aa.w, regs.a.w); op_writedbr(aa.w, regs.a.w);
if(regs.acc_8b)break; if(regs.p.m)break;
last_cycle(); last_cycle();
op_writedbr(aa.w + 1, regs.a.w >> 8); op_writedbr(aa.w + 1, regs.a.w >> 8);
} break; } break;
@@ -13,9 +13,9 @@ case 0x8d: {
case 0x8e: { case 0x8e: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
if(regs.idx_8b)last_cycle(); if(regs.p.x)last_cycle();
op_writedbr(aa.w, regs.x.w); op_writedbr(aa.w, regs.x.w);
if(regs.idx_8b)break; if(regs.p.x)break;
last_cycle(); last_cycle();
op_writedbr(aa.w + 1, regs.x.w >> 8); op_writedbr(aa.w + 1, regs.x.w >> 8);
} break; } break;
@@ -24,9 +24,9 @@ case 0x8e: {
case 0x8c: { case 0x8c: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
if(regs.idx_8b)last_cycle(); if(regs.p.x)last_cycle();
op_writedbr(aa.w, regs.y.w); op_writedbr(aa.w, regs.y.w);
if(regs.idx_8b)break; if(regs.p.x)break;
last_cycle(); last_cycle();
op_writedbr(aa.w + 1, regs.y.w >> 8); op_writedbr(aa.w + 1, regs.y.w >> 8);
} break; } break;
@@ -35,9 +35,9 @@ case 0x8c: {
case 0x9c: { case 0x9c: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
op_writedbr(aa.w, 0x0000); op_writedbr(aa.w, 0x0000);
if(regs.acc_8b)break; if(regs.p.m)break;
last_cycle(); last_cycle();
op_writedbr(aa.w + 1, 0x0000 >> 8); op_writedbr(aa.w + 1, 0x0000 >> 8);
} break; } break;
@@ -47,9 +47,9 @@ case 0x9d: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
op_io(); op_io();
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
op_writedbr(aa.w + regs.x.w, regs.a.w); op_writedbr(aa.w + regs.x.w, regs.a.w);
if(regs.acc_8b)break; if(regs.p.m)break;
last_cycle(); last_cycle();
op_writedbr(aa.w + regs.x.w + 1, regs.a.w >> 8); op_writedbr(aa.w + regs.x.w + 1, regs.a.w >> 8);
} break; } break;
@@ -59,9 +59,9 @@ case 0x9e: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
op_io(); op_io();
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
op_writedbr(aa.w + regs.x.w, 0x0000); op_writedbr(aa.w + regs.x.w, 0x0000);
if(regs.acc_8b)break; if(regs.p.m)break;
last_cycle(); last_cycle();
op_writedbr(aa.w + regs.x.w + 1, 0x0000 >> 8); op_writedbr(aa.w + regs.x.w + 1, 0x0000 >> 8);
} break; } break;
@@ -71,9 +71,9 @@ case 0x99: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
op_io(); op_io();
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l); op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)break; if(regs.p.m)break;
last_cycle(); last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h); op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
} break; } break;
@@ -83,9 +83,9 @@ case 0x8f: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
aa.b = op_readpc(); aa.b = op_readpc();
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
op_writelong(aa.d, regs.a.l); op_writelong(aa.d, regs.a.l);
if(regs.acc_8b)break; if(regs.p.m)break;
last_cycle(); last_cycle();
op_writelong(aa.d + 1, regs.a.h); op_writelong(aa.d + 1, regs.a.h);
} break; } break;
@@ -95,9 +95,9 @@ case 0x9f: {
aa.l = op_readpc(); aa.l = op_readpc();
aa.h = op_readpc(); aa.h = op_readpc();
aa.b = op_readpc(); aa.b = op_readpc();
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
op_writelong(aa.d + regs.x.w, regs.a.l); op_writelong(aa.d + regs.x.w, regs.a.l);
if(regs.acc_8b)break; if(regs.p.m)break;
last_cycle(); last_cycle();
op_writelong(aa.d + regs.x.w + 1, regs.a.h); op_writelong(aa.d + regs.x.w + 1, regs.a.h);
} break; } break;
@@ -106,9 +106,9 @@ case 0x9f: {
case 0x85: { case 0x85: {
dp = op_readpc(); dp = op_readpc();
op_io_cond2(); op_io_cond2();
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
op_writedp(dp, regs.a.w); op_writedp(dp, regs.a.w);
if(regs.acc_8b)break; if(regs.p.m)break;
last_cycle(); last_cycle();
op_writedp(dp + 1, regs.a.w >> 8); op_writedp(dp + 1, regs.a.w >> 8);
} break; } break;
@@ -117,9 +117,9 @@ case 0x85: {
case 0x86: { case 0x86: {
dp = op_readpc(); dp = op_readpc();
op_io_cond2(); op_io_cond2();
if(regs.idx_8b)last_cycle(); if(regs.p.x)last_cycle();
op_writedp(dp, regs.x.w); op_writedp(dp, regs.x.w);
if(regs.idx_8b)break; if(regs.p.x)break;
last_cycle(); last_cycle();
op_writedp(dp + 1, regs.x.w >> 8); op_writedp(dp + 1, regs.x.w >> 8);
} break; } break;
@@ -128,9 +128,9 @@ case 0x86: {
case 0x84: { case 0x84: {
dp = op_readpc(); dp = op_readpc();
op_io_cond2(); op_io_cond2();
if(regs.idx_8b)last_cycle(); if(regs.p.x)last_cycle();
op_writedp(dp, regs.y.w); op_writedp(dp, regs.y.w);
if(regs.idx_8b)break; if(regs.p.x)break;
last_cycle(); last_cycle();
op_writedp(dp + 1, regs.y.w >> 8); op_writedp(dp + 1, regs.y.w >> 8);
} break; } break;
@@ -139,9 +139,9 @@ case 0x84: {
case 0x64: { case 0x64: {
dp = op_readpc(); dp = op_readpc();
op_io_cond2(); op_io_cond2();
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
op_writedp(dp, 0x0000); op_writedp(dp, 0x0000);
if(regs.acc_8b)break; if(regs.p.m)break;
last_cycle(); last_cycle();
op_writedp(dp + 1, 0x0000 >> 8); op_writedp(dp + 1, 0x0000 >> 8);
} break; } break;
@@ -151,9 +151,9 @@ case 0x95: {
dp = op_readpc(); dp = op_readpc();
op_io_cond2(); op_io_cond2();
op_io(); op_io();
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
op_writedp(dp + regs.x.w, regs.a.w); op_writedp(dp + regs.x.w, regs.a.w);
if(regs.acc_8b)break; if(regs.p.m)break;
last_cycle(); last_cycle();
op_writedp(dp + regs.x.w + 1, regs.a.w >> 8); op_writedp(dp + regs.x.w + 1, regs.a.w >> 8);
} break; } break;
@@ -163,9 +163,9 @@ case 0x94: {
dp = op_readpc(); dp = op_readpc();
op_io_cond2(); op_io_cond2();
op_io(); op_io();
if(regs.idx_8b)last_cycle(); if(regs.p.x)last_cycle();
op_writedp(dp + regs.x.w, regs.y.w); op_writedp(dp + regs.x.w, regs.y.w);
if(regs.idx_8b)break; if(regs.p.x)break;
last_cycle(); last_cycle();
op_writedp(dp + regs.x.w + 1, regs.y.w >> 8); op_writedp(dp + regs.x.w + 1, regs.y.w >> 8);
} break; } break;
@@ -175,9 +175,9 @@ case 0x74: {
dp = op_readpc(); dp = op_readpc();
op_io_cond2(); op_io_cond2();
op_io(); op_io();
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
op_writedp(dp + regs.x.w, 0x0000); op_writedp(dp + regs.x.w, 0x0000);
if(regs.acc_8b)break; if(regs.p.m)break;
last_cycle(); last_cycle();
op_writedp(dp + regs.x.w + 1, 0x0000 >> 8); op_writedp(dp + regs.x.w + 1, 0x0000 >> 8);
} break; } break;
@@ -187,9 +187,9 @@ case 0x96: {
dp = op_readpc(); dp = op_readpc();
op_io_cond2(); op_io_cond2();
op_io(); op_io();
if(regs.idx_8b)last_cycle(); if(regs.p.x)last_cycle();
op_writedp(dp + regs.y.w, regs.x.l); op_writedp(dp + regs.y.w, regs.x.l);
if(regs.idx_8b)break; if(regs.p.x)break;
last_cycle(); last_cycle();
op_writedp(dp + regs.y.w + 1, regs.x.h); op_writedp(dp + regs.y.w + 1, regs.x.h);
} break; } break;
@@ -200,9 +200,9 @@ case 0x92: {
op_io_cond2(); op_io_cond2();
aa.l = op_readdp(dp); aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1); aa.h = op_readdp(dp + 1);
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
op_writedbr(aa.w, regs.a.l); op_writedbr(aa.w, regs.a.l);
if(regs.acc_8b)break; if(regs.p.m)break;
last_cycle(); last_cycle();
op_writedbr(aa.w + 1, regs.a.h); op_writedbr(aa.w + 1, regs.a.h);
} break; } break;
@@ -214,9 +214,9 @@ case 0x87: {
aa.l = op_readdp(dp); aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1); aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2); aa.b = op_readdp(dp + 2);
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
op_writelong(aa.d, regs.a.l); op_writelong(aa.d, regs.a.l);
if(regs.acc_8b)break; if(regs.p.m)break;
last_cycle(); last_cycle();
op_writelong(aa.d + 1, regs.a.h); op_writelong(aa.d + 1, regs.a.h);
} break; } break;
@@ -228,9 +228,9 @@ case 0x81: {
op_io(); op_io();
aa.l = op_readdp(dp + regs.x.w); aa.l = op_readdp(dp + regs.x.w);
aa.h = op_readdp(dp + regs.x.w + 1); aa.h = op_readdp(dp + regs.x.w + 1);
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
op_writedbr(aa.w, regs.a.l); op_writedbr(aa.w, regs.a.l);
if(regs.acc_8b)break; if(regs.p.m)break;
last_cycle(); last_cycle();
op_writedbr(aa.w + 1, regs.a.h); op_writedbr(aa.w + 1, regs.a.h);
} break; } break;
@@ -242,9 +242,9 @@ case 0x91: {
aa.l = op_readdp(dp); aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1); aa.h = op_readdp(dp + 1);
op_io(); op_io();
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l); op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)break; if(regs.p.m)break;
last_cycle(); last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h); op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
} break; } break;
@@ -256,9 +256,9 @@ case 0x97: {
aa.l = op_readdp(dp); aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1); aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2); aa.b = op_readdp(dp + 2);
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
op_writelong(aa.d + regs.y.w, regs.a.l); op_writelong(aa.d + regs.y.w, regs.a.l);
if(regs.acc_8b)break; if(regs.p.m)break;
last_cycle(); last_cycle();
op_writelong(aa.d + regs.y.w + 1, regs.a.h); op_writelong(aa.d + regs.y.w + 1, regs.a.h);
} break; } break;
@@ -267,9 +267,9 @@ case 0x97: {
case 0x83: { case 0x83: {
sp = op_readpc(); sp = op_readpc();
op_io(); op_io();
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
op_writesp(sp, regs.a.l); op_writesp(sp, regs.a.l);
if(regs.acc_8b)break; if(regs.p.m)break;
last_cycle(); last_cycle();
op_writesp(sp + 1, regs.a.h); op_writesp(sp + 1, regs.a.h);
} break; } break;
@@ -281,9 +281,9 @@ case 0x93: {
aa.l = op_readsp(sp); aa.l = op_readsp(sp);
aa.h = op_readsp(sp + 1); aa.h = op_readsp(sp + 1);
op_io(); op_io();
if(regs.acc_8b)last_cycle(); if(regs.p.m)last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l); op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.acc_8b)break; if(regs.p.m)break;
last_cycle(); last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h); op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
} break; } break;

View File

@@ -23,8 +23,8 @@ int32 r = regs.a.l + rd.l + regs.p.c;
r = regs.a.l + rd.l + regs.p.c; r = regs.a.l + rd.l + regs.p.c;
regs.p.c = (r > 0xff); regs.p.c = (r > 0xff);
} }
regs.p.n = bool(r & 0x80); regs.p.n = !!(r & 0x80);
regs.p.v = bool(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80); regs.p.v = !!(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
regs.p.z = ((uint8)r == 0); regs.p.z = ((uint8)r == 0);
regs.a.l = r; regs.a.l = r;
} }
@@ -67,135 +67,135 @@ int32 r;
r = regs.a.w + rd.w + regs.p.c; r = regs.a.w + rd.w + regs.p.c;
regs.p.c = (r > 0xffff); regs.p.c = (r > 0xffff);
} }
regs.p.n = bool(r & 0x8000); regs.p.n = !!(r & 0x8000);
regs.p.v = bool(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000); regs.p.v = !!(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
regs.p.z = ((uint16)r == 0); regs.p.z = ((uint16)r == 0);
regs.a.w = r; regs.a.w = r;
} }
inline void sCPU::op_and_b() { inline void sCPU::op_and_b() {
regs.a.l &= rd.l; regs.a.l &= rd.l;
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} }
inline void sCPU::op_and_w() { inline void sCPU::op_and_w() {
regs.a.w &= rd.w; regs.a.w &= rd.w;
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
inline void sCPU::op_bit_b() { inline void sCPU::op_bit_b() {
regs.p.n = bool(rd.l & 0x80); regs.p.n = !!(rd.l & 0x80);
regs.p.v = bool(rd.l & 0x40); regs.p.v = !!(rd.l & 0x40);
regs.p.z = ((rd.l & regs.a.l) == 0); regs.p.z = ((rd.l & regs.a.l) == 0);
} }
inline void sCPU::op_bit_w() { inline void sCPU::op_bit_w() {
regs.p.n = bool(rd.w & 0x8000); regs.p.n = !!(rd.w & 0x8000);
regs.p.v = bool(rd.w & 0x4000); regs.p.v = !!(rd.w & 0x4000);
regs.p.z = ((rd.w & regs.a.w) == 0); regs.p.z = ((rd.w & regs.a.w) == 0);
} }
inline void sCPU::op_cmp_b() { inline void sCPU::op_cmp_b() {
int32 r = regs.a.l - rd.l; int32 r = regs.a.l - rd.l;
regs.p.n = bool(r & 0x80); regs.p.n = !!(r & 0x80);
regs.p.z = ((uint8)r == 0); regs.p.z = ((uint8)r == 0);
regs.p.c = (r >= 0); regs.p.c = (r >= 0);
} }
inline void sCPU::op_cmp_w() { inline void sCPU::op_cmp_w() {
int32 r = regs.a.w - rd.w; int32 r = regs.a.w - rd.w;
regs.p.n = bool(r & 0x8000); regs.p.n = !!(r & 0x8000);
regs.p.z = ((uint16)r == 0); regs.p.z = ((uint16)r == 0);
regs.p.c = (r >= 0); regs.p.c = (r >= 0);
} }
inline void sCPU::op_cpx_b() { inline void sCPU::op_cpx_b() {
int32 r = regs.x.l - rd.l; int32 r = regs.x.l - rd.l;
regs.p.n = bool(r & 0x80); regs.p.n = !!(r & 0x80);
regs.p.z = ((uint8)r == 0); regs.p.z = ((uint8)r == 0);
regs.p.c = (r >= 0); regs.p.c = (r >= 0);
} }
inline void sCPU::op_cpx_w() { inline void sCPU::op_cpx_w() {
int32 r = regs.x.w - rd.w; int32 r = regs.x.w - rd.w;
regs.p.n = bool(r & 0x8000); regs.p.n = !!(r & 0x8000);
regs.p.z = ((uint16)r == 0); regs.p.z = ((uint16)r == 0);
regs.p.c = (r >= 0); regs.p.c = (r >= 0);
} }
inline void sCPU::op_cpy_b() { inline void sCPU::op_cpy_b() {
int32 r = regs.y.l - rd.l; int32 r = regs.y.l - rd.l;
regs.p.n = bool(r & 0x80); regs.p.n = !!(r & 0x80);
regs.p.z = ((uint8)r == 0); regs.p.z = ((uint8)r == 0);
regs.p.c = (r >= 0); regs.p.c = (r >= 0);
} }
inline void sCPU::op_cpy_w() { inline void sCPU::op_cpy_w() {
int32 r = regs.y.w - rd.w; int32 r = regs.y.w - rd.w;
regs.p.n = bool(r & 0x8000); regs.p.n = !!(r & 0x8000);
regs.p.z = ((uint16)r == 0); regs.p.z = ((uint16)r == 0);
regs.p.c = (r >= 0); regs.p.c = (r >= 0);
} }
inline void sCPU::op_eor_b() { inline void sCPU::op_eor_b() {
regs.a.l ^= rd.l; regs.a.l ^= rd.l;
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} }
inline void sCPU::op_eor_w() { inline void sCPU::op_eor_w() {
regs.a.w ^= rd.w; regs.a.w ^= rd.w;
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
inline void sCPU::op_lda_b() { inline void sCPU::op_lda_b() {
regs.a.l = rd.l; regs.a.l = rd.l;
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} }
inline void sCPU::op_lda_w() { inline void sCPU::op_lda_w() {
regs.a.w = rd.w; regs.a.w = rd.w;
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
inline void sCPU::op_ldx_b() { inline void sCPU::op_ldx_b() {
regs.x.l = rd.l; regs.x.l = rd.l;
regs.p.n = bool(regs.x.l & 0x80); regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0); regs.p.z = (regs.x.l == 0);
} }
inline void sCPU::op_ldx_w() { inline void sCPU::op_ldx_w() {
regs.x.w = rd.w; regs.x.w = rd.w;
regs.p.n = bool(regs.x.w & 0x8000); regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0); regs.p.z = (regs.x.w == 0);
} }
inline void sCPU::op_ldy_b() { inline void sCPU::op_ldy_b() {
regs.y.l = rd.l; regs.y.l = rd.l;
regs.p.n = bool(regs.y.l & 0x80); regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0); regs.p.z = (regs.y.l == 0);
} }
inline void sCPU::op_ldy_w() { inline void sCPU::op_ldy_w() {
regs.y.w = rd.w; regs.y.w = rd.w;
regs.p.n = bool(regs.y.w & 0x8000); regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0); regs.p.z = (regs.y.w == 0);
} }
inline void sCPU::op_ora_b() { inline void sCPU::op_ora_b() {
regs.a.l |= rd.l; regs.a.l |= rd.l;
regs.p.n = bool(regs.a.l & 0x80); regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0); regs.p.z = (regs.a.l == 0);
} }
inline void sCPU::op_ora_w() { inline void sCPU::op_ora_w() {
regs.a.w |= rd.w; regs.a.w |= rd.w;
regs.p.n = bool(regs.a.w & 0x8000); regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); regs.p.z = (regs.a.w == 0);
} }
@@ -221,8 +221,8 @@ int32 r;
r = regs.a.l - rd.l - !regs.p.c; r = regs.a.l - rd.l - !regs.p.c;
regs.p.c = (r >= 0); regs.p.c = (r >= 0);
} }
regs.p.n = bool(r & 0x80); regs.p.n = !!(r & 0x80);
regs.p.v = bool((regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80); regs.p.v = !!((regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
regs.p.z = ((uint8)r == 0); regs.p.z = ((uint8)r == 0);
regs.a.l = r; regs.a.l = r;
} }
@@ -261,8 +261,8 @@ int32 r;
r = regs.a.w - rd.w - !regs.p.c; r = regs.a.w - rd.w - !regs.p.c;
regs.p.c = (r >= 0); regs.p.c = (r >= 0);
} }
regs.p.n = bool(r & 0x8000); regs.p.n = !!(r & 0x8000);
regs.p.v = bool((regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000); regs.p.v = !!((regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
regs.p.z = ((uint16)r == 0); regs.p.z = ((uint16)r == 0);
regs.a.w = r; regs.a.w = r;
} }
@@ -270,89 +270,85 @@ int32 r;
//op_rmw //op_rmw
inline void sCPU::op_inc_b() { inline void sCPU::op_inc_b() {
rd.l++; rd.l++;
regs.p.n = bool(rd.l & 0x80); regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0); regs.p.z = (rd.l == 0);
} }
inline void sCPU::op_inc_w() { inline void sCPU::op_inc_w() {
rd.w++; rd.w++;
regs.p.n = bool(rd.w & 0x8000); regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0); regs.p.z = (rd.w == 0);
} }
inline void sCPU::op_dec_b() { inline void sCPU::op_dec_b() {
rd.l--; rd.l--;
regs.p.n = bool(rd.l & 0x80); regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0); regs.p.z = (rd.l == 0);
} }
inline void sCPU::op_dec_w() { inline void sCPU::op_dec_w() {
rd.w--; rd.w--;
regs.p.n = bool(rd.w & 0x8000); regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0); regs.p.z = (rd.w == 0);
} }
inline void sCPU::op_asl_b() { inline void sCPU::op_asl_b() {
regs.p.c = bool(rd.l & 0x80); regs.p.c = !!(rd.l & 0x80);
rd.l <<= 1; rd.l <<= 1;
regs.p.n = bool(rd.l & 0x80); regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0); regs.p.z = (rd.l == 0);
} }
inline void sCPU::op_asl_w() { inline void sCPU::op_asl_w() {
regs.p.c = bool(rd.w & 0x8000); regs.p.c = !!(rd.w & 0x8000);
rd.w <<= 1; rd.w <<= 1;
regs.p.n = bool(rd.w & 0x8000); regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0); regs.p.z = (rd.w == 0);
} }
inline void sCPU::op_lsr_b() { inline void sCPU::op_lsr_b() {
regs.p.c = rd.l & 1; regs.p.c = rd.l & 1;
rd.l >>= 1; rd.l >>= 1;
regs.p.n = bool(rd.l & 0x80); regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0); regs.p.z = (rd.l == 0);
} }
inline void sCPU::op_lsr_w() { inline void sCPU::op_lsr_w() {
regs.p.c = rd.w & 1; regs.p.c = rd.w & 1;
rd.w >>= 1; rd.w >>= 1;
regs.p.n = bool(rd.w & 0x8000); regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0); regs.p.z = (rd.w == 0);
} }
inline void sCPU::op_rol_b() { inline void sCPU::op_rol_b() {
uint16 c = regs.p.c; uint16 carry = (uint16)regs.p.c;
regs.p.c = bool(rd.l & 0x80); regs.p.c = !!(rd.l & 0x80);
rd.l <<= 1; rd.l = (rd.l << 1) | carry;
rd.l |= c; regs.p.n = !!(rd.l & 0x80);
regs.p.n = bool(rd.l & 0x80);
regs.p.z = (rd.l == 0); regs.p.z = (rd.l == 0);
} }
inline void sCPU::op_rol_w() { inline void sCPU::op_rol_w() {
uint16 c = regs.p.c; uint16 carry = (uint16)regs.p.c;
regs.p.c = bool(rd.w & 0x8000); regs.p.c = !!(rd.w & 0x8000);
rd.w <<= 1; rd.w = (rd.w << 1) | carry;
rd.w |= c; regs.p.n = !!(rd.w & 0x8000);
regs.p.n = bool(rd.w & 0x8000);
regs.p.z = (rd.w == 0); regs.p.z = (rd.w == 0);
} }
inline void sCPU::op_ror_b() { inline void sCPU::op_ror_b() {
uint16 c = (regs.p.c)?0x80:0; uint16 carry = (uint16)regs.p.c << 7;
regs.p.c = rd.l & 1; regs.p.c = rd.l & 1;
rd.l >>= 1; rd.l = carry | (rd.l >> 1);
rd.l |= c; regs.p.n = !!(rd.l & 0x80);
regs.p.n = bool(rd.l & 0x80);
regs.p.z = (rd.l == 0); regs.p.z = (rd.l == 0);
} }
inline void sCPU::op_ror_w() { inline void sCPU::op_ror_w() {
uint16 c = (regs.p.c)?0x8000:0; uint16 carry = (uint16)regs.p.c << 15;
regs.p.c = rd.w & 1; regs.p.c = rd.w & 1;
rd.w >>= 1; rd.w = carry | (rd.w >> 1);
rd.w |= c; regs.p.n = !!(rd.w & 0x8000);
regs.p.n = bool(rd.w & 0x8000);
regs.p.z = (rd.w == 0); regs.p.z = (rd.w == 0);
} }

View File

@@ -1,3 +1,8 @@
void sCPU::dma_add_clocks(uint clocks) {
status.dma_clocks += clocks;
add_clocks(clocks);
}
/***** /*****
* used by both DMA and HDMA * used by both DMA and HDMA
* *
@@ -29,9 +34,7 @@ uint8 r;
r_mem->write(abus, r); r_mem->write(abus, r);
} }
status.dma_clocks += 8; dma_add_clocks(8);
add_clocks(8);
co_return();
cycle_edge(); cycle_edge();
} }
@@ -105,8 +108,7 @@ inline void sCPU::dma_write(uint8 i, uint8 index) {
void sCPU::dma_run() { void sCPU::dma_run() {
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
if(channel[i].dma_enabled == false)continue; if(channel[i].dma_enabled == false)continue;
status.dma_clocks += 8; dma_add_clocks(8);
add_clocks(8);
if(cartridge.info.sdd1 == true) { if(cartridge.info.sdd1 == true) {
sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr), sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr),
@@ -130,7 +132,7 @@ void sCPU::dma_run() {
channel[i].dma_enabled = false; channel[i].dma_enabled = false;
} }
counter_set(counter.irq_delay, 24); counter.set(counter.irq_delay, 2);
} }
/***** /*****
@@ -167,19 +169,19 @@ uint8 r = 0;
void sCPU::hdma_update(uint8 i) { void sCPU::hdma_update(uint8 i) {
channel[i].hdma_line_counter = r_mem->read(hdma_addr(i)); channel[i].hdma_line_counter = r_mem->read(hdma_addr(i));
add_clocks(8); dma_add_clocks(8);
channel[i].hdma_completed = (channel[i].hdma_line_counter == 0); channel[i].hdma_completed = (channel[i].hdma_line_counter == 0);
channel[i].hdma_do_transfer = !channel[i].hdma_completed; channel[i].hdma_do_transfer = !channel[i].hdma_completed;
if(channel[i].hdma_indirect) { if(channel[i].hdma_indirect) {
channel[i].hdma_iaddr = r_mem->read(hdma_addr(i)) << 8; channel[i].hdma_iaddr = r_mem->read(hdma_addr(i)) << 8;
add_clocks(8); dma_add_clocks(8);
if(!channel[i].hdma_completed || hdma_active_after(i)) { if(!channel[i].hdma_completed || hdma_active_after(i)) {
channel[i].hdma_iaddr >>= 8; channel[i].hdma_iaddr >>= 8;
channel[i].hdma_iaddr |= r_mem->read(hdma_addr(i)) << 8; channel[i].hdma_iaddr |= r_mem->read(hdma_addr(i)) << 8;
add_clocks(8); dma_add_clocks(8);
} }
} }
} }
@@ -189,7 +191,7 @@ static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
if(hdma_active(i) == false)continue; if(hdma_active(i) == false)continue;
channel[i].dma_enabled = false; //HDMA run during DMA will stop DMA mid-transfer channel[i].dma_enabled = false; //HDMA run during DMA will stop DMA mid-transfer
add_clocks(8); dma_add_clocks(8);
if(channel[i].hdma_do_transfer) { if(channel[i].hdma_do_transfer) {
int xferlen = hdma_xferlen[channel[i].xfermode]; int xferlen = hdma_xferlen[channel[i].xfermode];
@@ -198,8 +200,7 @@ static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
dma_transfer(channel[i].direction, dma_bbus(i, index), dma_transfer(channel[i].direction, dma_bbus(i, index),
!channel[i].hdma_indirect ? hdma_addr(i) : hdma_iaddr(i)); !channel[i].hdma_indirect ? hdma_addr(i) : hdma_iaddr(i));
} else { } else {
add_clocks(8); dma_add_clocks(8);
co_return();
cycle_edge(); cycle_edge();
} }
} }
@@ -212,7 +213,7 @@ static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
} }
} }
counter_set(counter.irq_delay, 24); counter.set(counter.irq_delay, 2);
} }
void sCPU::hdma_init_reset() { void sCPU::hdma_init_reset() {
@@ -231,7 +232,7 @@ void sCPU::hdma_init() {
hdma_update(i); hdma_update(i);
} }
counter_set(counter.irq_delay, 24); counter.set(counter.irq_delay, 2);
} }
/***** /*****

View File

@@ -45,6 +45,7 @@ struct {
bool hdma_do_transfer; bool hdma_do_transfer;
} channel[8]; } channel[8];
void dma_add_clocks(uint clocks);
void dma_transfer(bool direction, uint8 bbus, uint32 abus); void dma_transfer(bool direction, uint8 bbus, uint32 abus);
uint8 dma_bbus(uint8 i, uint8 index); uint8 dma_bbus(uint8 i, uint8 index);

View File

@@ -10,7 +10,6 @@ void sCPU::op_io() {
status.clock_count = 6; status.clock_count = 6;
precycle_edge(); precycle_edge();
add_clocks(6); add_clocks(6);
//co_return();
cycle_edge(); cycle_edge();
} }
@@ -18,9 +17,6 @@ uint8 sCPU::op_read(uint32 addr) {
status.clock_count = r_mem->speed(addr); status.clock_count = r_mem->speed(addr);
precycle_edge(); precycle_edge();
add_clocks(status.clock_count - 4); add_clocks(status.clock_count - 4);
#ifdef FAVOR_ACCURACY
co_return();
#endif
regs.mdr = r_mem->read(addr); regs.mdr = r_mem->read(addr);
add_clocks(4); add_clocks(4);
cycle_edge(); cycle_edge();
@@ -31,10 +27,95 @@ void sCPU::op_write(uint32 addr, uint8 data) {
status.clock_count = r_mem->speed(addr); status.clock_count = r_mem->speed(addr);
precycle_edge(); precycle_edge();
add_clocks(status.clock_count); add_clocks(status.clock_count);
#ifdef FAVOR_ACCURACY
co_return();
#endif
regs.mdr = data; regs.mdr = data;
r_mem->write(addr, regs.mdr); r_mem->write(addr, regs.mdr);
cycle_edge(); cycle_edge();
} }
//
alwaysinline uint8 sCPU::op_readpc() {
return op_read((regs.pc.b << 16) + regs.pc.w++);
}
alwaysinline uint8 sCPU::op_readstack() {
if(regs.e) {
regs.s.l++;
} else {
regs.s.w++;
}
return op_read(regs.s.w);
}
alwaysinline uint8 sCPU::op_readstackn() {
return op_read(++regs.s.w);
}
alwaysinline uint8 sCPU::op_readaddr(uint32 addr) {
return op_read(addr & 0xffff);
}
alwaysinline uint8 sCPU::op_readlong(uint32 addr) {
return op_read(addr & 0xffffff);
}
alwaysinline uint8 sCPU::op_readdbr(uint32 addr) {
return op_read(((regs.db << 16) + addr) & 0xffffff);
}
alwaysinline uint8 sCPU::op_readpbr(uint32 addr) {
return op_read((regs.pc.b << 16) + (addr & 0xffff));
}
alwaysinline uint8 sCPU::op_readdp(uint32 addr) {
if(regs.e && regs.d.l == 0x00) {
return op_read((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff));
} else {
return op_read((regs.d + (addr & 0xffff)) & 0xffff);
}
}
alwaysinline uint8 sCPU::op_readsp(uint32 addr) {
return op_read((regs.s + (addr & 0xffff)) & 0xffff);
}
alwaysinline void sCPU::op_writestack(uint8 data) {
op_write(regs.s.w, data);
if(regs.e) {
regs.s.l--;
} else {
regs.s.w--;
}
}
alwaysinline void sCPU::op_writestackn(uint8 data) {
op_write(regs.s.w--, data);
}
alwaysinline void sCPU::op_writeaddr(uint32 addr, uint8 data) {
op_write(addr & 0xffff, data);
}
alwaysinline void sCPU::op_writelong(uint32 addr, uint8 data) {
op_write(addr & 0xffffff, data);
}
alwaysinline void sCPU::op_writedbr(uint32 addr, uint8 data) {
op_write(((regs.db << 16) + addr) & 0xffffff, data);
}
alwaysinline void sCPU::op_writepbr(uint32 addr, uint8 data) {
op_write((regs.pc.b << 16) + (addr & 0xffff), data);
}
alwaysinline void sCPU::op_writedp(uint32 addr, uint8 data) {
if(regs.e && regs.d.l == 0x00) {
op_write((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff), data);
} else {
op_write((regs.d + (addr & 0xffff)) & 0xffff, data);
}
}
alwaysinline void sCPU::op_writesp(uint32 addr, uint8 data) {
op_write((regs.s + (addr & 0xffff)) & 0xffff, data);
}

View File

@@ -15,19 +15,21 @@ uint8 apu_port[4];
/***** /*****
* helper memory addressing functions used by CPU core * helper memory addressing functions used by CPU core
*****/ *****/
uint8 op_readpc () { return op_read((regs.pc.b << 16) + regs.pc.w++); } uint8 op_readpc ();
uint8 op_readstack() { (regs.e) ? regs.s.l++ : regs.s.w++; return op_read(regs.s.w); } uint8 op_readstack ();
uint8 op_readaddr (uint32 addr) { return op_read(addr & 0xffff); } uint8 op_readstackn();
uint8 op_readlong (uint32 addr) { return op_read(addr & 0xffffff); } uint8 op_readaddr (uint32 addr);
uint8 op_readdbr (uint32 addr) { return op_read(((regs.db << 16) + addr) & 0xffffff); } uint8 op_readlong (uint32 addr);
uint8 op_readpbr (uint32 addr) { return op_read((regs.pc.b << 16) + (addr & 0xffff)); } uint8 op_readdbr (uint32 addr);
uint8 op_readdp (uint32 addr) { return op_read((regs.d + (addr & 0xffff)) & 0xffff); } uint8 op_readpbr (uint32 addr);
uint8 op_readsp (uint32 addr) { return op_read((regs.s + (addr & 0xffff)) & 0xffff); } uint8 op_readdp (uint32 addr);
uint8 op_readsp (uint32 addr);
void op_writestack(uint8 data) { op_write(regs.s.w, data); (regs.e) ? regs.s.l-- : regs.s.w--; } void op_writestack (uint8 data);
void op_writeaddr (uint32 addr, uint8 data) { op_write(addr & 0xffff, data); } void op_writestackn(uint8 data);
void op_writelong (uint32 addr, uint8 data) { op_write(addr & 0xffffff, data); } void op_writeaddr (uint32 addr, uint8 data);
void op_writedbr (uint32 addr, uint8 data) { op_write(((regs.db << 16) + addr) & 0xffffff, data); } void op_writelong (uint32 addr, uint8 data);
void op_writepbr (uint32 addr, uint8 data) { op_write((regs.pc.b << 16) + (addr & 0xffff), data); } void op_writedbr (uint32 addr, uint8 data);
void op_writedp (uint32 addr, uint8 data) { op_write((regs.d + (addr & 0xffff)) & 0xffff, data); } void op_writepbr (uint32 addr, uint8 data);
void op_writesp (uint32 addr, uint8 data) { op_write((regs.s + (addr & 0xffff)) & 0xffff, data); } void op_writedp (uint32 addr, uint8 data);
void op_writesp (uint32 addr, uint8 data);

View File

@@ -41,7 +41,7 @@ void sCPU::mmio_w4016(uint8 data) {
status.joypad_strobe_latch = !!(data & 1); status.joypad_strobe_latch = !!(data & 1);
if(status.joypad_strobe_latch == 1) { if(status.joypad_strobe_latch == 1) {
snes->poll_input(); snes.poll_input();
} }
} }
@@ -53,7 +53,7 @@ void sCPU::mmio_w4016(uint8 data) {
//realtime or buffered status of joypadN.b //realtime or buffered status of joypadN.b
uint8 sCPU::mmio_r4016() { uint8 sCPU::mmio_r4016() {
uint8 r = regs.mdr & 0xfc; uint8 r = regs.mdr & 0xfc;
r |= (uint8)snes->port_read(0); r |= (uint8)snes.port_read(0);
return r; return r;
} }
@@ -63,43 +63,14 @@ uint8 r = regs.mdr & 0xfc;
//1-0 = Joypad serial data //1-0 = Joypad serial data
uint8 sCPU::mmio_r4017() { uint8 sCPU::mmio_r4017() {
uint8 r = (regs.mdr & 0xe0) | 0x1c; uint8 r = (regs.mdr & 0xe0) | 0x1c;
r |= (uint8)snes->port_read(1); r |= (uint8)snes.port_read(1);
return r; return r;
} }
//NMITIMEN //NMITIMEN
void sCPU::mmio_w4200(uint8 data) { void sCPU::mmio_w4200(uint8 data) {
status.nmi_enabled = !!(data & 0x80);
status.virq_enabled = !!(data & 0x20);
status.hirq_enabled = !!(data & 0x10);
status.auto_joypad_poll = !!(data & 0x01); status.auto_joypad_poll = !!(data & 0x01);
nmitimen_update(data);
if(status.nmi_read == 0) {
if(status.nmi_line == 1 && status.nmi_enabled == 1) {
status.nmi_transition = 1;
}
status.nmi_line = !status.nmi_enabled;
}
if(status.irq_read == 0) {
if(status.irq_line == 1 && (status.virq_enabled || status.hirq_enabled)) {
status.irq_transition = 1;
}
status.irq_line = !(status.virq_enabled || status.hirq_enabled);
}
if(status.virq_enabled == true && status.hirq_enabled == false) {
status.irq_lock = false;
}
if(status.virq_enabled == false && status.hirq_enabled == false) {
status.irq_line = 1;
status.irq_read = 1;
status.irq_transition = 0;
}
update_interrupts();
counter_set(counter.irq_delay, 2);
} }
//WRIO //WRIO
@@ -119,7 +90,7 @@ void sCPU::mmio_w4202(uint8 data) {
void sCPU::mmio_w4203(uint8 data) { void sCPU::mmio_w4203(uint8 data) {
status.mul_b = data; status.mul_b = data;
status.r4216 = status.mul_a * status.mul_b; status.r4216 = status.mul_a * status.mul_b;
//counter_set(counter.hw_math, 48); //counter.set(counter.hw_math, 48);
} }
//WRDIVL //WRDIVL
@@ -137,51 +108,35 @@ void sCPU::mmio_w4206(uint8 data) {
status.div_b = data; status.div_b = data;
status.r4214 = (status.div_b) ? status.div_a / status.div_b : 0xffff; status.r4214 = (status.div_b) ? status.div_a / status.div_b : 0xffff;
status.r4216 = (status.div_b) ? status.div_a % status.div_b : status.div_a; status.r4216 = (status.div_b) ? status.div_a % status.div_b : status.div_a;
//counter_set(counter.hw_math, 96); //counter.set(counter.hw_math, 96);
} }
//HTIMEL //HTIMEL
void sCPU::mmio_w4207(uint8 data) { void sCPU::mmio_w4207(uint8 data) {
status.hirq_pos = (status.hirq_pos & ~0xff) | (data); status.hirq_pos = (status.hirq_pos & ~0xff) | (data);
status.hirq_pos &= 0x01ff; status.hirq_pos &= 0x01ff;
update_interrupts(); hvtime_update(0x4207);
uint vpos = status.vcounter, hpos = status.hclock;
timeshift_backward(10, vpos, hpos);
if(hpos < status.hirq_trigger_pos) { status.irq_lock = false; }
} }
//HTIMEH //HTIMEH
void sCPU::mmio_w4208(uint8 data) { void sCPU::mmio_w4208(uint8 data) {
status.hirq_pos = (status.hirq_pos & 0xff) | (data << 8); status.hirq_pos = (status.hirq_pos & 0xff) | (data << 8);
status.hirq_pos &= 0x01ff; status.hirq_pos &= 0x01ff;
update_interrupts(); hvtime_update(0x4208);
uint vpos = status.vcounter, hpos = status.hclock;
timeshift_backward(10, vpos, hpos);
if(hpos < status.hirq_trigger_pos) { status.irq_lock = false; }
} }
//VTIMEL //VTIMEL
void sCPU::mmio_w4209(uint8 data) { void sCPU::mmio_w4209(uint8 data) {
status.virq_pos = (status.virq_pos & ~0xff) | (data); status.virq_pos = (status.virq_pos & ~0xff) | (data);
status.virq_pos &= 0x01ff; status.virq_pos &= 0x01ff;
update_interrupts(); hvtime_update(0x4209);
uint vpos = status.vcounter, hpos = status.hclock;
timeshift_backward(10, vpos, hpos);
if(hpos < status.hirq_trigger_pos) { status.irq_lock = false; }
} }
//VTIMEH //VTIMEH
void sCPU::mmio_w420a(uint8 data) { void sCPU::mmio_w420a(uint8 data) {
status.virq_pos = (status.virq_pos & 0xff) | (data << 8); status.virq_pos = (status.virq_pos & 0xff) | (data << 8);
status.virq_pos &= 0x01ff; status.virq_pos &= 0x01ff;
update_interrupts(); hvtime_update(0x420a);
uint vpos = status.vcounter, hpos = status.hclock;
timeshift_backward(10, vpos, hpos);
if(hpos < status.hirq_trigger_pos) { status.irq_lock = false; }
} }
//DMAEN //DMAEN
@@ -213,12 +168,7 @@ void sCPU::mmio_w420d(uint8 data) {
//3-0 = CPU (5a22) version //3-0 = CPU (5a22) version
uint8 sCPU::mmio_r4210() { uint8 sCPU::mmio_r4210() {
uint8 r = (regs.mdr & 0x70); uint8 r = (regs.mdr & 0x70);
r |= (uint8)(!status.nmi_read) << 7; r |= (uint8)(rdnmi()) << 7;
if(!counter.nmi_fire) {
status.nmi_read = 1;
}
r |= (cpu_version & 0x0f); r |= (cpu_version & 0x0f);
return r; return r;
} }
@@ -228,14 +178,7 @@ uint8 r = (regs.mdr & 0x70);
//6-0 = MDR //6-0 = MDR
uint8 sCPU::mmio_r4211() { uint8 sCPU::mmio_r4211() {
uint8 r = (regs.mdr & 0x7f); uint8 r = (regs.mdr & 0x7f);
r |= (uint8)(!status.irq_read) << 7; r |= (uint8)(timeup()) << 7;
if(!counter.irq_fire) {
status.irq_read = 1;
status.irq_line = 1;
status.irq_transition = 0;
}
return r; return r;
} }
@@ -479,9 +422,7 @@ void sCPU::mmio_reset() {
uint8 sCPU::mmio_read(uint16 addr) { uint8 sCPU::mmio_read(uint16 addr) {
//APU //APU
if((addr & 0xffc0) == 0x2140) { //$2140-$217f if((addr & 0xffc0) == 0x2140) { //$2140-$217f
#ifdef FAVOR_SPEED scheduler.sync_cpusmp();
co_return();
#endif
return r_smp->port_read(addr & 3); return r_smp->port_read(addr & 3);
} }
@@ -536,9 +477,7 @@ uint8 sCPU::mmio_read(uint16 addr) {
void sCPU::mmio_write(uint16 addr, uint8 data) { void sCPU::mmio_write(uint16 addr, uint8 data) {
//APU //APU
if((addr & 0xffc0) == 0x2140) { //$2140-$217f if((addr & 0xffc0) == 0x2140) { //$2140-$217f
#ifdef FAVOR_SPEED scheduler.sync_cpusmp();
co_return();
#endif
port_write(addr & 3, data); port_write(addr & 3, data);
return; return;
} }

View File

@@ -6,16 +6,8 @@
#include "mmio/mmio.cpp" #include "mmio/mmio.cpp"
#include "timing/timing.cpp" #include "timing/timing.cpp"
void scpu_entry_point() {
r_cpu->main();
}
void sCPU::run() {
co_call(thread);
}
void sCPU::power() { void sCPU::power() {
status.region = bool(snes->region()); status.region = (bool)snes.region();
regs.a = regs.x = regs.y = 0x0000; regs.a = regs.x = regs.y = 0x0000;
regs.s = 0x01ff; regs.s = 0x01ff;
@@ -28,16 +20,10 @@ void sCPU::power() {
} }
void sCPU::reset() { void sCPU::reset() {
if(thread)co_delete(thread);
thread = co_create(scpu_entry_point, 65536);
regs.pc.d = 0x000000; regs.pc.d = 0x000000;
regs.pc.l = r_mem->read(0xfffc); regs.pc.l = r_mem->read(0xfffc);
regs.pc.h = r_mem->read(0xfffd); regs.pc.h = r_mem->read(0xfffd);
regs.acc_8b = true;
regs.idx_8b = true;
//note: some registers are not fully reset by SNES //note: some registers are not fully reset by SNES
regs.x.h = 0x00; regs.x.h = 0x00;
regs.y.h = 0x00; regs.y.h = 0x00;
@@ -62,11 +48,5 @@ void sCPU::reset() {
apu_port[3] = 0x00; apu_port[3] = 0x00;
} }
sCPU::sCPU() { sCPU::sCPU() {}
//#include "core/optable.cpp" sCPU::~sCPU() {}
thread = 0;
}
sCPU::~sCPU() {
if(thread)co_delete(thread);
}

View File

@@ -1,4 +1,7 @@
class sCPU : public CPU { class sCPU : public CPU {
public:
void enter();
public: public:
#include "core/core.h" #include "core/core.h"
#include "dma/dma.h" #include "dma/dma.h"
@@ -6,8 +9,6 @@ public:
#include "mmio/mmio.h" #include "mmio/mmio.h"
#include "timing/timing.h" #include "timing/timing.h"
thread_t thread;
struct { struct {
bool wai; bool wai;
bool irq; bool irq;
@@ -15,11 +16,25 @@ struct {
} event; } event;
struct { struct {
bool enabled; uint nmi_hold;
uint irq_delay; uint irq_hold;
uint irq_fire;
uint nmi_fire; uint nmi_fire;
uint irq_fire;
uint irq_delay;
uint hw_math; uint hw_math;
alwaysinline void set(uint &ctr, uint clocks) {
if(clocks >= ctr) { ctr = clocks; }
}
alwaysinline void sub(uint &ctr, uint clocks) {
if(ctr >= clocks) {
ctr -= clocks;
} else {
ctr = 0;
}
}
} counter; } counter;
enum { enum {
@@ -35,7 +50,6 @@ struct {
bool in_opcode; bool in_opcode;
uint clock_count; uint clock_count;
uint clocks_executed;
//timing //timing
bool region; bool region;
@@ -44,6 +58,7 @@ struct {
bool interlace, interlace_field; bool interlace, interlace_field;
bool overscan; bool overscan;
uint16 field_lines, line_clocks; uint16 field_lines, line_clocks;
uint16 prev_field_lines, prev_line_clocks;
uint16 vblstart; uint16 vblstart;
bool line_rendered; bool line_rendered;
@@ -59,13 +74,17 @@ struct {
uint16 irq_delay; uint16 irq_delay;
uint16 nmi_trigger_pos; uint16 vnmi_trigger_pos;
bool nmi_read, nmi_line, nmi_transition; bool nmi_valid;
bool nmi_line;
bool nmi_transition;
bool nmi_pending; bool nmi_pending;
uint16 virq_trigger_pos, hirq_trigger_pos; uint16 virq_trigger_pos, hirq_trigger_pos;
bool irq_read, irq_line, irq_transition; bool irq_valid;
bool irq_lock, irq_pending; bool irq_line;
bool irq_transition;
bool irq_pending;
//dma //dma
uint dma_counter; uint dma_counter;
@@ -114,7 +133,6 @@ struct {
uint8 joy4l, joy4h; uint8 joy4l, joy4h;
} status; } status;
void run();
void power(); void power();
void reset(); void reset();

View File

@@ -1,61 +1,4 @@
void sCPU::update_interrupts() { #include "irqtiming.cpp"
status.nmi_trigger_pos = (status.vcounter == status.vblstart) ? 2 : IRQ_TRIGGER_NEVER;
if(irq_pos_valid() == true) {
status.virq_trigger_pos = status.virq_pos;
status.hirq_trigger_pos = (status.hirq_enabled) ? ((status.hirq_pos + 1) * 4) : 0;
} else {
status.virq_trigger_pos = IRQ_TRIGGER_NEVER;
status.hirq_trigger_pos = IRQ_TRIGGER_NEVER;
}
}
alwaysinline void sCPU::nmi_tick() {
counter.nmi_fire -= 2;
if(counter.nmi_fire != 0) { return; }
if(status.nmi_enabled == true && status.nmi_line == 1) {
status.nmi_line = 0;
status.nmi_transition = 1;
}
}
alwaysinline void sCPU::irq_tick() {
counter.irq_fire -= 2;
if(counter.irq_fire != 0) { return; }
if(status.virq_enabled == true || status.hirq_enabled == true) {
status.irq_line = 0;
status.irq_transition = 1;
}
}
alwaysinline void sCPU::poll_interrupts() {
if(status.hclock == status.nmi_trigger_pos) {
status.nmi_read = 0;
counter.nmi_fire = 4;
}
if(status.hclock == 10) { status.irq_lock = false; }
if(status.hirq_trigger_pos == IRQ_TRIGGER_NEVER)return;
if(status.virq_enabled == false && status.hirq_enabled == false)return;
if(status.irq_lock == true)return;
uint vpos = status.vcounter;
uint hpos = status.hclock;
timeshift_backward(10, vpos, hpos);
bool trigger_irq = true;
if(status.virq_enabled == true && vpos != status.virq_trigger_pos)trigger_irq = false;
if(status.hirq_enabled == true && hpos != status.hirq_trigger_pos)trigger_irq = false;
if(trigger_irq == true) {
status.irq_lock = true;
status.irq_read = 0;
counter.irq_fire = 4;
}
}
bool sCPU::irq_pos_valid() { bool sCPU::irq_pos_valid() {
uint vpos = status.virq_pos; uint vpos = status.virq_pos;
@@ -74,19 +17,29 @@ uint vlimit = region_scanlines() >> 1;
return true; return true;
} }
alwaysinline bool sCPU::nmi_test() { alwaysinline
if(status.nmi_transition == 0)return false; bool sCPU::nmi_test() {
if(status.nmi_transition == false) { return false; }
status.nmi_transition = false;
status.nmi_transition = 0;
event.wai = false; event.wai = false;
return true; return true;
} }
alwaysinline bool sCPU::irq_test() { alwaysinline
bool sCPU::irq_test() {
if(status.irq_transition == false) { return false; }
status.irq_transition = false;
event.wai = false;
return (regs.p.i) ? false : true;
}
/*
if(status.irq_transition == 1)goto irq_trigger; if(status.irq_transition == 1)goto irq_trigger;
if(status.irq_read == 0) { if(status.irq_read == 0) {
if(status.irq_line == 1 && counter.irq_fire) { if(status.irq_line == 1 && irq_edge()) {
return false; return false;
} }
goto irq_trigger; goto irq_trigger;
@@ -104,3 +57,4 @@ irq_trigger:
event.wai = false; event.wai = false;
return (regs.p.i) ? false : true; return (regs.p.i) ? false : true;
} }
*/

View File

@@ -0,0 +1,105 @@
void sCPU::update_interrupts() {
status.vnmi_trigger_pos = status.vblstart;
if(irq_pos_valid() == true) {
status.virq_trigger_pos = status.virq_pos;
status.hirq_trigger_pos = 4 * ((status.hirq_enabled) ? (status.hirq_pos + 1) : 0);
} else {
status.virq_trigger_pos = IRQ_TRIGGER_NEVER;
status.hirq_trigger_pos = IRQ_TRIGGER_NEVER;
}
}
alwaysinline
void sCPU::poll_interrupts() {
uint vpos = status.vcounter, hpos = status.hclock;
//NMI test
timeshift_backward(2, vpos, hpos);
bool nmi_valid = (vpos >= status.vnmi_trigger_pos);
if(status.nmi_valid == false && nmi_valid == true) {
//0->1 edge sensitive transition
status.nmi_line = true;
counter.nmi_hold = 6;
} else if(status.nmi_valid == true && nmi_valid == false) {
//1->0 edge sensitive transition
status.nmi_line = false;
}
status.nmi_valid = nmi_valid;
//NMI hold
if(counter.nmi_hold) {
counter.nmi_hold -= 2;
if(counter.nmi_hold == 0) {
if(status.nmi_enabled == true) { status.nmi_transition = true; }
}
}
//IRQ test
timeshift_backward(8, vpos, hpos);
bool irq_valid = (status.virq_enabled == true || status.hirq_enabled == true);
if(irq_valid == true) {
if(status.virq_enabled == true && vpos != status.virq_trigger_pos) { irq_valid = false; }
if(status.hirq_enabled == true && hpos != status.hirq_trigger_pos) { irq_valid = false; }
}
if(status.irq_valid == false && irq_valid == true) {
//0->1 edge sensitive transition
status.irq_line = true;
counter.irq_hold = 6;
}
status.irq_valid = irq_valid;
//IRQ hold
if(counter.irq_hold) { counter.irq_hold -= 2; }
if(status.irq_line == true && counter.irq_hold == 0) {
if(status.virq_enabled == true || status.hirq_enabled == true) { status.irq_transition = true; }
}
}
void sCPU::nmitimen_update(uint8 data) {
bool nmi_enabled = status.nmi_enabled;
bool virq_enabled = status.virq_enabled;
bool hirq_enabled = status.hirq_enabled;
status.nmi_enabled = !!(data & 0x80);
status.virq_enabled = !!(data & 0x20);
status.hirq_enabled = !!(data & 0x10);
//0->1 edge sensitive transition
if(nmi_enabled == false && status.nmi_enabled == true && status.nmi_line == true) {
status.nmi_transition = true;
}
//?->1 level sensitive transition
if(status.virq_enabled == true && status.hirq_enabled == false && status.irq_line == true) {
status.irq_transition = true;
}
if(status.virq_enabled == false && status.hirq_enabled == false) {
status.irq_line = false;
status.irq_transition = false;
}
update_interrupts();
counter.set(counter.irq_delay, 2);
}
void sCPU::hvtime_update(uint16 addr) {
update_interrupts();
}
bool sCPU::rdnmi() {
bool result = status.nmi_line;
if(counter.nmi_hold == 0) {
status.nmi_line = false;
}
return result;
}
bool sCPU::timeup() {
bool result = status.irq_line;
if(counter.irq_hold == 0) {
status.irq_line = false;
status.irq_transition = false;
}
return result;
}

View File

@@ -1,8 +1,8 @@
void sCPU::run_auto_joypad_poll() { void sCPU::run_auto_joypad_poll() {
uint16 joy1 = 0, joy2 = 0; uint16 joy1 = 0, joy2 = 0;
for(int i = 0; i < 16; i++) { for(int i = 0; i < 16; i++) {
joy1 |= (uint16)snes->port_read(0) ? (0x8000 >> i) : 0; joy1 |= (uint16)snes.port_read(0) ? (0x8000 >> i) : 0;
joy2 |= (uint16)snes->port_read(1) ? (0x8000 >> i) : 0; joy2 |= (uint16)snes.port_read(1) ? (0x8000 >> i) : 0;
} }
status.joy1l = joy1; status.joy1l = joy1;

View File

@@ -1,6 +1,5 @@
alwaysinline void sCPU::timeshift_forward(uint clocks, uint &vtime, uint &htime) { alwaysinline void sCPU::timeshift_forward(uint clocks, uint &vtime, uint &htime) {
htime += clocks; htime += clocks;
if(htime >= status.line_clocks) { if(htime >= status.line_clocks) {
htime -= status.line_clocks; htime -= status.line_clocks;
if(++vtime >= status.field_lines) { if(++vtime >= status.field_lines) {
@@ -13,14 +12,11 @@ alwaysinline void sCPU::timeshift_backward(uint clocks, uint &vtime, uint &htime
if(htime >= clocks) { if(htime >= clocks) {
htime -= clocks; htime -= clocks;
} else { } else {
htime += 1364 - clocks; htime += status.prev_line_clocks - clocks;
if(status.region == SNES::NTSC && status.vcounter == 241 &&
status.interlace == false && status.interlace_field == 1)htime -= 4;
if(vtime > 0) { if(vtime > 0) {
vtime--; vtime--;
} else { } else {
vtime = status.region_scanlines; vtime = status.prev_field_lines - 1;
if(status.interlace == true && status.interlace_field == 1)vtime++;
} }
} }
} }

View File

@@ -45,35 +45,22 @@ uint16 sCPU::hcounter() {
} }
void sCPU::add_clocks(uint clocks) { void sCPU::add_clocks(uint clocks) {
status.clocks_executed += clocks; if(status.dram_refreshed == false) {
if(status.hclock + clocks >= status.dram_refresh_position) {
if(counter.irq_delay) { status.dram_refreshed = true;
counter.irq_delay = (counter.irq_delay > clocks) ? (counter.irq_delay - clocks) : 0; clocks += 40;
}
} }
if(status.hclock + clocks >= status.line_clocks) { counter.sub(counter.irq_delay, clocks);
clocks = (status.hclock + clocks) - status.line_clocks; scheduler.addclocks_cpu(clocks);
while(status.hclock < status.line_clocks - 2) { tick(); }
scanline();
}
clocks >>= 1; clocks >>= 1;
while(clocks--) { tick(); } while(clocks--) {
} status.hclock += 2;
if(status.hclock >= status.line_clocks) { scanline(); }
alwaysinline void sCPU::tick() { poll_interrupts();
status.hclock += 2;
if(counter.nmi_fire) { nmi_tick(); }
if(counter.irq_fire) { irq_tick(); }
if(status.dram_refreshed == false && status.hclock >= status.dram_refresh_position) {
status.dram_refreshed = true;
add_clocks(40);
return;
} }
poll_interrupts();
} }
void sCPU::scanline() { void sCPU::scanline() {
@@ -84,6 +71,7 @@ void sCPU::scanline() {
frame(); frame();
} }
status.prev_line_clocks = status.line_clocks;
status.line_clocks = (ntsc_color_burst_phase_shift_scanline() == false) ? 1364 : 1360; status.line_clocks = (ntsc_color_burst_phase_shift_scanline() == false) ? 1364 : 1360;
//dram refresh occurs once every scanline //dram refresh occurs once every scanline
@@ -103,23 +91,20 @@ void sCPU::scanline() {
status.hdma_triggered = (status.vcounter <= (!overscan() ? 224 : 239)) ? false : true; status.hdma_triggered = (status.vcounter <= (!overscan() ? 224 : 239)) ? false : true;
r_ppu->scanline(); r_ppu->scanline();
snes->scanline(); snes.scanline();
update_interrupts(); update_interrupts();
if(status.auto_joypad_poll == true && status.vcounter == (!overscan() ? 227 : 242)) { if(status.auto_joypad_poll == true && status.vcounter == (!overscan() ? 227 : 242)) {
snes->poll_input(); snes.poll_input();
run_auto_joypad_poll(); run_auto_joypad_poll();
} }
} }
void sCPU::frame() { void sCPU::frame() {
status.nmi_read = 1;
status.nmi_line = 1;
status.nmi_transition = 0;
status.vcounter = 0; status.vcounter = 0;
status.interlace_field ^= 1; status.interlace_field ^= 1;
status.prev_field_lines = status.field_lines;
status.field_lines = (status.region_scanlines >> 1); status.field_lines = (status.region_scanlines >> 1);
//interlaced even fields have one extra scanline //interlaced even fields have one extra scanline
//(263+262=525 NTSC, 313+312=625 PAL) //(263+262=525 NTSC, 313+312=625 PAL)
@@ -133,7 +118,7 @@ void sCPU::frame() {
} }
r_ppu->frame(); r_ppu->frame();
snes->frame(); snes.frame();
} }
/***** /*****
@@ -185,15 +170,16 @@ void sCPU::cycle_edge() {
if(status.hdmainit_triggered == false) { if(status.hdmainit_triggered == false) {
if(status.hclock >= status.hdmainit_trigger_position || status.vcounter) { if(status.hclock >= status.hdmainit_trigger_position || status.vcounter) {
status.hdmainit_triggered = true; status.hdmainit_triggered = true;
hdma_init_reset(); hdma_init_reset();
if(hdma_enabled_channels()) { if(hdma_enabled_channels()) {
if(status.dma_state == DMASTATE_INACTIVE) { add_clocks(12);
status.dma_state = DMASTATE_DMASYNC; hdma_init();
status.hdmainit_pending = true; //if(status.dma_state == DMASTATE_INACTIVE) {
} else { // status.dma_state = DMASTATE_DMASYNC;
hdma_init(); // status.hdmainit_pending = true;
} //} else {
// hdma_init();
//}
} }
} }
} }
@@ -202,12 +188,14 @@ void sCPU::cycle_edge() {
if(status.hclock >= 1106) { if(status.hclock >= 1106) {
status.hdma_triggered = true; status.hdma_triggered = true;
if(hdma_active_channels()) { if(hdma_active_channels()) {
if(status.dma_state == DMASTATE_INACTIVE) { add_clocks(12);
status.dma_state = DMASTATE_DMASYNC; hdma_run();
status.hdma_pending = true; //if(status.dma_state == DMASTATE_INACTIVE) {
} else { // status.dma_state = DMASTATE_DMASYNC;
hdma_run(); // status.hdma_pending = true;
} //} else {
// hdma_run();
//}
} }
} }
} }
@@ -231,30 +219,19 @@ void sCPU::last_cycle() {
event.irq = (status.nmi_pending || status.irq_pending); event.irq = (status.nmi_pending || status.irq_pending);
} }
/*****
* clocks_executed()
*
* Return number of clocks executed since last call to this function.
* Used by class SNES to control CPU<>APU synchronization.
*****/
uint32 sCPU::clocks_executed() {
uint32 r = status.clocks_executed;
status.clocks_executed = 0;
return r;
}
void sCPU::timing_power() { void sCPU::timing_power() {
} }
void sCPU::timing_reset() { void sCPU::timing_reset() {
counter.enabled = false; counter.nmi_hold = 0;
counter.irq_hold = 0;
counter.nmi_fire = 0;
counter.irq_fire = 0;
counter.irq_delay = 0; counter.irq_delay = 0;
counter.hw_math = 0; counter.hw_math = 0;
counter.irq_fire = 0;
counter.nmi_fire = 0;
status.clock_count = 0; status.clock_count = 0;
status.clocks_executed = 0;
status.vcounter = 0; status.vcounter = 0;
status.hcounter = 0; status.hcounter = 0;
@@ -269,8 +246,11 @@ void sCPU::timing_reset() {
status.field_lines = status.region_scanlines >> 1; status.field_lines = status.region_scanlines >> 1;
status.line_clocks = 1364; status.line_clocks = 1364;
status.prev_field_lines = status.region_scanlines >> 1;
status.prev_line_clocks = 1364;
status.line_rendered = false; status.line_rendered = false;
status.line_render_position = minmax<0, 1112>((uint16)config::ppu.render_scanline_position); status.line_render_position = minmax<0, 1112>((uint16)config::ppu.hack.render_scanline_position);
status.dram_refreshed = false; status.dram_refreshed = false;
status.dram_refresh_position = (cpu_version == 1) ? 530 : 538; status.dram_refresh_position = (cpu_version == 1) ? 530 : 538;
@@ -282,15 +262,14 @@ void sCPU::timing_reset() {
status.irq_delay = 0; status.irq_delay = 0;
status.nmi_read = 1; status.nmi_valid = false;
status.nmi_line = 1; status.nmi_line = false;
status.nmi_transition = 0; status.nmi_transition = false;
status.nmi_pending = false; status.nmi_pending = false;
status.irq_read = 1; status.irq_valid = false;
status.irq_line = 1; status.irq_line = false;
status.irq_transition = 0; status.irq_transition = false;
status.irq_lock = false;
status.irq_pending = false; status.irq_pending = false;
update_interrupts(); update_interrupts();

View File

@@ -13,7 +13,6 @@
uint dma_counter(); uint dma_counter();
void add_clocks(uint clocks); void add_clocks(uint clocks);
void tick();
void scanline(); void scanline();
void frame(); void frame();
@@ -25,10 +24,6 @@
void timing_power(); void timing_power();
void timing_reset(); void timing_reset();
void counter_set(uint &ctr, uint clocks) {
if(clocks >= ctr) { ctr = clocks; }
}
//timeshift.cpp //timeshift.cpp
void timeshift_forward (uint clocks, uint &v, uint &h); void timeshift_forward (uint clocks, uint &v, uint &h);
void timeshift_backward(uint clocks, uint &v, uint &h); void timeshift_backward(uint clocks, uint &v, uint &h);
@@ -36,9 +31,12 @@
//irq.cpp //irq.cpp
enum { IRQ_TRIGGER_NEVER = 0x3fff }; enum { IRQ_TRIGGER_NEVER = 0x3fff };
void update_interrupts(); void update_interrupts();
void nmi_tick();
void irq_tick();
void poll_interrupts(); void poll_interrupts();
void nmitimen_update(uint8 data);
void hvtime_update(uint16 addr);
bool rdnmi();
bool timeup();
bool irq_pos_valid(); bool irq_pos_valid();
bool nmi_test(); bool nmi_test();
bool irq_test(); bool irq_test();

View File

@@ -558,7 +558,7 @@ int32 fir_samplel, fir_sampler;
msampler = sclamp<16>(msampler); msampler = sclamp<16>(msampler);
} }
return uint32( uint16(msamplel) | (uint16(msampler) << 16) ); return (uint32)( (uint16)msamplel | ((uint16)msampler << 16) );
} }
bDSP::bDSP() {} bDSP::bDSP() {}

View File

@@ -20,11 +20,9 @@
#include "cpu/cpu.h" #include "cpu/cpu.h"
#include "cpu/scpu/scpu.h" #include "cpu/scpu/scpu.h"
//#include "cpu/bcpu/bcpu.h"
#include "smp/smp.h" #include "smp/smp.h"
#include "smp/ssmp/ssmp.h" #include "smp/ssmp/ssmp.h"
//#include "smp/bsmp/bsmp.h"
#include "dsp/dsp.h" #include "dsp/dsp.h"
#include "dsp/bdsp/bdsp.h" #include "dsp/bdsp/bdsp.h"

View File

@@ -1,5 +1,5 @@
/* /*
libbase : version 0.08c ~byuu (09/28/06) libbase : version 0.08f ~byuu (2006-11-07)
*/ */
#ifndef __LIBBASE #ifndef __LIBBASE
@@ -9,6 +9,7 @@
//disable libc deprecation warnings in MSVC 2k5+ //disable libc deprecation warnings in MSVC 2k5+
#pragma warning(disable:4996) #pragma warning(disable:4996)
#define NOMINMAX
#define ftruncate _chsize #define ftruncate _chsize
#define vsnprintf _vsnprintf #define vsnprintf _vsnprintf
#endif #endif
@@ -28,7 +29,10 @@
#define alwaysinline inline #define alwaysinline inline
#define fastcall __attribute__((fastcall)) #define fastcall __attribute__((fastcall))
#else #else
#error "unsupported compiler" #define noinline
#define inline inline
#define alwaysinline inline
#define fastcall
#endif #endif
#include <stdio.h> #include <stdio.h>
@@ -47,6 +51,7 @@
#define TRUE !FALSE #define TRUE !FALSE
#endif #endif
//deprecated
#define SafeFree(__n) if(__n) { free(__n); __n = 0; } #define SafeFree(__n) if(__n) { free(__n); __n = 0; }
#define SafeDelete(__n) if(__n) { delete(__n); __n = 0; } #define SafeDelete(__n) if(__n) { delete(__n); __n = 0; }
#define SafeRelease(__n) if(__n) { __n->Release(); __n = 0; } #define SafeRelease(__n) if(__n) { __n->Release(); __n = 0; }
@@ -78,14 +83,45 @@ typedef signed long long int64;
* templates * templates
*****/ *****/
template<typename T> inline void safe_free(T &handle) {
if(handle) {
free(handle);
handle = 0;
}
}
template<typename T> inline void safe_delete(T &handle) {
if(handle) {
delete handle;
handle = 0;
}
}
template<typename T> inline void safe_release(T &handle) {
if(handle) {
handle->Release();
handle = 0;
}
}
template<typename T> inline void swap(T &x, T &y) { template<typename T> inline void swap(T &x, T &y) {
T z = x; T z = x;
x = y; x = y;
y = z; y = z;
} }
#ifdef min
#undef min
#endif
#define min(x, y) ((x < y) ? x : y)
#ifdef max
#undef max
#endif
#define max(x, y) ((x > y) ? x : y)
template<int min, int max, typename T> inline T minmax(const T x) { template<int min, int max, typename T> inline T minmax(const T x) {
return (x < T(min)) ? T(min) : (x > T(max)) ? T(max) : x; return (x < (T)min) ? (T)min : (x > (T)max) ? (T)max : x;
} }
template<int bits> inline unsigned uclamp(const unsigned x) { template<int bits> inline unsigned uclamp(const unsigned x) {
@@ -243,6 +279,90 @@ typedef int_t<48, int64> int48;
* libc extensions * libc extensions
*****/ *****/
static uint8 fgetb(FILE *fp) { return fgetc(fp); }
static uint8 fgetlb(FILE *fp) { return fgetc(fp); }
static uint8 fgetmb(FILE *fp) { return fgetc(fp); }
static uint16 fgetlw(FILE *fp) {
return (fgetc(fp)) | (fgetc(fp) << 8);
}
static uint16 fgetmw(FILE *fp) {
return (fgetc(fp) << 8) | (fgetc(fp) << 8);
}
static uint32 fgetld(FILE *fp) {
return (fgetc(fp)) | (fgetc(fp) << 8) | (fgetc(fp) << 16) | (fgetc(fp) << 24);
}
static uint32 fgetmd(FILE *fp) {
return (fgetc(fp) << 24) | (fgetc(fp) << 16) | (fgetc(fp) << 8) | (fgetc(fp));
}
static uint64 fgetlq(FILE *fp) {
return ((uint64)fgetc(fp) << 0) | ((uint64)fgetc(fp) << 8) |
((uint64)fgetc(fp) << 16) | ((uint64)fgetc(fp) << 24) |
((uint64)fgetc(fp) << 32) | ((uint64)fgetc(fp) << 40) |
((uint64)fgetc(fp) << 48) | ((uint64)fgetc(fp) << 56);
}
static uint64 fgetmq(FILE *fp) {
return ((uint64)fgetc(fp) << 56) | ((uint64)fgetc(fp) << 48) |
((uint64)fgetc(fp) << 40) | ((uint64)fgetc(fp) << 32) |
((uint64)fgetc(fp) << 24) | ((uint64)fgetc(fp) << 16) |
((uint64)fgetc(fp) << 8) | ((uint64)fgetc(fp) << 0);
}
static void fputb(FILE *fp, uint8 data) { fputc(data, fp); }
static void fputlb(FILE *fp, uint8 data) { fputc(data, fp); }
static void fputmb(FILE *fp, uint8 data) { fputc(data, fp); }
static void fputlw(FILE *fp, uint16 data) {
fputc(data >> 0, fp);
fputc(data >> 8, fp);
}
static void fputmw(FILE *fp, uint16 data) {
fputc(data >> 8, fp);
fputc(data >> 0, fp);
}
static void fputld(FILE *fp, uint32 data) {
fputc(data >> 0, fp);
fputc(data >> 8, fp);
fputc(data >> 16, fp);
fputc(data >> 24, fp);
}
static void fputmd(FILE *fp, uint32 data) {
fputc(data >> 24, fp);
fputc(data >> 16, fp);
fputc(data >> 8, fp);
fputc(data >> 0, fp);
}
static void fputlq(FILE *fp, uint64 data) {
fputc(data >> 0, fp);
fputc(data >> 8, fp);
fputc(data >> 16, fp);
fputc(data >> 24, fp);
fputc(data >> 32, fp);
fputc(data >> 40, fp);
fputc(data >> 48, fp);
fputc(data >> 56, fp);
}
static void fputmq(FILE *fp, uint64 data) {
fputc(data >> 56, fp);
fputc(data >> 48, fp);
fputc(data >> 40, fp);
fputc(data >> 32, fp);
fputc(data >> 24, fp);
fputc(data >> 16, fp);
fputc(data >> 8, fp);
fputc(data >> 0, fp);
}
static bool fexists(const char *fn) { static bool fexists(const char *fn) {
FILE *fp = fopen(fn, "rb"); FILE *fp = fopen(fn, "rb");
if(!fp)return false; if(!fp)return false;
@@ -270,7 +390,7 @@ uint32 size = ftell(fp);
return size; return size;
} }
inline int ftruncate(FILE *fp, long size) { return ftruncate(fileno(fp), size); } static int ftruncate(FILE *fp, long size) { return ftruncate(fileno(fp), size); }
/***** /*****
* crc32 calculation * crc32 calculation
@@ -327,4 +447,12 @@ inline uint32 crc32_adjust(uint32 crc32, uint8 input) {
return ((crc32 >> 8) & 0x00ffffff) ^ crc32_table[(crc32 ^ input) & 0xff]; return ((crc32 >> 8) & 0x00ffffff) ^ crc32_table[(crc32 ^ input) & 0xff];
} }
inline uint32 crc32_calculate(uint8 *data, uint length) {
uint32 crc32 = ~0;
for(uint i = 0; i < length; i++) {
crc32 = crc32_adjust(crc32, data[i]);
}
return ~crc32;
}
#endif #endif

View File

@@ -1,5 +1,5 @@
/* /*
libco_win32 : version 0.06 ~byuu (05/21/06) libco_win32 : version 0.08 ~byuu (10/21/06)
win32-x86 implementation of libco win32-x86 implementation of libco
*/ */
@@ -9,60 +9,62 @@
#include "libco_win32.h" #include "libco_win32.h"
namespace libco_win32 { struct cothread_struct {
bool co_enabled = false; void *cohandle;
int co_stackptr = 0; cothread_p coentry;
thread_t co_stack[4096]; cothread_t colink;
void __stdcall coentry_proc(void *coentry) {
thread_p main = (thread_p)coentry;
main();
}
}; };
void co_init() { cothread_t __co_active = 0, __co_primary = 0;
if(libco_win32::co_enabled == true)return;
libco_win32::co_enabled = true;
void __stdcall co_entryproc(void *coentry) {
cothread_struct *s = static_cast<cothread_struct*>(coentry);
s->coentry();
co_exit(0);
}
cothread_t co_init() {
ConvertThreadToFiber(0); ConvertThreadToFiber(0);
cothread_struct *s = static_cast<cothread_struct*>(malloc(sizeof(cothread_struct)));
s->colink = 0;
s->coentry = 0;
s->cohandle = GetCurrentFiber();
__co_active = __co_primary = static_cast<cothread_t>(s);
return __co_active;
} }
void co_term() { void co_term() {
/***** //primary fiber cannot be deleted; free memory used by handle to fiber only
//ConverFiberToThread() only exists on WinXP+ free(__co_primary);
//ConvertFiberToThread(); //only exists on WinXP+
if(libco_win32::co_enabled == false)return;
libco_win32::co_enabled = false;
ConvertFiberToThread();
*****/
} }
thread_t co_active() { cothread_t co_active() {
if(libco_win32::co_enabled == false)co_init(); return __co_active;
return GetCurrentFiber();
} }
thread_t co_create(thread_p coentry, unsigned int heapsize) { cothread_t co_create(cothread_p coentry, unsigned int heapsize) {
if(libco_win32::co_enabled == false)co_init(); cothread_struct *s = static_cast<cothread_struct*>(malloc(sizeof(cothread_struct)));
s->colink = co_active();
return CreateFiber(heapsize, libco_win32::coentry_proc, (void*)coentry); s->coentry = coentry;
s->cohandle = CreateFiber(heapsize + 512, co_entryproc, static_cast<void*>(s));
return static_cast<cothread_t>(s);
} }
void co_delete(thread_t cothread) { void co_delete(cothread_t cothread) {
DeleteFiber(cothread); cothread_struct *s = static_cast<cothread_struct*>(cothread);
DeleteFiber(s->cohandle);
free(cothread);
} }
void co_jump(thread_t cothread) { void co_switch(cothread_t cothread) {
SwitchToFiber(cothread); __co_active = cothread;
cothread_struct *s = static_cast<cothread_struct*>(cothread);
SwitchToFiber(s->cohandle);
} }
void co_call(thread_t cothread) { void co_exit(cothread_t cothread) {
libco_win32::co_stack[libco_win32::co_stackptr++] = co_active(); if(cothread != 0) { co_switch(cothread); }
co_jump(cothread); cothread_struct *s = static_cast<cothread_struct*>(__co_active);
} co_switch(s->colink);
void co_return() {
co_jump(libco_win32::co_stack[--libco_win32::co_stackptr]);
} }

View File

@@ -1,15 +1,20 @@
/* /*
libco_win32 : version 0.06 ~byuu (05/21/2006) libco_win32 : version 0.08 ~byuu (10/21/2006)
*/ */
typedef void (*thread_t); #define COTHREAD_STACKSIZE_TINY 0x1000
typedef void (*thread_p)(); #define COTHREAD_STACKSIZE_SMALL 0x4000
#define COTHREAD_STACKSIZE_NORMAL 0x10000
#define COTHREAD_STACKSIZE_LARGE 0x40000
#define COTHREAD_STACKSIZE_HUGE 0x100000
void co_init(); typedef void (*cothread_t);
void co_term(); typedef void (*cothread_p)(void);
thread_t co_active();
thread_t co_create(thread_p coentry, unsigned int heapsize); cothread_t co_init();
void co_delete(thread_t cothread); void co_term();
void co_jump(thread_t cothread); cothread_t co_active();
void co_call(thread_t cothread); cothread_t co_create(cothread_p coentry, unsigned int heapsize);
void co_return(); void co_delete(cothread_t cothread);
void co_switch(cothread_t cothread);
void co_exit(cothread_t cothread);

View File

@@ -1,9 +1,9 @@
;***** ;*****
;libco_x86 : version 0.07 ~byuu (08/15/06) ;libco_x86 : version 0.08 ~byuu (10/21/06)
;cross-platform x86 implementation of libco ;cross-platform x86 implementation of libco
; ;
;context save/restore adheres to c/c++ ABI ;context save/restore adheres to c/c++ ABI
;for x86 windows, linux and freebsd ;for x86 windows, osx, linux and freebsd
; ;
;context saves esp+ebp+esi+edi+ebx ;context saves esp+ebp+esi+edi+ebx
;context ignores eax+ecx+edx ;context ignores eax+ecx+edx
@@ -14,8 +14,8 @@
section .data section .data
align 4 align 4
co_initialized dd 0
co_active_context dd 0 co_active_context dd 0
co_primary_context dd 0
section .code section .code
@@ -31,9 +31,21 @@ section .code
%define co_active @co_active@0 %define co_active @co_active@0
%define co_create @co_create@8 %define co_create @co_create@8
%define co_delete @co_delete@4 %define co_delete @co_delete@4
%define co_jump @co_jump@4 %define co_switch @co_switch@4
%define co_call @co_call@4 %define co_exit @co_exit@4
%define co_return @co_return@0 %endif
%ifdef OSX86
%define malloc _malloc
%define free _free
%define co_init _co_init
%define co_term _co_term
%define co_active _co_active
%define co_create _co_create
%define co_delete _co_delete
%define co_switch _co_switch
%define co_exit _co_exit
%endif %endif
extern malloc extern malloc
@@ -44,26 +56,22 @@ global co_term
global co_active global co_active
global co_create global co_create
global co_delete global co_delete
global co_jump global co_switch
global co_call global co_exit
global co_return
;***** ;*****
;extern "C" void fastcall co_init(); ;extern "C" cothread_t fastcall co_init();
;return = eax
;***** ;*****
align 16 align 16
co_init: co_init:
cmp dword[co_initialized],0 ;only run co_init once ;create context for main cothread
jne .end
inc dword[co_initialized]
;create context for main thread
mov ecx,0 ;entry point for main thread is not needed mov ecx,0 ;entry point for main thread is not needed
mov edx,256 ;main thread uses default program stack mov edx,512 ;main cothread uses default program stack
call co_create call co_create
mov dword[co_active_context],eax mov dword[co_active_context],eax
.end mov dword[co_primary_context],eax
ret ret
;***** ;*****
@@ -72,24 +80,22 @@ co_init:
align 16 align 16
co_term: co_term:
mov ecx,dword[co_primary_context]
call co_delete
ret ret
;***** ;*****
;extern "C" thread_t fastcall co_active(); ;extern "C" cothread_t fastcall co_active();
;return = eax ;return = eax
;***** ;*****
align 16 align 16
co_active: co_active:
cmp dword[co_initialized],0 ;make sure co_init has been called
jne .next
call co_init
.next:
mov eax,dword[co_active_context] mov eax,dword[co_active_context]
ret ret
;***** ;*****
;extern "C" thread_t fastcall co_create(thread_p coentry, unsigned int heapsize); ;extern "C" cothread_t fastcall co_create(cothread_p coentry, unsigned int heapsize);
;ecx = coentry ;ecx = coentry
;edx = heapsize ;edx = heapsize
;return = eax ;return = eax
@@ -97,17 +103,8 @@ co_active:
align 16 align 16
co_create: co_create:
cmp dword[co_initialized],0 ;make sure co_init has been called
jne .next
push ecx
push edx
call co_init
pop edx
pop ecx
.next:
;create heap space (stack + register storage) ;create heap space (stack + register storage)
add edx,28 ;+8(esp+prev_call_context)+4(coentry)+16(stack_align) add edx,512 ;+4(esp)+4(coentry)+4(colink)+256(stack_align)
push ecx push ecx
push edx push edx
@@ -119,10 +116,10 @@ co_create:
pop ecx pop ecx
add edx,eax ;set edx to point to top of stack heap add edx,eax ;set edx to point to top of stack heap
and edx,0xfffffff0 ;force 16-byte alignment of stack heap and edx,0xffffff00 ;force 256-byte alignment of stack heap
;store thread entry point + registers so that first call to co_jump will go to coentry ;store thread entry point + registers so that first call to co_switch will execute coentry
mov dword[edx-4],ecx ;edx=*stack,ecx=coentry mov dword[edx-4],co_entrypoint ;edx=*stack
mov dword[edx-8],0 mov dword[edx-8],0
mov dword[edx-12],0 mov dword[edx-12],0
mov dword[edx-16],0 mov dword[edx-16],0
@@ -130,13 +127,15 @@ co_create:
sub edx,20 sub edx,20
;initialize context memory heap ;initialize context memory heap
mov dword[eax],edx ;thread_t[0-3] = stack heap pointer (esp) mov dword[eax],edx ;cothread_t[ 0- 3] = stack heap pointer (esp)
mov dword[eax+4],0 ;thread_t[4-7] = (null) pointer to prev_call_context mov dword[eax+4],ecx ;cothread_t[ 4- 7] = entry point
mov ecx,dword[co_active_context]
mov dword[eax+8],ecx ;cothread_t[ 8-11] = return context
ret ;return allocated memory block as thread handle ret ;return allocated memory block as thread handle
;***** ;*****
;extern "C" void fastcall co_delete(thread_t cothread); ;extern "C" void fastcall co_delete(cothread_t cothread);
;ecx = cothread ;ecx = cothread
;***** ;*****
@@ -148,12 +147,12 @@ co_delete:
ret ret
;***** ;*****
;extern "C" void fastcall co_jump(thread_t cothread); ;extern "C" void fastcall co_switch(cothread_t cothread);
;ecx = cothread ;ecx = cothread
;***** ;*****
align 16 align 16
co_jump: co_switch:
mov eax,dword[co_active_context] ;backup current context mov eax,dword[co_active_context] ;backup current context
mov dword[co_active_context],ecx ;set new active context mov dword[co_active_context],ecx ;set new active context
@@ -172,50 +171,27 @@ co_jump:
ret ret
;***** ;*****
;extern "C" void fastcall co_call(thread_t cothread); ;extern "C" void fastcall co_exit(cothread_t cothread);
;ecx = cothread ;ecx = cothread
;***** ;*****
align 16 align 16
co_call: co_exit:
mov eax,dword[co_active_context] ;backup current context cmp ecx,0
mov dword[co_active_context],ecx ;set new active context jne co_switch
mov dword[ecx+4],eax
push ebp ;if cothread is null, switch to context that created current context
push esi mov eax,dword[co_active_context]
push edi mov ecx,dword[eax+8]
push ebx jmp co_switch
mov dword[eax],esp
mov esp,dword[ecx]
pop ebx
pop edi
pop esi
pop ebp
ret
;***** ;*****
;extern "C" void fastcall co_return(); ;void fastcall co_entrypoint();
;***** ;*****
align 16 align 16
co_return: co_entrypoint:
mov eax,dword[co_active_context] ;backup current context mov eax,dword[co_active_context]
mov ecx,dword[eax+4] ;restore pre-call context call dword[eax+4]
mov dword[co_active_context],ecx ;set new active context xor ecx,ecx
jmp co_exit
push ebp
push esi
push edi
push ebx
mov dword[eax],esp
mov esp,dword[ecx]
pop ebx
pop edi
pop esi
pop ebp
ret

View File

@@ -1,15 +1,20 @@
/* /*
libco_x86 : version 0.06 ~byuu (05/21/2006) libco_x86 : version 0.08 ~byuu (10/21/2006)
*/ */
typedef void (*thread_t); #define COTHREAD_STACKSIZE_TINY 0x1000
typedef void (*thread_p)(); #define COTHREAD_STACKSIZE_SMALL 0x4000
#define COTHREAD_STACKSIZE_NORMAL 0x10000
#define COTHREAD_STACKSIZE_LARGE 0x40000
#define COTHREAD_STACKSIZE_HUGE 0x100000
extern "C" void fastcall co_init(); typedef void (*cothread_t);
extern "C" void fastcall co_term(); typedef void (*cothread_p)(void);
extern "C" thread_t fastcall co_active();
extern "C" thread_t fastcall co_create(thread_p coentry, unsigned int heapsize); extern "C" cothread_t fastcall co_init();
extern "C" void fastcall co_delete(thread_t cothread); extern "C" void fastcall co_term();
extern "C" void fastcall co_jump(thread_t cothread); extern "C" cothread_t fastcall co_active();
extern "C" void fastcall co_call(thread_t cothread); extern "C" cothread_t fastcall co_create(cothread_p coentry, unsigned int heapsize);
extern "C" void fastcall co_return(); extern "C" void fastcall co_delete(cothread_t cothread);
extern "C" void fastcall co_switch(cothread_t cothread);
extern "C" void fastcall co_exit(cothread_t cothread);

View File

@@ -14,7 +14,7 @@ void Setting::set(uint _data) {
data = _data; data = _data;
switch(type) { switch(type) {
case TRUE_FALSE: case BOOL:
case ENABLED_DISABLED: case ENABLED_DISABLED:
case ON_OFF: case ON_OFF:
case YES_NO: case YES_NO:
@@ -32,22 +32,20 @@ void Setting::set(uint _data) {
} }
} }
char *Setting::sget() { char *Setting::strget() {
return strptr(char_data); return strptr(char_data);
} }
void Setting::sset(const char *_data) { void Setting::strset(const char *_data) {
strcpy(char_data, _data); strcpy(char_data, _data);
strunquote(char_data);
} }
Setting::Setting(Config *_parent, char *_name, char *_desc, uint _data, uint _type) { Setting::Setting(Config *_parent, char *_name, char *_desc, uint _data, uint _type) {
int s;
if(_parent) { if(_parent) {
_parent->add(this); _parent->add(this);
} }
s = strlen(_name); uint s = strlen(_name);
name = (char*)malloc(s + 1); name = (char*)malloc(s + 1);
strcpy(name, _name); strcpy(name, _name);
@@ -66,12 +64,11 @@ int s;
} }
Setting::Setting(Config *_parent, char *_name, char *_desc, char *_data) { Setting::Setting(Config *_parent, char *_name, char *_desc, char *_data) {
int s;
if(_parent) { if(_parent) {
_parent->add(this); _parent->add(this);
} }
s = strlen(_name); uint s = strlen(_name);
name = (char*)malloc(s + 1); name = (char*)malloc(s + 1);
strcpy(name, _name); strcpy(name, _name);
@@ -87,7 +84,7 @@ int s;
strcpy(char_data, _data); strcpy(char_data, _data);
strcpy(char_def, _data); strcpy(char_def, _data);
type = STR; type = STRING;
} }
void Config::add(Setting *setting) { void Config::add(Setting *setting) {
@@ -95,18 +92,18 @@ void Config::add(Setting *setting) {
} }
uint Config::string_to_uint(uint type, char *input) { uint Config::string_to_uint(uint type, char *input) {
if(strmatch(input, "true") || if(!strcmp(input, "true") ||
strmatch(input, "enabled") || !strcmp(input, "enabled") ||
strmatch(input, "on") || !strcmp(input, "on") ||
strmatch(input, "yes") !strcmp(input, "yes")
) { ) {
return (uint)true; return (uint)true;
} }
if(strmatch(input, "false") || if(!strcmp(input, "false") ||
strmatch(input, "disabled") || !strcmp(input, "disabled") ||
strmatch(input, "off") || !strcmp(input, "off") ||
strmatch(input, "no") !strcmp(input, "no")
) { ) {
return (uint)false; return (uint)false;
} }
@@ -121,7 +118,7 @@ uint Config::string_to_uint(uint type, char *input) {
char *Config::uint_to_string(uint type, uint input) { char *Config::uint_to_string(uint type, uint input) {
static char output[512]; static char output[512];
switch(type) { switch(type) {
case Setting::TRUE_FALSE: case Setting::BOOL:
sprintf(output, "%s", (input & 1) ? "true" : "false"); sprintf(output, "%s", (input & 1) ? "true" : "false");
break; break;
case Setting::ENABLED_DISABLED: case Setting::ENABLED_DISABLED:
@@ -144,7 +141,7 @@ static char output[512];
return output; return output;
} }
bool Config::load(char *fn) { bool Config::load(const char *fn) {
FILE *fp; FILE *fp;
fp = fopen(fn, "rb"); fp = fopen(fn, "rb");
if(!fp)return false; if(!fp)return false;
@@ -172,11 +169,12 @@ char *buffer = (char*)malloc(fsize + 1);
qsplit(part, "=", line[i]); qsplit(part, "=", line[i]);
for(int l = 0; l < list_count; l++) { for(int l = 0; l < list_count; l++) {
if(strmatch(list[l]->name, part[0])) { if(!strcmp(list[l]->name, part[0])) {
if(list[l]->type != Setting::STR) { if(list[l]->type != Setting::STR) {
list[l]->set(string_to_uint(list[l]->type, strptr(part[1]))); list[l]->set(string_to_uint(list[l]->type, strptr(part[1])));
} else { } else {
list[l]->sset(strptr(part[1])); list[l]->strset(strptr(part[1]));
strunquote(list[l]->char_data);
} }
} }
} }
@@ -186,7 +184,7 @@ char *buffer = (char*)malloc(fsize + 1);
} }
bool Config::load(string &fn) { return load(strptr(fn)); } bool Config::load(string &fn) { return load(strptr(fn)); }
bool Config::save(char *fn) { bool Config::save(const char *fn) {
FILE *fp; FILE *fp;
fp = fopen(fn, "wb"); fp = fopen(fn, "wb");
if(!fp)return false; if(!fp)return false;
@@ -198,7 +196,7 @@ FILE *fp;
for(int l = 0; l < count(line); l++) { for(int l = 0; l < count(line); l++) {
fprintf(fp, "# %s\r\n", strptr(line[l])); fprintf(fp, "# %s\r\n", strptr(line[l]));
} }
if(list[i]->type != Setting::STR) { if(list[i]->type != Setting::STRING) {
fprintf(fp, "# (default = %s)\r\n", uint_to_string(list[i]->type, list[i]->def)); fprintf(fp, "# (default = %s)\r\n", uint_to_string(list[i]->type, list[i]->def));
fprintf(fp, "%s = %s\r\n\r\n", list[i]->name, uint_to_string(list[i]->type, list[i]->data)); fprintf(fp, "%s = %s\r\n\r\n", list[i]->name, uint_to_string(list[i]->type, list[i]->data));
} else { } else {
@@ -207,6 +205,7 @@ FILE *fp;
} }
} }
fclose(fp);
return true; return true;
} }
bool Config::save(string &fn) { return save(strptr(fn)); } bool Config::save(string &fn) { return save(strptr(fn)); }

View File

@@ -1,5 +1,5 @@
/* /*
libconfig : version 0.10 ~byuu (10/10/06) libconfig : version 0.11 ~byuu (2006/11/12)
*/ */
#ifndef __LIBCONFIG #ifndef __LIBCONFIG
@@ -30,16 +30,18 @@ enum {
HEX16 = 7, HEX16 = 7,
HEX24 = 8, HEX24 = 8,
HEX32 = 9, HEX32 = 9,
STRING = 10,
STR = 10, STR = 10,
}; };
char *name, *desc; char *name, *desc;
string char_data, char_def; string char_data, char_def;
virtual void toggle(); virtual void toggle();
virtual uint get(); virtual uint get();
virtual void set(uint _data); virtual void set(uint _data);
virtual char *sget(); virtual char *strget();
virtual void sset(const char *_data); virtual void strset(const char *_data);
Setting(Config *_parent, char *_name, char *_desc, uint _data, uint _type); Setting(Config *_parent, char *_name, char *_desc, uint _data, uint _type);
Setting(Config *_parent, char *_name, char *_desc, char *_data); Setting(Config *_parent, char *_name, char *_desc, char *_data);
@@ -52,6 +54,12 @@ string char_data, char_def;
template<typename T> inline bool operator> (const T &x) { return (T)get() > x; } template<typename T> inline bool operator> (const T &x) { return (T)get() > x; }
template<typename T> inline bool operator<=(const T &x) { return (T)get() <= x; } template<typename T> inline bool operator<=(const T &x) { return (T)get() <= x; }
template<typename T> inline bool operator< (const T &x) { return (T)get() < x; } template<typename T> inline bool operator< (const T &x) { return (T)get() < x; }
inline operator char*() { return strget(); }
inline Setting &operator=(char *x) { strset(x); return *this; }
inline Setting &operator=(const char *x) { strset(x); return *this; }
inline bool operator==(const char *x) { return !strcmp(strget(), x); }
inline bool operator!=(const char *x) { return strcmp(strget(), x); }
}; };
class Config { class Config {
@@ -67,9 +75,9 @@ char *uint_to_string(uint type, uint input);
public: public:
void add(Setting *setting); void add(Setting *setting);
bool load(char *fn); bool load(const char *fn);
bool load(string &fn); bool load(string &fn);
bool save(char *fn); bool save(const char *fn);
bool save(string &fn); bool save(string &fn);
Config(); Config();
}; };

View File

@@ -1,5 +1,5 @@
/* /*
libfile : version 0.05 ~byuu (10/12/06) libfile : version 0.05a ~byuu (10/26/06)
*/ */
#ifndef __LIBFILE #ifndef __LIBFILE
@@ -51,10 +51,12 @@ uint32 crc32 = 0xffffffff;
inline void fread(file &s, uint8 *data, uint length) { s.read(data, length); } inline void fread(file &s, uint8 *data, uint length) { s.read(data, length); }
inline uint8 fread(file &s) { return s.read(); } inline uint8 fread(file &s) { return s.read(); }
inline uint8 fgetc(file &s) { return s.read(); } inline uint8 fgetc(file &s) { return s.read(); }
inline uint fgetb(file &s) { return s.read(); }
inline void fwrite(file &s, uint8 *data, uint length) { s.write(data, length); } inline void fwrite(file &s, uint8 *data, uint length) { s.write(data, length); }
inline void fwrite(file &s, uint8 data) { s.write(data); } inline void fwrite(file &s, uint8 data) { s.write(data); }
inline void fputc(file &s, uint8 data) { s.write(data); } inline void fputc(uint8 data, file &s) { s.write(data); }
inline void fputb(file &s, uint8 data) { s.write(data); }
inline uint32 fcrc32(file &s) { return s.crc32(); } inline uint32 fcrc32(file &s) { return s.crc32(); }
@@ -107,53 +109,53 @@ inline uint64 fgetmq(file &s) {
((uint64)fgetc(s) << 8) | ((uint64)fgetc(s) << 0); ((uint64)fgetc(s) << 8) | ((uint64)fgetc(s) << 0);
} }
inline void fputlb(file &s, uint8 data) { fputc(s, data); } inline void fputlb(file &s, uint8 data) { fputc(data, s); }
inline void fputmb(file &s, uint8 data) { fputc(s, data); } inline void fputmb(file &s, uint8 data) { fputc(data, s); }
inline void fputlw(file &s, uint16 data) { inline void fputlw(file &s, uint16 data) {
fputc(s, data >> 0); fputc(data >> 0, s);
fputc(s, data >> 8); fputc(data >> 8, s);
} }
inline void fputmw(file &s, uint16 data) { inline void fputmw(file &s, uint16 data) {
fputc(s, data >> 8); fputc(data >> 8, s);
fputc(s, data >> 0); fputc(data >> 0, s);
} }
inline void fputld(file &s, uint32 data) { inline void fputld(file &s, uint32 data) {
fputc(s, data >> 0); fputc(data >> 0, s);
fputc(s, data >> 8); fputc(data >> 8, s);
fputc(s, data >> 16); fputc(data >> 16, s);
fputc(s, data >> 24); fputc(data >> 24, s);
} }
inline void fputmd(file &s, uint32 data) { inline void fputmd(file &s, uint32 data) {
fputc(s, data >> 24); fputc(data >> 24, s);
fputc(s, data >> 16); fputc(data >> 16, s);
fputc(s, data >> 8); fputc(data >> 8, s);
fputc(s, data >> 0); fputc(data >> 0, s);
} }
inline void fputlq(file &s, uint64 data) { inline void fputlq(file &s, uint64 data) {
fputc(s, data >> 0); fputc(data >> 0, s);
fputc(s, data >> 8); fputc(data >> 8, s);
fputc(s, data >> 16); fputc(data >> 16, s);
fputc(s, data >> 24); fputc(data >> 24, s);
fputc(s, data >> 32); fputc(data >> 32, s);
fputc(s, data >> 40); fputc(data >> 40, s);
fputc(s, data >> 48); fputc(data >> 48, s);
fputc(s, data >> 56); fputc(data >> 56, s);
} }
inline void fputmq(file &s, uint64 data) { inline void fputmq(file &s, uint64 data) {
fputc(s, data >> 56); fputc(data >> 56, s);
fputc(s, data >> 48); fputc(data >> 48, s);
fputc(s, data >> 40); fputc(data >> 40, s);
fputc(s, data >> 32); fputc(data >> 32, s);
fputc(s, data >> 24); fputc(data >> 24, s);
fputc(s, data >> 16); fputc(data >> 16, s);
fputc(s, data >> 8); fputc(data >> 8, s);
fputc(s, data >> 0); fputc(data >> 0, s);
} }
/***** /*****

34
src/lib/libsort.h Normal file
View File

@@ -0,0 +1,34 @@
/*
libsort : version 0.01 ~byuu (2006-11-15)
*/
#ifndef __LIBSORT
#define __LIBSORT
template<typename T>
void sort(T list[], uint length) {
for(uint d = 0; d < length; d++) {
uint min = d;
for(uint s = d + 1; s < length; s++) {
if(list[s] < list[min]) { min = s; }
}
if(min != d) {
swap(list[d], list[min]);
}
}
}
template<typename T, typename Tcmp>
void sort(T list[], uint length, Tcmp comparator) {
for(uint d = 0; d < length; d++) {
uint min = d;
for(uint s = d + 1; s < length; s++) {
if(comparator(list[s], list[min]) == true) { min = s; }
}
if(min != d) {
swap(list[d], list[min]);
}
}
}
#endif __LIBSORT

View File

@@ -1,5 +1,6 @@
#include "libbase.h" #include "libbase.h"
#include "libstring.h" #include "libstring.h"
#include "libstring_oo.cpp"
uint count(stringarray &str) { return str.size(); } uint count(stringarray &str) { return str.size(); }
@@ -13,12 +14,6 @@ char chrupper(char c) {
return c; return c;
} }
void strresize(string &str, uint size) {
str.s = (char*)realloc(str.s, size + 1);
str.s[size] = 0;
str.size = size;
}
char *strptr(string &str) { return str.s; } char *strptr(string &str) { return str.s; }
uint strlen(string &str) { return strlen(strptr(str)); } uint strlen(string &str) { return strlen(strptr(str)); }
@@ -39,49 +34,41 @@ int stricmp(string &dest, const char *src) { return __stricmp(strptr(dest), src)
int stricmp(const char *dest, string &src) { return __stricmp(dest, strptr(src)); } int stricmp(const char *dest, string &src) { return __stricmp(dest, strptr(src)); }
int stricmp(string &dest, string &src) { return __stricmp(strptr(dest), strptr(src)); } int stricmp(string &dest, string &src) { return __stricmp(strptr(dest), strptr(src)); }
bool strmatch(const char *dest, const char *src) { return !strcmp(dest, src); }
bool strmatch(string &dest, const char *src) { return strmatch(strptr(dest), src); }
bool strmatch(const char *dest, string &src) { return strmatch(dest, strptr(src)); }
bool strmatch(string &dest, string &src) { return strmatch(strptr(dest), strptr(src)); }
bool strimatch(const char *dest, const char *src) { return !stricmp(dest, src); }
bool strimatch(string &dest, const char *src) { return strimatch(strptr(dest), src); }
bool strimatch(const char *dest, string &src) { return strimatch(dest, strptr(src)); }
bool strimatch(string &dest, string &src) { return strimatch(strptr(dest), strptr(src)); }
void strcpy(string &dest, const char src) { void strcpy(string &dest, const char src) {
if(1 > dest.size) { strresize(dest, 1); } dest.reserve(2);
dest.s[0] = src; dest.s[0] = src;
dest.s[1] = 0; dest.s[1] = 0;
} }
void strcpy(string &dest, const char *src) { void strcpy(string &dest, const char *src) {
int srclen = strlen(src); int srclen = strlen(src);
if(srclen > dest.size) { strresize(dest, srclen); } dest.reserve(srclen);
strcpy(dest.s, src); strcpy(dest.s, src);
} }
void strcpy(string &dest, string &src) { strcpy(dest, strptr(src)); } void strcpy(string &dest, string &src) { strcpy(dest, strptr(src)); }
//this differs from libc's strncpy in that it always uint strlcpy(char *dest, const char *src, uint length) {
//appends a null terminator to the end of a copied string uint srclen = strlen(src);
void strncpy(string &dest, const char *src, uint32 length) { length--;
int srclen = strlen(src); if(length > srclen)length = srclen;
//never copy more text than is in the string memcpy(dest, src, length);
if(srclen > length)srclen = length; dest[length] = 0;
if(srclen > dest.size) { strresize(dest, srclen); } return srclen;
strncpy(dest.s, src, srclen);
dest.s[srclen] = 0;
} }
void strncpy(string &dest, string &src, uint32 length) { strncpy(dest, strptr(src), length); }
void strset(string &dest, uint pos, uint8 c) { uint strlcpy(string &dest, const char *src, uint length) {
if(pos > dest.size) { strresize(dest, pos); } dest.reserve(length);
dest.s[pos] = c; return strlcpy(strptr(dest), src, length);
}
uint strlcpy(string &dest, string &src, uint length) {
dest.reserve(length);
return strlcpy(strptr(dest), strptr(src), length);
} }
void strcat(string &dest, const char src) { void strcat(string &dest, const char src) {
int length = strlen(dest); int length = strlen(dest);
if(length + 1 > dest.size) { strresize(dest, length + 1); } dest.reserve(length + 1);
dest.s[length] = src; dest.s[length] = src;
dest.s[length + 1] = 0; dest.s[length + 1] = 0;
} }
@@ -89,32 +76,62 @@ int length = strlen(dest);
void strcat(string &dest, const char *src) { void strcat(string &dest, const char *src) {
int srclen = strlen(src); int srclen = strlen(src);
int destlen = strlen(dest); int destlen = strlen(dest);
if(srclen + destlen > dest.size) { strresize(dest, srclen + destlen); } dest.reserve(srclen + destlen);
strcat(dest.s, src); strcat(dest.s, src);
} }
void strcat(string &dest, string &src) { strcat(dest, strptr(src)); } void strcat(string &dest, string &src) { strcat(dest, strptr(src)); }
uint strlcat(char *dest, const char *src, uint length) {
uint destlen = strlen(dest), srclen = strlen(src);
length--;
if(length > destlen + srclen)length = destlen + srclen;
memcpy(dest + destlen, src, length - destlen);
dest[length] = 0;
return destlen + srclen;
}
uint strlcat(string &dest, const char *src, uint length) {
dest.reserve(length);
return strlcat(strptr(dest), src, length);
}
uint strlcat(string &dest, string &src, uint length) {
dest.reserve(length);
return strlcat(strptr(dest), strptr(src), length);
}
string substr(string &dest, const char *src, uint start, uint length) {
string temp;
if(length == 0) {
//copy entire string
strcpy(temp, src + start);
} else {
//copy partial string
strlcpy(temp, src + start, length + 1);
}
return temp;
}
string substr(string &dest, string &src, uint start, uint length) { return substr(dest, strptr(src), start, length); }
void strinsert(string &dest, const char *src, uint pos) { void strinsert(string &dest, const char *src, uint pos) {
static string s; string temp;
strcpy(s, strptr(dest) + pos); strcpy(temp, strptr(dest) + pos);
strset(dest, pos, 0); dest[pos] = 0;
strcat(dest, src); strcat(dest, src);
strcat(dest, s); strcat(dest, temp);
} }
void strinsert(string &dest, string &src, uint pos) { strinsert(dest, strptr(src), pos); } void strinsert(string &dest, string &src, uint pos) { strinsert(dest, strptr(src), pos); }
void strremove(string &dest, uint start, uint length) { void strremove(string &dest, uint start, uint length) {
int destlen; int i, destlen = strlen(dest);
char *s; dest.reserve(start);
int i, sl = strlen(dest.s);
if(start > dest.size) { strresize(dest, start); }
if(!length) { if(!length) {
strset(dest, start, 0); dest[start] = 0;
return; return;
} }
s = dest.s; for(i = start; i < destlen; i++) { dest.s[i] = dest.s[i + length]; }
for(i=start;i<sl;i++) { s[i] = s[i+length]; } dest.s[i] = 0;
s[i] = 0;
} }
char *strlower(char *str) { char *strlower(char *str) {
@@ -401,7 +418,7 @@ uint mask = 1000000000;
} }
string &utoa(string &str, uint num) { string &utoa(string &str, uint num) {
if(str.size < 16) { strresize(str, 16); } str.reserve(16);
utoa(strptr(str), num); utoa(strptr(str), num);
return str; return str;
} }
@@ -418,7 +435,7 @@ char *pstr = str;
} }
string &itoa(string &str, uint num) { string &itoa(string &str, uint num) {
if(str.size < 16) { strresize(str, 16); } str.reserve(16);
itoa(strptr(str), num); itoa(strptr(str), num);
return str; return str;
} }
@@ -441,7 +458,7 @@ uint mask = 28, r;
} }
string &htoa(string &str, uint num) { string &htoa(string &str, uint num) {
if(str.size < 16) { strresize(str, 16); } str.reserve(16);
htoa(strptr(str), num); htoa(strptr(str), num);
return str; return str;
} }
@@ -464,7 +481,7 @@ uint mask = 28, r;
} }
string &uhtoa(string &str, uint num) { string &uhtoa(string &str, uint num) {
if(str.size < 16) { strresize(str, 16); } str.reserve(16);
uhtoa(strptr(str), num); uhtoa(strptr(str), num);
return str; return str;
} }
@@ -485,7 +502,7 @@ uint mask = 0x80000000;
} }
string &btoa(string &str, uint num) { string &btoa(string &str, uint num) {
if(str.size < 48) { strresize(str, 48); } str.reserve(48);
btoa(strptr(str), num); btoa(strptr(str), num);
return str; return str;
} }
@@ -507,6 +524,7 @@ char *fdata = (char*)malloc(size + 1);
return true; return true;
} }
#include "libstring_int.cpp"
#include "libstring_math.cpp" #include "libstring_math.cpp"
#include "libstring_split.cpp" #include "libstring_split.cpp"
#include "libstring_replace.cpp" #include "libstring_replace.cpp"

View File

@@ -1,5 +1,5 @@
/* /*
libstring : version 0.12 ~byuu (10/05/06) libstring : version 0.14b ~byuu (2006/11/17)
*/ */
#ifndef __LIBSTRING #ifndef __LIBSTRING
@@ -15,10 +15,7 @@ char chrupper(char c);
uint count(stringarray &str); uint count(stringarray &str);
void strresize(string &str, uint size); char *strptr(string &str);
char* strptr(string &str);
uint strlen(string &str); uint strlen(string &str);
int strcmp(string &dest, const char *src); int strcmp(string &dest, const char *src);
@@ -34,26 +31,21 @@ int stricmp(string &dest, const char *src);
int stricmp(const char *dest, string &src); int stricmp(const char *dest, string &src);
int stricmp(string &dest, string &src); int stricmp(string &dest, string &src);
bool strmatch(const char *dest, const char *src);
bool strmatch(string &dest, const char *src);
bool strmatch(const char *dest, string &src);
bool strmatch(string &dest, string &src);
bool strimatch(const char *dest, const char *src);
bool strimatch(string &dest, const char *src);
bool strimatch(const char *dest, string &src);
bool strimatch(string &dest, string &src);
void strcpy(string &dest, const char *src); void strcpy(string &dest, const char *src);
void strcpy(string &dest, string &src); void strcpy(string &dest, string &src);
void strncpy(string &dest, const char *src, uint32 length); uint strlcpy(char *dest, const char *src, uint length);
void strncpy(string &dest, string &src, uint32 length); uint strlcpy(string &dest, const char *src, uint length);
uint strlcpy(string &dest, string &src, uint length);
void strset(string &dest, uint pos, uint8 c);
void strcat(string &dest, const char src); void strcat(string &dest, const char src);
void strcat(string &dest, const char *src); void strcat(string &dest, const char *src);
void strcat(string &dest, string &src); void strcat(string &dest, string &src);
uint strlcat(char *dest, const char *src, uint length);
uint strlcat(string &dest, const char *src, uint length);
uint strlcat(string &dest, string &src, uint length);
string substr(string &dest, const char *src, uint start = 0, uint length = 0);
string substr(string &dest, string &src, uint start = 0, uint length = 0);
void strinsert(string &dest, const char *src, uint pos); void strinsert(string &dest, const char *src, uint pos);
void strinsert(string &dest, string &src, uint pos); void strinsert(string &dest, string &src, uint pos);
@@ -143,6 +135,8 @@ string &btoa(string &str, uint num);
bool strfread(string &str, const char *filename); bool strfread(string &str, const char *filename);
string strfmt(const char *fmt, int num);
int strmath(const char *in_str); int strmath(const char *in_str);
int strmath(string &in_str); int strmath(string &in_str);
@@ -165,20 +159,68 @@ class string {
public: public:
char *s; char *s;
uint size; uint size;
void reserve(uint reqsize) {
if(reqsize > size) {
size = reqsize;
s = (char*)realloc(s, size + 1);
s[size] = 0;
}
}
void swap(string &str) {
::swap(s, str.s);
::swap(size, str.size);
}
string() { string() {
size = 16; size = 16;
s = (char*)malloc(size + 1); s = (char*)malloc(size + 1);
*s = 0; s[0] = 0;
} }
~string() { SafeFree(s); } string(const char *str) {
size = strlen(str);
void operator=(const string &p) {
SafeFree(s);
size = p.size;
s = (char*)malloc(size + 1); s = (char*)malloc(size + 1);
strcpy(s, p.s); strcpy(s, str);
} }
string(string &str) {
size = strlen(str);
s = (char*)malloc(size + 1);
strcpy(s, strptr(str));
}
~string() { safe_free(s); }
const char *operator()();
char &operator[](uint);
string &operator=(int);
string &operator=(const char *);
string &operator=(string &);
string &operator+=(int);
string &operator+=(const char *);
string &operator+=(string &);
bool operator==(const char *);
bool operator==(string &);
bool operator!=(const char *);
bool operator!=(string &);
bool operator<(const char *);
bool operator<(string &);
bool operator<=(const char *);
bool operator<=(string &);
bool operator>(const char *);
bool operator>(string &);
bool operator>=(const char *);
bool operator>=(string &);
string operator+(int);
string operator+(const char *);
string operator+(string &);
}; };
string operator+(int, string &);
string operator+(const char *, string &);
inline void swap(string &x, string &y) { x.swap(y); }
#endif //__LIBSTRING #endif //__LIBSTRING

View File

@@ -0,0 +1,5 @@
string strfmt(const char *fmt, int num) {
string temp;
sprintf(temp, fmt, num);
return temp;
}

83
src/lib/libstring_oo.cpp Normal file
View File

@@ -0,0 +1,83 @@
const char *string::operator()() {
return s;
}
char &string::operator[](const uint index) {
reserve(index);
return s[index];
}
string &string::operator=(int num) {
strcpy(*this, strfmt("%d", num));
return *this;
}
string &string::operator=(const char *str) {
strcpy(*this, str);
return *this;
}
string &string::operator=(string &str) {
strcpy(*this, str);
return *this;
}
string &string::operator+=(int num) {
strcat(*this, strfmt("%d", num));
return *this;
}
string &string::operator+=(const char *str) {
strcat(*this, str);
return *this;
}
string &string::operator+=(string &str) {
strcat(*this, str);
return *this;
}
bool string::operator==(const char *str) { return strcmp(strptr(*this), str) == 0; }
bool string::operator==(string &str) { return strcmp(strptr(*this), strptr(str)) == 0; }
bool string::operator!=(const char *str) { return strcmp(strptr(*this), str) != 0; }
bool string::operator!=(string &str) { return strcmp(strptr(*this), strptr(str)) != 0; }
bool string::operator<(const char *str) { return strcmp(strptr(*this), str) < 0; }
bool string::operator<(string &str) { return strcmp(strptr(*this), strptr(str)) < 0; }
bool string::operator<=(const char *str) { return strcmp(strptr(*this), str) <= 0; }
bool string::operator<=(string &str) { return strcmp(strptr(*this), strptr(str)) <= 0; }
bool string::operator>(const char *str) { return strcmp(strptr(*this), str) > 0; }
bool string::operator>(string &str) { return strcmp(strptr(*this), strptr(str)) > 0; }
bool string::operator>=(const char *str) { return strcmp(strptr(*this), str) >= 0; }
bool string::operator>=(string &str) { return strcmp(strptr(*this), strptr(str)) >= 0; }
string string::operator+(int num) {
string temp(*this);
strcat(temp, strfmt("%d", num));
return temp;
}
string string::operator+(const char *str) {
string temp(*this);
strcat(temp, str);
return temp;
}
string string::operator+(string &str) {
string temp(*this);
strcat(temp, str);
return temp;
}
//
string operator+(int x, string &y) {
string temp(strfmt("%d", x));
strcat(temp, y);
return temp;
}
string operator+(const char *x, string &y) {
string temp(x);
strcat(temp, y);
return temp;
}

View File

@@ -4,17 +4,17 @@ uint replace_count = 0, size = ssl;
char *data; char *data;
if(ksl > ssl)return str; if(ksl > ssl)return str;
if(tsl > ksl) { //the new string may be longer than the old string... if(tsl > ksl) { //the new string may be longer than the old string...
for(i=0;i<=ssl-ksl;) { //so let's find out how big of a string we'll need... for(i = 0; i <= ssl - ksl;) { //so let's find out how big of a string we'll need...
if(!memcmp(str.s + i, key, ksl)) { if(!memcmp(str.s + i, key, ksl)) {
replace_count++; replace_count++;
i += ksl; i += ksl;
} else i++; } else i++;
} }
size = ssl + ((tsl - ksl) * replace_count); size = ssl + ((tsl - ksl) * replace_count);
if(size > str.size)strresize(str, size); str.reserve(size);
} }
data = (char*)malloc(size + 1); data = (char*)malloc(size + 1);
for(i=z=0;i<ssl;) { for(i = z = 0; i < ssl;) {
if(i <= ssl - ksl) { if(i <= ssl - ksl) {
if(!memcmp(str.s + i, key, ksl)) { if(!memcmp(str.s + i, key, ksl)) {
memcpy(data + z, token, tsl); memcpy(data + z, token, tsl);
@@ -37,7 +37,7 @@ uint8 x;
char *data; char *data;
if(ksl > ssl)return str; if(ksl > ssl)return str;
if(tsl > ksl) { if(tsl > ksl) {
for(i=0;i<=ssl-ksl;) { for(i = 0; i <= ssl - ksl;) {
x = str.s[i]; x = str.s[i];
if(x == '\"' || x == '\'') { if(x == '\"' || x == '\'') {
l = i; l = i;
@@ -55,10 +55,10 @@ char *data;
} else i++; } else i++;
} }
size = ssl + ((tsl - ksl) * replace_count); size = ssl + ((tsl - ksl) * replace_count);
if(size > str.size)strresize(str, size); str.reserve(size);
} }
data = (char*)malloc(size + 1); data = (char*)malloc(size + 1);
for(i=z=0;i<ssl;) { for(i = z = 0; i < ssl;) {
x = str.s[i]; x = str.s[i];
if(x == '\"' || x == '\'') { if(x == '\"' || x == '\'') {
l = i++; l = i++;

View File

@@ -5,7 +5,7 @@ int ssl = strlen(src), ksl = strlen(key);
int lp = 0, split_count = 0; int lp = 0, split_count = 0;
for(int i = 0; i <= ssl - ksl;) { for(int i = 0; i <= ssl - ksl;) {
if(!memcmp(src + i, key, ksl)) { if(!memcmp(src + i, key, ksl)) {
strncpy(dest[split_count++], src + lp, i - lp); strlcpy(dest[split_count++], src + lp, i - lp + 1);
i += ksl; i += ksl;
lp = i; lp = i;
} else i++; } else i++;
@@ -27,7 +27,7 @@ int lp = 0, split_count = 0;
if(i >= ssl)i = z; if(i >= ssl)i = z;
} }
if(!memcmp(src + i, key, ksl)) { if(!memcmp(src + i, key, ksl)) {
strncpy(dest[split_count++], src + lp, i - lp); strlcpy(dest[split_count++], src + lp, i - lp + 1);
i += ksl; i += ksl;
lp = i; lp = i;
} else i++; } else i++;

View File

@@ -8,7 +8,7 @@ uint length = vsprintf(str, s, args);
uint vsprintf(string &str, const char *s, va_list args) { uint vsprintf(string &str, const char *s, va_list args) {
uint length = vsnprintf(0, 0, s, args); uint length = vsnprintf(0, 0, s, args);
strresize(str, length + 1); str.reserve(length + 1);
return vsprintf(strptr(str), s, args); return vsprintf(strptr(str), s, args);
} }

View File

@@ -226,33 +226,33 @@ uint ptr = 0;
template<typename FTO, typename FTM, typename FTP> template<typename FTO, typename FTM, typename FTP>
void UPS<FTO, FTM, FTP>::ptr_write(uint ptr) { void UPS<FTO, FTM, FTP>::ptr_write(uint ptr) {
if(ptr <= 0xf7) { if(ptr <= 0xf7) {
fputc(patch.fp, ptr); fputb(patch.fp, ptr);
return; return;
} }
ptr -= 0xf8; ptr -= 0xf8;
if(ptr <= 0xffff) { if(ptr <= 0xffff) {
fputc(patch.fp, 0xf8); fputb(patch.fp, 0xf8);
fputc(patch.fp, ptr); fputb(patch.fp, ptr);
fputc(patch.fp, ptr >> 8); fputb(patch.fp, ptr >> 8);
return; return;
} }
ptr -= 0x10000; ptr -= 0x10000;
if(ptr <= 0xffffff) { if(ptr <= 0xffffff) {
fputc(patch.fp, 0xf9); fputb(patch.fp, 0xf9);
fputc(patch.fp, ptr); fputb(patch.fp, ptr);
fputc(patch.fp, ptr >> 8); fputb(patch.fp, ptr >> 8);
fputc(patch.fp, ptr >> 16); fputb(patch.fp, ptr >> 16);
return; return;
} }
ptr -= 0x1000000; ptr -= 0x1000000;
fputc(patch.fp, 0xfa); fputb(patch.fp, 0xfa);
fputc(patch.fp, ptr); fputb(patch.fp, ptr);
fputc(patch.fp, ptr >> 8); fputb(patch.fp, ptr >> 8);
fputc(patch.fp, ptr >> 16); fputb(patch.fp, ptr >> 16);
fputc(patch.fp, ptr >> 24); fputb(patch.fp, ptr >> 24);
} }
template<typename FTO, typename FTM, typename FTP> template<typename FTO, typename FTM, typename FTP>
@@ -298,14 +298,14 @@ uint last_ptr = 0, rle_count, last_out, rep_count;
ptr_write((i - 1) - last_ptr); ptr_write((i - 1) - last_ptr);
//data //data
fputc(patch.fp, r); fputb(patch.fp, r);
last_out = r; last_out = r;
rep_count = 0; rep_count = 0;
do { do {
r = fgetc(original) ^ fgetc(modified); r = fgetc(original) ^ fgetc(modified);
i++; i++;
fputc(patch.fp, r); fputb(patch.fp, r);
if(last_out != r) { if(last_out != r) {
rep_count = 0; rep_count = 0;
@@ -319,7 +319,7 @@ uint last_ptr = 0, rle_count, last_out, rep_count;
} while(i < largest_filesize); } while(i < largest_filesize);
ptr_write(rle_count); ptr_write(rle_count);
if(i < largest_filesize) { fputc(patch.fp, r); } if(i < largest_filesize) { fputb(patch.fp, r); }
rep_count = 0; rep_count = 0;
} }
} }
@@ -331,7 +331,7 @@ uint last_ptr = 0, rle_count, last_out, rep_count;
last_ptr = i; last_ptr = i;
} }
fputc(patch.fp, 0xff); fputb(patch.fp, 0xff);
} }
template<typename FTO, typename FTM, typename FTP> template<typename FTO, typename FTM, typename FTP>
@@ -385,7 +385,7 @@ void UPS<FTO, FTM, FTP>::apply_linear() {
fseek(original, 0, file::seek_start); fseek(original, 0, file::seek_start);
fseek(modified, 0, file::seek_start); fseek(modified, 0, file::seek_start);
for(uint i = 0; i < modified_filesize; i++) { for(uint i = 0; i < modified_filesize; i++) {
fputc(modified, fgetc(original)); fputb(modified, fgetc(original));
} }
fseek(original, 0, file::seek_start); fseek(original, 0, file::seek_start);
@@ -408,14 +408,14 @@ uint rle_count, last_in, rep_count;
if(ftell(modified) >= modified_filesize) { break; } if(ftell(modified) >= modified_filesize) { break; }
uint8 r = fgetc(patch.fp); uint8 r = fgetc(patch.fp);
fputc(modified, r ^ fgetc(original)); fputb(modified, r ^ fgetc(original));
if(r != last_in) { if(r != last_in) {
rep_count = 0; rep_count = 0;
} else { } else {
if(++rep_count == (3 - 1)) { if(++rep_count == (3 - 1)) {
rle_count = ptr_read(); rle_count = ptr_read();
while(rle_count-- && ftell(modified) < modified_filesize) { while(rle_count-- && ftell(modified) < modified_filesize) {
fputc(modified, r ^ fgetc(original)); fputb(modified, r ^ fgetc(original));
} }
rep_count = 0; rep_count = 0;
} }

View File

@@ -14,12 +14,12 @@ bool Button::Create(Window *parent_window, const char *style, int x, int y, int
stringarray part; stringarray part;
ParseStyleParam(style, part); ParseStyleParam(style, part);
for(int i = 0; i < count(part); i++) { for(int i = 0; i < count(part); i++) {
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE; if(!strcmp(part[i], "visible"))state.ws |= WS_VISIBLE;
if(strmatch(part[i], "disabled"))state.ws |= WS_DISABLED; if(!strcmp(part[i], "disabled"))state.ws |= WS_DISABLED;
if(strmatch(part[i], "left"))state.ws |= BS_LEFT; if(!strcmp(part[i], "left"))state.ws |= BS_LEFT;
if(strmatch(part[i], "center"))state.ws |= BS_CENTER; if(!strcmp(part[i], "center"))state.ws |= BS_CENTER;
if(strmatch(part[i], "right"))state.ws |= BS_RIGHT; if(!strcmp(part[i], "right"))state.ws |= BS_RIGHT;
} }
hwnd = CreateWindowEx(state.es, "BUTTON", text, state.ws, hwnd = CreateWindowEx(state.es, "BUTTON", text, state.ws,

View File

@@ -20,13 +20,13 @@ bool Checkbox::Create(Window *parent_window, const char *style, int x, int y, in
stringarray part; stringarray part;
ParseStyleParam(style, part); ParseStyleParam(style, part);
for(int i = 0; i < count(part); i++) { for(int i = 0; i < count(part); i++) {
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE; if(!strcmp(part[i], "visible"))state.ws |= WS_VISIBLE;
if(strmatch(part[i], "disabled"))state.ws |= WS_DISABLED; if(!strcmp(part[i], "disabled"))state.ws |= WS_DISABLED;
if(strmatch(part[i], "left"))state.ws |= BS_LEFT; if(!strcmp(part[i], "left"))state.ws |= BS_LEFT;
if(strmatch(part[i], "center"))state.ws |= BS_CENTER; if(!strcmp(part[i], "center"))state.ws |= BS_CENTER;
if(strmatch(part[i], "right"))state.ws |= BS_RIGHT; if(!strcmp(part[i], "right"))state.ws |= BS_RIGHT;
if(strmatch(part[i], "auto"))state.ws |= BS_AUTOCHECKBOX; if(!strcmp(part[i], "auto"))state.ws |= BS_AUTOCHECKBOX;
} }
if(!(state.ws & BS_AUTOCHECKBOX))state.ws |= BS_CHECKBOX; if(!(state.ws & BS_AUTOCHECKBOX))state.ws |= BS_CHECKBOX;

View File

@@ -38,13 +38,13 @@ bool Combobox::Create(Window *parent_window, const char *style, int x, int y, in
stringarray part; stringarray part;
ParseStyleParam(style, part); ParseStyleParam(style, part);
for(int i = 0; i < count(part); i++) { for(int i = 0; i < count(part); i++) {
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE; if(!strcmp(part[i], "visible"))state.ws |= WS_VISIBLE;
if(strmatch(part[i], "disabled"))state.ws |= WS_DISABLED; if(!strcmp(part[i], "disabled"))state.ws |= WS_DISABLED;
if(strmatch(part[i], "border"))state.ws |= WS_BORDER; if(!strcmp(part[i], "border"))state.ws |= WS_BORDER;
if(strmatch(part[i], "raised"))state.ws |= WS_DLGFRAME; if(!strcmp(part[i], "raised"))state.ws |= WS_DLGFRAME;
if(strmatch(part[i], "sunken"))state.es |= WS_EX_STATICEDGE; if(!strcmp(part[i], "sunken"))state.es |= WS_EX_STATICEDGE;
if(strmatch(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE; if(!strcmp(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE;
} }
hwnd = CreateWindowEx(state.es, "COMBOBOX", text, state.ws, hwnd = CreateWindowEx(state.es, "COMBOBOX", text, state.ws,
@@ -52,7 +52,7 @@ stringarray part;
parent->hwnd, (HMENU)id, GetModuleHandle(0), 0); parent->hwnd, (HMENU)id, GetModuleHandle(0), 0);
if(!hwnd)return false; if(!hwnd)return false;
if(strmatch(text, "") == false) { if(!strcmp(text, "") == false) {
stringarray t; stringarray t;
split(t, "|", text); split(t, "|", text);
for(int i = 0; i < ::count(t); i++) { for(int i = 0; i < ::count(t); i++) {

View File

@@ -74,12 +74,12 @@ void Control::GetText(char *text, uint length) {
} }
void Control::SetText(const char *text, ...) { void Control::SetText(const char *text, ...) {
char str[4096]; string str;
va_list args; va_list args;
va_start(args, text); va_start(args, text);
vsprintf(str, text, args); vsprintf(str, text, args);
va_end(args); va_end(args);
SetWindowText(hwnd, str); SetWindowText(hwnd, strptr(str));
} }
Control::Control() { Control::Control() {

View File

@@ -19,18 +19,18 @@ bool Editbox::Create(Window *parent_window, const char *style, int x, int y, int
stringarray part; stringarray part;
ParseStyleParam(style, part); ParseStyleParam(style, part);
for(int i = 0; i < count(part); i++) { for(int i = 0; i < count(part); i++) {
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE; if(!strcmp(part[i], "visible"))state.ws |= WS_VISIBLE;
if(strmatch(part[i], "disabled"))state.ws |= WS_DISABLED; if(!strcmp(part[i], "disabled"))state.ws |= WS_DISABLED;
if(strmatch(part[i], "border"))state.ws |= WS_BORDER; if(!strcmp(part[i], "border"))state.ws |= WS_BORDER;
if(strmatch(part[i], "raised"))state.ws |= WS_DLGFRAME; if(!strcmp(part[i], "raised"))state.ws |= WS_DLGFRAME;
if(strmatch(part[i], "vscroll"))state.ws |= WS_VSCROLL; if(!strcmp(part[i], "vscroll"))state.ws |= WS_VSCROLL;
if(strmatch(part[i], "hscroll"))state.ws |= WS_HSCROLL; if(!strcmp(part[i], "hscroll"))state.ws |= WS_HSCROLL;
if(strmatch(part[i], "multiline"))state.ws |= ES_MULTILINE; if(!strcmp(part[i], "multiline"))state.ws |= ES_MULTILINE;
if(strmatch(part[i], "readonly"))state.ws |= ES_READONLY; if(!strcmp(part[i], "readonly"))state.ws |= ES_READONLY;
if(strmatch(part[i], "sunken"))state.es |= WS_EX_STATICEDGE; if(!strcmp(part[i], "sunken"))state.es |= WS_EX_STATICEDGE;
if(strmatch(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE; if(!strcmp(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE;
} }
hwnd = CreateWindowEx(state.es, "EDIT", text, state.ws, hwnd = CreateWindowEx(state.es, "EDIT", text, state.ws,

View File

@@ -14,13 +14,13 @@ bool Groupbox::Create(Window *parent_window, const char *style, int x, int y, in
stringarray part; stringarray part;
ParseStyleParam(style, part); ParseStyleParam(style, part);
for(int i = 0; i < count(part); i++) { for(int i = 0; i < count(part); i++) {
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE; if(!strcmp(part[i], "visible"))state.ws |= WS_VISIBLE;
if(strmatch(part[i], "disabled"))state.ws |= WS_DISABLED; if(!strcmp(part[i], "disabled"))state.ws |= WS_DISABLED;
if(strmatch(part[i], "border"))state.ws |= WS_BORDER; if(!strcmp(part[i], "border"))state.ws |= WS_BORDER;
if(strmatch(part[i], "raised"))state.ws |= WS_DLGFRAME; if(!strcmp(part[i], "raised"))state.ws |= WS_DLGFRAME;
if(strmatch(part[i], "sunken"))state.es |= WS_EX_STATICEDGE; if(!strcmp(part[i], "sunken"))state.es |= WS_EX_STATICEDGE;
if(strmatch(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE; if(!strcmp(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE;
} }
hwnd = CreateWindowEx(state.es, "BUTTON", text, state.ws, hwnd = CreateWindowEx(state.es, "BUTTON", text, state.ws,

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