Compare commits

...

7 Commits
v007 ... v013

Author SHA1 Message Date
byuu
c6c5f4669c Update to bsnes v013 release.
- Greatly improved HDMA timing and accuracy with help from anomie and DMV27 -- fixes bugs in Energy Breaker and Street Fighter Alpha 2
    - Fixed a problem with color add/sub code -- fixes opening battle in Tales of Phantasia and clouds in Energy Breaker
    - Temporarily added DMV27's bugfix for the DSP KON register -- fixes sound in Der Langrisser, but this is not a hardware-accurate fix
    - Disabled VRAM writes outside of vblank -- fixes Hook, but breaks many PD ROMs and fan translations (Roto's BS Zelda hack, Gideon Zhi's Ys 4 translation, etc). I might add an option in the future to toggle this behavior, but for now these games will no longer work. Please keep in mind these games will not run properly on real SNES hardware, either.
    - Improved frameskipping code thanks to a suggestion from Richard Bannister
    - Misc. other code cleanups and improvements (notably in the color table generation code)
    - bsnes is now endian-safe and runs on Mac OS X
    - Added caching support for window clipping tables resulting in a slight speedup. Please let me know if you spot any errors as a result of this change.
2005-10-23 23:32:30 +00:00
byuu
397b9c4505 Update to bsnes v012 release.
Changelog:
    - Added S-DSP emulation
    - Added sound output support via DirectSound -- no sound buffering though, so sound is muted by default
    - Added option to record raw sound output to WAV files
    - Added multiple color adjustment filters to the video output
    - Added mode3/4 direct color support
    - Added mode7 direct color and mosaic support
    - Greatly improved mode7 rendering algorithm thanks to anomie
    - Fixed mode7 screen repitition and EXTBG effects
    - Greatly increased accuracy of NMI and IRQ timing, and emulated many newly discovered hardware quirks involving the two
    - A few speed improvements courtesy of Nach for profiling the code for me
I'm now looking for assistance with sound buffering. Specifically, I need help modifying the DirectSound code to allow the emulator to be ran between 50%-400% normal speed, while keeping the sound output relatively good. If you have experience with this and can help, please get in touch with me (setsunakun0 at hotmail dot com).
2005-10-02 00:38:34 +00:00
byuu
7e2cfb6d40 Update to bsnes v011 release.
- Fixed Mode 0 color palette index problem. Fixes ToP, DQ5, etc.
    - Improved LoROM memory mapper to support 32mbit images. Fixes Tokimeki Memorial, etc.
    - Added full S-DD1 support, SFA2 and Star Ocean are now playable. Special thanks to Andreas Naive
    - Updated BGnxOFS / Mode7 registers with anomie's latest findings
    - Added basic ROM mirroring support. Fixes copy protection issues in MMX, etc.
    - Rewrote string library to work better on gcc/linux
    - Cleaned up S-RTC/S-DD1 emulation to make way for future add-on chip emulation
    - Rewrote DMA code, now runs cycle-by-cycle
    - Rewrote HDMA code, now allows HDMA to be enabled mid-frame, fixes many games
    - Fixed a bug in Mode7 vertical screen flip mode. Fixes FF5 title screen, etc.
    - Greatly improved IRQ triggering. Fixes Der Langrisser, etc.
    - Added full support for open bus. This includes PPU1 and PPU2 open bus support
    - Modified CPU core back to cycle-based system. Slower, but improves debugger
    - Implemented temporary fix for debugger to handle new cycle-based cores
    - Modified CGRAM to ignore highest bit, since it is not used at all by the SNES, and is impossible to read on real hardware. Lowers memory usage by ~1.2mb
    - Added mostly accurate PAL timing support. This should increase compatibility by ~30% or so
    - More stuff I'm forgetting at the moment...
2005-08-26 20:38:00 +00:00
byuu
970dcea0ac Update to bsnes v010 release.
bsnes now supports SPC700 emulation (no DSP or sound support, however), and has greatly improved compatibility. It also now contains a keyboard-only joypad configuration tool.
2005-08-03 21:22:42 +00:00
byuu
402c146a53 Update to bsnes v009 release.
- Fixed non-interlaced display modes from not drawing every other frame
    - Changed OAM halve to skip every other scanline in 224-height modes
    - Updated renderer to properly support games that switch resolutions mid-frame
    - Fixed VRAM address remapping modes, fixes DQ3R, FF: MQ
    - Fixed a bug in main color window clipping affecting BGs
    - Added video color curve option, thanks to Overload for the idea + color table
    - Added vblank, FPS counter, and DDraw surface memory options to settings menu
    - Added fullscreen modes 640x480 and 1024x768 to video modes
    - Added option to toggle the menubar on and off by pressing the escape key
    - Mode3 was not rendering sprites
    - Priorities were wrong for modes 2-4, thanks to anomie for info
    - Fixed a serious bug in IRQ interrupts. May not be perfect, but helps many games
2005-06-26 11:07:38 +00:00
byuu
a471c150c9 Update to bsnes v008 release.
moving the window + main color window clipping into the bg/oam/mode7 rendering routines themselves, I was able to greatly simplify the most complicated part of rendering: the final pass where color add/sub effects are applied. As a result, the new PPU core is not only ~35% faster (on graphics intensive screens, even faster on simpler screens), but more accurate as well. Awesome.
In celebration, I´m releasing bsnes v0.008. I can actually run all games I have at >60fps on my Athlon 1.67ghz PC. Probably not something to brag about, though ...
Oh, and I also updated the keyboard polling code to only capture keypresses if the main window has focus. I´ve been meaning to do this for the better part of a year now, but never got around to it.
If, for some reason, you still want to use the old renderer, you can uncomment the first line in src/ppu/bppu/bppu.h and recompile the emulator yourself. Or you can use v0.007a, I´ll leave it up for a bit.
2005-06-21 09:13:40 +00:00
byuu
ea38ea2537 Update to bsnes v007a release.
[No changelog available]
2005-06-13 04:34:10 +00:00
187 changed files with 26324 additions and 12512 deletions

148
bsnes.cfg
View File

@@ -1,21 +1,135 @@
#[bsnes v0.007 configuration file]
# Applies contrast adjust filter to video output when enabled
# Works by lowering the brightness of darker colors,
# while leaving brighter colors alone; thus reducing saturation
# (default = true)
snes.video_color_curve = true
#[video mode]
# 0: 256x224w
# 1: 512x448w
# 2: 960x720w
# Selects color adjustment filter for video output
# 0 = Normal (no filter, rgb555)
# 1 = Grayscale mode (l5)
# 2 = VGA mode (rgb332)
# 3 = Genesis mode (rgb333)
# (default = 0)
snes.video_color_adjust_mode = 0
# Mutes SNES audio output when enabled
# (default = true)
snes.mute = true
# Video mode
# 0 = 256x224w
# 1 = 512x448w
# 2 = 960x720w
# 3 = 640x480f
# 4 = 1024x768f
# (default = 1)
video.mode = 1
#[video memory type]
# true: video ram (VRAM)
# false: system ram (SRAM)
#
# VRAM results in the image being stretched in hardware,
# which is generally much faster, and automatically adds
# bilinear filtering (if the card supports it).
#
# However, some video cards end up taking a major speed
# loss when this option is enabled. It is also the only
# way to guarantee that the output image will not be
# filtered.
# Use Video RAM instead of System RAM
# (default = true)
video.use_vram = true
# Wait for vertical retrace when updating screen
# (default = false)
video.vblank = false
# Show framerate in window title
# (default = true)
gui.show_fps = true
# Joypad1 up
# (default = 0x26)
input.joypad1.up = 0x26
# Joypad1 down
# (default = 0x28)
input.joypad1.down = 0x28
# Joypad1 left
# (default = 0x25)
input.joypad1.left = 0x25
# Joypad1 right
# (default = 0x27)
input.joypad1.right = 0x27
# Joypad1 A
# (default = 0x58)
input.joypad1.a = 0x58
# Joypad1 B
# (default = 0x5a)
input.joypad1.b = 0x5a
# Joypad1 X
# (default = 0x53)
input.joypad1.x = 0x53
# Joypad1 Y
# (default = 0x41)
input.joypad1.y = 0x41
# Joypad1 L
# (default = 0x44)
input.joypad1.l = 0x44
# Joypad1 R
# (default = 0x43)
input.joypad1.r = 0x43
# Joypad1 select
# (default = 0x10)
input.joypad1.select = 0x10
# Joypad1 start
# (default = 0xd)
input.joypad1.start = 0xd
# Joypad2 up
# (default = 0x54)
input.joypad2.up = 0x54
# Joypad2 down
# (default = 0x47)
input.joypad2.down = 0x47
# Joypad2 left
# (default = 0x46)
input.joypad2.left = 0x46
# Joypad2 right
# (default = 0x48)
input.joypad2.right = 0x48
# Joypad2 A
# (default = 0x4b)
input.joypad2.a = 0x4b
# Joypad2 B
# (default = 0x4a)
input.joypad2.b = 0x4a
# Joypad2 X
# (default = 0x49)
input.joypad2.x = 0x49
# Joypad2 Y
# (default = 0x55)
input.joypad2.y = 0x55
# Joypad2 L
# (default = 0x4f)
input.joypad2.l = 0x4f
# Joypad2 R
# (default = 0x4c)
input.joypad2.r = 0x4c
# Joypad2 select
# (default = 0x5b)
input.joypad2.select = 0x5b
# Joypad2 start
# (default = 0x5d)
input.joypad2.start = 0x5d

BIN
bsnes.exe Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,10 +1,26 @@
bsnes Licensing Agreement:
bsnes License:
--------------
You are free to redistribute this software, and its source code; provided
there is no charge for the software, nor any charge for the medium used to
distribute the software. You are also free to use and modify the source code
as you desire for personal use only. No publically-released derivative works
of this source code are permitted without my permission. You must also abide
by the terms of any additional source code licenses contained within my code.
At present, this only includes the mode7 renderer, which was derived from the
snes9x mode7 renderer.
of this source code are permitted without my permission, though I will likely
grant you permission if you ask me. You must also abide by the terms of any
additional source code licenses contained within this program.
Simple DirectMedia Layer License:
---------------------------------
The Simple DirectMedia Layer (SDL for short) is a cross-platform library
designed to make it easy to write multi-media software, such as games and
emulators.
The Simple DirectMedia Layer library source code is available from:
http://www.libsdl.org/
This library is distributed under the terms of the GNU LGPL:
http://www.gnu.org/copyleft/lesser.html
Licensing Exemptions:
---------------------
Richard Bannister has asked for and received my permission to distribute
a binary-only port of bsnes on the Mac OS X platform.

3
src/apu/apu.cpp Normal file
View File

@@ -0,0 +1,3 @@
#include "../base.h"
#include "iplrom.h"
#include "dapu.cpp"

30
src/apu/apu.h Normal file
View File

@@ -0,0 +1,30 @@
#include "apuregs.h"
class APU {
public:
APURegs regs;
static const uint8 iplrom[64];
enum {
FLAG_N = 0x80, FLAG_V = 0x40,
FLAG_P = 0x20, FLAG_B = 0x10,
FLAG_H = 0x08, FLAG_I = 0x04,
FLAG_Z = 0x02, FLAG_C = 0x01
};
virtual uint8 spcram_read (uint16 addr) = 0;
virtual void spcram_write(uint16 addr, uint8 value) = 0;
//$f4-$f7
virtual uint8 port_read (uint8 port) = 0;
virtual void port_write(uint8 port, uint8 value) = 0;
virtual uint8 *get_spcram_handle() = 0;
virtual void run() = 0;
virtual uint32 cycles_executed() = 0;
virtual void power() = 0;
virtual void reset() = 0;
//debugging functions
virtual bool in_opcode();
void disassemble_opcode(char *output);
inline uint16 __relb(int8 offset, int op_len);
};

49
src/apu/apuregs.h Normal file
View File

@@ -0,0 +1,49 @@
class APURegFlags {
private:
template <uint8 B> class bit {
public:
uint8 _b;
inline operator bool() { return (_b & B); }
inline bool operator = (bool i) { (i) ? _b |= B : _b &= ~B; return (_b & B); }
inline bool operator & (bool i) { if(i)_b &= ~B; return (_b & B); }
inline bool operator &= (bool i) { if(i)_b &= ~B; return (_b & B); }
inline bool operator | (bool i) { if(i)_b |= B; return (_b & B); }
inline bool operator |= (bool i) { if(i)_b |= B; return (_b & B); }
inline bool operator ^ (bool i) { if(i)_b ^= B; return (_b & B); }
inline bool operator ^= (bool i) { if(i)_b ^= B; return (_b & B); }
};
public:
union {
uint8 _b;
bit<0x80> n;
bit<0x40> v;
bit<0x20> p;
bit<0x10> b;
bit<0x08> h;
bit<0x04> i;
bit<0x02> z;
bit<0x01> c;
};
APURegFlags() { _b = 0; }
inline operator uint8() { return _b; }
inline unsigned operator = (uint8 i) { _b = i; return _b; }
inline unsigned operator &= (uint8 i) { _b &= i; return _b; }
inline unsigned operator |= (uint8 i) { _b |= i; return _b; }
inline unsigned operator ^= (uint8 i) { _b ^= i; return _b; }
};
class APURegs {
public:
uint16 pc;
union {
uint16 ya;
#ifdef ARCH_LSB
struct { uint8 a, y; };
#else
struct { uint8 y, a; };
#endif
};
uint8 x, sp;
APURegFlags p;
};

299
src/apu/bapu/bapu.cpp Normal file
View File

@@ -0,0 +1,299 @@
#include "../../base.h"
#include "bapu_op_fn.cpp"
#include "bapu_op_mov.cpp"
#include "bapu_op_pc.cpp"
#include "bapu_op_read.cpp"
#include "bapu_op_rmw.cpp"
#include "bapu_op_misc.cpp"
#include "bapu_exec.cpp"
uint8 bAPU::spcram_read(uint16 addr) {
uint8 r;
if(addr >= 0x00f0 && addr <= 0x00ff) {
switch(addr) {
case 0xf0: //TEST -- operation unknown, supposedly returns 0x00
r = 0x00;
break;
case 0xf1: //CONTROL -- write-only register, always returns 0x00
r = 0x00;
break;
case 0xf2: //DSPADDR
r = status.dsp_addr;
break;
case 0xf3: //DSPDATA
//0x80-0xff is a read-only mirror of 0x00-0x7f
r = dsp->read(status.dsp_addr & 0x7f);
break;
case 0xf4: //CPUIO0
case 0xf5: //CPUIO1
case 0xf6: //CPUIO2
case 0xf7: //CPUIO3
r = cpu->port_read(addr & 3);
break;
case 0xf8: //???
case 0xf9: //??? -- Mapped to SPCRAM
r = spcram[addr];
break;
case 0xfa: //T0TARGET
case 0xfb: //T1TARGET
case 0xfc: //T2TARGET -- write-only registers, always return 0x00
r = 0x00;
break;
case 0xfd: //T0OUT -- 4-bit counter value
r = t0.stage3_ticks & 15;
t0.stage3_ticks = 0;
break;
case 0xfe: //T1OUT -- 4-bit counter value
r = t1.stage3_ticks & 15;
t1.stage3_ticks = 0;
break;
case 0xff: //T2OUT -- 4-bit counter value
r = t2.stage3_ticks & 15;
t2.stage3_ticks = 0;
break;
}
} else if(addr < 0xffc0) {
r = spcram[addr];
} else {
if(status.iplrom_enabled == true) {
r = iplrom[addr & 0x3f];
} else {
r = spcram[addr];
}
}
snes->notify(SNES::SPCRAM_READ, addr, r);
return r;
}
void bAPU::spcram_write(uint16 addr, uint8 value) {
if(addr >= 0x00f0 && addr <= 0x00ff) {
switch(addr) {
case 0xf0: //TEST -- operation unknown
break;
case 0xf1: //CONTROL
status.iplrom_enabled = !!(value & 0x80);
//one-time clearing of APU port read registers,
//emulated by simulating CPU writes of 0x00
if(value & 0x20) {
cpu->port_write(2, 0x00);
cpu->port_write(3, 0x00);
}
if(value & 0x10) {
cpu->port_write(0, 0x00);
cpu->port_write(1, 0x00);
}
//0->1 transistion resets timers
if(t2.enabled == false && (value & 0x04)) {
t2.stage2_ticks = 0;
t2.stage3_ticks = 0;
}
t2.enabled = !!(value & 0x04);
if(t1.enabled == false && (value & 0x02)) {
t1.stage2_ticks = 0;
t1.stage3_ticks = 0;
}
t1.enabled = !!(value & 0x02);
if(t0.enabled == false && (value & 0x01)) {
t0.stage2_ticks = 0;
t0.stage3_ticks = 0;
}
t0.enabled = !!(value & 0x01);
break;
case 0xf2: //DSPADDR
status.dsp_addr = value;
break;
case 0xf3: //DSPDATA
//0x80-0xff is a read-only mirror of 0x00-0x7f
if(status.dsp_addr < 0x80) {
dsp->write(status.dsp_addr & 0x7f, value);
}
break;
case 0xf4: //CPUIO0
case 0xf5: //CPUIO1
case 0xf6: //CPUIO2
case 0xf7: //CPUIO3
port_write(addr & 3, value);
break;
case 0xf8: //???
case 0xf9: //??? - Mapped to SPCRAM
spcram[addr] = value;
break;
case 0xfa: //T0TARGET
t0.target = value;
break;
case 0xfb: //T1TARGET
t1.target = value;
break;
case 0xfc: //T2TARGET
t2.target = value;
break;
case 0xfd: //T0OUT
case 0xfe: //T1OUT
case 0xff: //T2OUT -- read-only registers
break;
}
} else {
//writes to $ffc0-$ffff always go to spcram,
//even if the iplrom is enabled.
spcram[addr] = value;
}
snes->notify(SNES::SPCRAM_WRITE, addr, value);
}
uint8 bAPU::port_read(uint8 port) {
return spcram[0xf4 + (port & 3)];
}
void bAPU::port_write(uint8 port, uint8 value) {
spcram[0xf4 + (port & 0x03)] = value;
}
void bAPU::add_cycles(int cycles) {
status.cycles_executed += cycles;
t0.add_cycles(cycles);
t1.add_cycles(cycles);
t2.add_cycles(cycles);
}
uint32 bAPU::cycles_executed() {
uint32 r = status.cycles_executed;
status.cycles_executed = 0;
return (r << 4) + (r << 3);
}
uint8 bAPU::op_read() {
uint8 r;
r = spcram_read(regs.pc);
regs.pc++;
return r;
}
uint8 bAPU::op_read(uint8 mode, uint16 addr) {
uint8 r;
switch(mode) {
case OPMODE_ADDR:
r = spcram_read(addr);
break;
case OPMODE_DP:
r = spcram_read(((regs.p.p)?0x100:0x000) + (addr & 0xff));
break;
}
return r;
}
void bAPU::op_write(uint8 mode, uint16 addr, uint8 value) {
switch(mode) {
case OPMODE_ADDR:
spcram_write(addr, value);
break;
case OPMODE_DP:
spcram_write(((regs.p.p)?0x100:0x000) + (addr & 0xff), value);
break;
}
}
uint8 bAPU::stack_read() {
regs.sp++;
return spcram_read(0x0100 | regs.sp);
}
void bAPU::stack_write(uint8 value) {
spcram_write(0x0100 | regs.sp, value);
regs.sp--;
}
uint8 *bAPU::get_spcram_handle() {
if(!spcram) {
alert("bAPU::get_spcram_handle() -- spcram uninitialized");
}
return spcram;
}
void bAPU::run() {
exec_cycle();
}
void bAPU::power() {
memset(spcram, 0x00, 65536);
reset();
}
void bAPU::reset() {
regs.pc = 0xffc0;
regs.a = 0x00;
regs.x = 0x00;
regs.y = 0x00;
regs.sp = 0xef;
regs.p = 0x02;
status.cycle_pos = 0;
status.cycles_executed = 0;
//$f1
status.iplrom_enabled = true;
t0.enabled = false;
t1.enabled = false;
t2.enabled = false;
t0.stage1_ticks = 0;
t1.stage1_ticks = 0;
t2.stage1_ticks = 0;
t0.stage2_ticks = 0;
t1.stage2_ticks = 0;
t2.stage2_ticks = 0;
t0.stage3_ticks = 0;
t1.stage3_ticks = 0;
t2.stage3_ticks = 0;
}
bAPU::bAPU() {
init_op_table();
spcram = (uint8*)malloc(65536);
t0.cycle_frequency = 128; //1.024mhz / 8khz = 128
t1.cycle_frequency = 128; //1.024mhz / 8khz = 128
t2.cycle_frequency = 16; //1.024mhz / 64khz = 16
//targets not initialized/changed upon reset
t0.target = 0;
t1.target = 0;
t2.target = 0;
}
bAPU::~bAPU() {
if(spcram)free(spcram);
}
//cycles should never be greater than 12. since the minimum
//cycle_frequency value is 16, we don't have to worry about
//two ticks occuring in one call to this function.
void bAPUTimer::add_cycles(int cycles) {
//stage 1 increment
stage1_ticks += cycles;
if(stage1_ticks < cycle_frequency)return;
stage1_ticks -= cycle_frequency;
if(enabled == false)return;
//stage 2 increment
stage2_ticks++;
if(stage2_ticks != target)return;
//stage 3 increment
stage2_ticks = 0;
stage3_ticks++;
stage3_ticks &= 15;
}

81
src/apu/bapu/bapu.h Normal file
View File

@@ -0,0 +1,81 @@
class bAPU;
class bAPUTimer {
public:
uint8 cycle_frequency, target;
uint8 stage1_ticks, stage2_ticks, stage3_ticks;
bool enabled;
inline void add_cycles(int cycles);
};
class bAPU : public APU {
private:
typedef void (bAPU::*op)();
op optbl[256];
public:
uint16 dp, sp, rd, wr, bit, ya;
struct {
uint8 cycle_pos, opcode;
uint32 cycles_executed;
//$f1
bool iplrom_enabled;
//$f2
uint8 dsp_addr;
}status;
bAPUTimer t0, t1, t2;
uint8 *spcram;
inline uint8 spcram_read (uint16 addr);
inline void spcram_write(uint16 addr, uint8 value);
inline uint8 port_read (uint8 port);
inline void port_write(uint8 port, uint8 value);
inline uint8 *get_spcram_handle();
inline void run();
inline uint32 cycles_executed();
inline void power();
inline void reset();
inline void add_cycles(int cycles);
enum {
OPMODE_ADDR = 0,
OPMODE_DP = 1
};
inline uint8 op_read();
inline uint8 op_read (uint8 mode, uint16 addr);
inline void op_write(uint8 mode, uint16 addr, uint8 value);
inline uint8 stack_read();
inline void stack_write(uint8 value);
inline void exec_cycle();
inline bool in_opcode();
inline void init_op_table();
inline uint8 op_adc (uint8 x, uint8 y);
inline uint16 op_addw(uint16 x, uint16 y);
inline uint8 op_and (uint8 x, uint8 y);
inline uint8 op_cmp (uint8 x, uint8 y);
inline uint16 op_cmpw(uint16 x, uint16 y);
inline uint8 op_eor (uint8 x, uint8 y);
inline uint8 op_inc (uint8 x);
inline uint16 op_incw(uint16 x);
inline uint8 op_dec (uint8 x);
inline uint16 op_decw(uint16 x);
inline uint8 op_or (uint8 x, uint8 y);
inline uint8 op_sbc (uint8 x, uint8 y);
inline uint16 op_subw(uint16 x, uint16 y);
inline uint8 op_asl (uint8 x);
inline uint8 op_lsr (uint8 x);
inline uint8 op_rol (uint8 x);
inline uint8 op_ror (uint8 x);
#include "bapu_op.h"
bAPU();
~bAPU();
};

View File

@@ -0,0 +1,25 @@
void bAPU::exec_cycle() {
uint8 op;
if(status.cycle_pos == 0) {
op = spcram_read(regs.pc);
snes->notify(SNES::APU_EXEC_OPCODE_BEGIN);
status.opcode = op_read();
status.cycle_pos = 1;
add_cycles(1);
} else {
(this->*optbl[status.opcode])();
add_cycles(1);
if(status.cycle_pos == 0) {
snes->notify(SNES::APU_EXEC_OPCODE_END);
}
}
}
//only return true when we are on an opcode edge
bool bAPU::in_opcode() {
return (status.cycle_pos != 0);
}
void bAPU::init_op_table() {
#include "bapu_optable.cpp"
}

256
src/apu/bapu/bapu_op.h Normal file
View File

@@ -0,0 +1,256 @@
void op_mov_a_x();
void op_mov_a_y();
void op_mov_x_a();
void op_mov_y_a();
void op_mov_x_sp();
void op_mov_sp_x();
void op_mov_a_const();
void op_mov_x_const();
void op_mov_y_const();
void op_mov_a_ix();
void op_mov_a_ixinc();
void op_mov_a_dp();
void op_mov_x_dp();
void op_mov_y_dp();
void op_mov_a_dpx();
void op_mov_x_dpy();
void op_mov_y_dpx();
void op_mov_a_addr();
void op_mov_x_addr();
void op_mov_y_addr();
void op_mov_a_addrx();
void op_mov_a_addry();
void op_mov_a_idpx();
void op_mov_a_idpy();
void op_mov_dp_dp();
void op_mov_dp_const();
void op_mov_ix_a();
void op_mov_ixinc_a();
void op_mov_dp_a();
void op_mov_dp_x();
void op_mov_dp_y();
void op_mov_dpx_a();
void op_mov_dpy_x();
void op_mov_dpx_y();
void op_mov_addr_a();
void op_mov_addr_x();
void op_mov_addr_y();
void op_mov_addrx_a();
void op_mov_addry_a();
void op_mov_idpx_a();
void op_mov_idpy_a();
void op_movw_ya_dp();
void op_movw_dp_ya();
void op_mov1_c_bit();
void op_mov1_bit_c();
void op_bra();
void op_beq();
void op_bne();
void op_bcs();
void op_bcc();
void op_bvs();
void op_bvc();
void op_bmi();
void op_bpl();
void op_bbs0();
void op_bbc0();
void op_bbs1();
void op_bbc1();
void op_bbs2();
void op_bbc2();
void op_bbs3();
void op_bbc3();
void op_bbs4();
void op_bbc4();
void op_bbs5();
void op_bbc5();
void op_bbs6();
void op_bbc6();
void op_bbs7();
void op_bbc7();
void op_cbne_dp();
void op_cbne_dpx();
void op_dbnz_dp();
void op_dbnz_y();
void op_jmp_addr();
void op_jmp_iaddrx();
void op_call();
void op_pcall();
void op_tcall_0();
void op_tcall_1();
void op_tcall_2();
void op_tcall_3();
void op_tcall_4();
void op_tcall_5();
void op_tcall_6();
void op_tcall_7();
void op_tcall_8();
void op_tcall_9();
void op_tcall_10();
void op_tcall_11();
void op_tcall_12();
void op_tcall_13();
void op_tcall_14();
void op_tcall_15();
void op_brk();
void op_ret();
void op_reti();
void op_adc_a_const();
void op_and_a_const();
void op_cmp_a_const();
void op_cmp_x_const();
void op_cmp_y_const();
void op_eor_a_const();
void op_or_a_const();
void op_sbc_a_const();
void op_adc_a_ix();
void op_and_a_ix();
void op_cmp_a_ix();
void op_eor_a_ix();
void op_or_a_ix();
void op_sbc_a_ix();
void op_adc_a_dp();
void op_and_a_dp();
void op_cmp_a_dp();
void op_cmp_x_dp();
void op_cmp_y_dp();
void op_eor_a_dp();
void op_or_a_dp();
void op_sbc_a_dp();
void op_adc_a_dpx();
void op_and_a_dpx();
void op_cmp_a_dpx();
void op_eor_a_dpx();
void op_or_a_dpx();
void op_sbc_a_dpx();
void op_adc_a_addr();
void op_and_a_addr();
void op_cmp_a_addr();
void op_cmp_x_addr();
void op_cmp_y_addr();
void op_eor_a_addr();
void op_or_a_addr();
void op_sbc_a_addr();
void op_adc_a_addrx();
void op_adc_a_addry();
void op_and_a_addrx();
void op_and_a_addry();
void op_cmp_a_addrx();
void op_cmp_a_addry();
void op_eor_a_addrx();
void op_eor_a_addry();
void op_or_a_addrx();
void op_or_a_addry();
void op_sbc_a_addrx();
void op_sbc_a_addry();
void op_adc_a_idpx();
void op_and_a_idpx();
void op_cmp_a_idpx();
void op_eor_a_idpx();
void op_or_a_idpx();
void op_sbc_a_idpx();
void op_adc_a_idpy();
void op_and_a_idpy();
void op_cmp_a_idpy();
void op_eor_a_idpy();
void op_or_a_idpy();
void op_sbc_a_idpy();
void op_adc_ix_iy();
void op_and_ix_iy();
void op_cmp_ix_iy();
void op_eor_ix_iy();
void op_or_ix_iy();
void op_sbc_ix_iy();
void op_adc_dp_dp();
void op_and_dp_dp();
void op_cmp_dp_dp();
void op_eor_dp_dp();
void op_or_dp_dp();
void op_sbc_dp_dp();
void op_adc_dp_const();
void op_and_dp_const();
void op_cmp_dp_const();
void op_eor_dp_const();
void op_or_dp_const();
void op_sbc_dp_const();
void op_addw_ya_dp();
void op_cmpw_ya_dp();
void op_subw_ya_dp();
void op_and1_bit();
void op_and1_notbit();
void op_eor1_bit();
void op_not1_bit();
void op_or1_bit();
void op_or1_notbit();
void op_inc_a();
void op_inc_x();
void op_inc_y();
void op_dec_a();
void op_dec_x();
void op_dec_y();
void op_asl_a();
void op_lsr_a();
void op_rol_a();
void op_ror_a();
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_inc_dpx();
void op_dec_dpx();
void op_asl_dpx();
void op_lsr_dpx();
void op_rol_dpx();
void op_ror_dpx();
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_incw_dp();
void op_decw_dp();
void op_nop();
void op_sleep();
void op_stop();
void op_xcn();
void op_daa();
void op_das();
void op_clrc();
void op_clrp();
void op_setc();
void op_setp();
void op_clrv();
void op_notc();
void op_ei();
void op_di();
void op_set0_dp();
void op_clr0_dp();
void op_set1_dp();
void op_clr1_dp();
void op_set2_dp();
void op_clr2_dp();
void op_set3_dp();
void op_clr3_dp();
void op_set4_dp();
void op_clr4_dp();
void op_set5_dp();
void op_clr5_dp();
void op_set6_dp();
void op_clr6_dp();
void op_set7_dp();
void op_clr7_dp();
void op_tset_addr_a();
void op_tclr_addr_a();
void op_push_a();
void op_push_x();
void op_push_y();
void op_push_p();
void op_pop_a();
void op_pop_x();
void op_pop_y();
void op_pop_p();
void op_mul_ya();
void op_div_ya_x();

140
src/apu/bapu/bapu_op_fn.cpp Normal file
View File

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

View File

@@ -0,0 +1,643 @@
void bAPU::op_nop() {
switch(status.cycle_pos++) {
case 1:
status.cycle_pos = 0;
break;
}
}
void bAPU::op_sleep() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
regs.pc--;
status.cycle_pos = 0;
break;
}
}
void bAPU::op_stop() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
regs.pc--;
status.cycle_pos = 0;
break;
}
}
void bAPU::op_xcn() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
regs.a = (regs.a >> 4) | (regs.a << 4);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_daa() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
if(regs.p.c || (regs.a) > 0x99) {
regs.a += 0x60;
regs.p.c = 1;
}
if(regs.p.h || (regs.a & 15) > 0x09) {
regs.a += 0x06;
}
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_das() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
if(!regs.p.c || (regs.a) > 0x99) {
regs.a -= 0x60;
regs.p.c = 0;
}
if(!regs.p.h || (regs.a & 15) > 0x09) {
regs.a -= 0x06;
}
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_clrc() {
switch(status.cycle_pos++) {
case 1:
regs.p.c = 0;
status.cycle_pos = 0;
break;
}
}
void bAPU::op_clrp() {
switch(status.cycle_pos++) {
case 1:
regs.p.p = 0;
status.cycle_pos = 0;
break;
}
}
void bAPU::op_setc() {
switch(status.cycle_pos++) {
case 1:
regs.p.c = 1;
status.cycle_pos = 0;
break;
}
}
void bAPU::op_setp() {
switch(status.cycle_pos++) {
case 1:
regs.p.p = 1;
status.cycle_pos = 0;
break;
}
}
void bAPU::op_clrv() {
switch(status.cycle_pos++) {
case 1:
regs.p.v = 0;
regs.p.h = 0;
status.cycle_pos = 0;
break;
}
}
void bAPU::op_notc() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
regs.p.c ^= 1;
status.cycle_pos = 0;
break;
}
}
void bAPU::op_ei() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
regs.p.i = 1;
status.cycle_pos = 0;
break;
}
}
void bAPU::op_di() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
regs.p.i = 0;
status.cycle_pos = 0;
break;
}
}
void bAPU::op_set0_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd |= 0x01;
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_clr0_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd &= ~0x01;
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_set1_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd |= 0x02;
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_clr1_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd &= ~0x02;
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_set2_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd |= 0x04;
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_clr2_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd &= ~0x04;
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_set3_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd |= 0x08;
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_clr3_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd &= ~0x08;
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_set4_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd |= 0x10;
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_clr4_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd &= ~0x10;
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_set5_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd |= 0x20;
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_clr5_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd &= ~0x20;
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_set6_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd |= 0x40;
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_clr6_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd &= ~0x40;
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_set7_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd |= 0x80;
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_clr7_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd &= ~0x80;
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_tset_addr_a() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
dp |= op_read() << 8;
break;
case 3:
rd = op_read(OPMODE_ADDR, dp);
break;
case 4:
regs.p.n = !!((rd & regs.a) & 0x80);
regs.p.z = ((rd & regs.a) == 0);
rd |= regs.a;
break;
case 5:
op_write(OPMODE_ADDR, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_tclr_addr_a() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
dp |= op_read() << 8;
break;
case 3:
rd = op_read(OPMODE_ADDR, dp);
break;
case 4:
regs.p.n = !!((rd & regs.a) & 0x80);
regs.p.z = ((rd & regs.a) == 0);
rd &=~ regs.a;
break;
case 5:
op_write(OPMODE_ADDR, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_push_a() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
break;
case 3:
stack_write(regs.a);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_push_x() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
break;
case 3:
stack_write(regs.x);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_push_y() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
break;
case 3:
stack_write(regs.y);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_push_p() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
break;
case 3:
stack_write(regs.p);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_pop_a() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
break;
case 3:
regs.a = stack_read();
status.cycle_pos = 0;
break;
}
}
void bAPU::op_pop_x() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
break;
case 3:
regs.x = stack_read();
status.cycle_pos = 0;
break;
}
}
void bAPU::op_pop_y() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
break;
case 3:
regs.y = stack_read();
status.cycle_pos = 0;
break;
}
}
void bAPU::op_pop_p() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
break;
case 3:
regs.p = stack_read();
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mul_ya() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 8:
ya = regs.y * regs.a;
regs.a = ya;
regs.y = ya >> 8;
//result is set based on y (high-byte) only
regs.p.n = !!(regs.y & 0x80);
regs.p.z = (regs.y == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_div_ya_x() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 8:
break;
case 9:
break;
case 10:
break;
case 11:
ya = regs.ya;
//overflow set if quotient >= 256
regs.p.v = !!(regs.y >= regs.x);
regs.p.h = !!((regs.y & 15) >= (regs.x & 15));
if(regs.y < (regs.x << 1)) {
//if quotient is <= 511 (will fit into 9-bit result)
regs.a = ya / regs.x;
regs.y = ya % regs.x;
} else {
//otherwise, the quotient won't fit into regs.p.v + regs.a
//this emulates the odd behavior of the SPC700 in this case
regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x);
regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x);
}
//result is set based on a (quotient) only
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
status.cycle_pos = 0;
break;
}
}

View File

@@ -0,0 +1,710 @@
void bAPU::op_mov_a_x() {
switch(status.cycle_pos++) {
case 1:
regs.a = regs.x;
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_a_y() {
switch(status.cycle_pos++) {
case 1:
regs.a = regs.y;
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_x_a() {
switch(status.cycle_pos++) {
case 1:
regs.x = regs.a;
regs.p.n = !!(regs.x & 0x80);
regs.p.z = (regs.x == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_y_a() {
switch(status.cycle_pos++) {
case 1:
regs.y = regs.a;
regs.p.n = !!(regs.y & 0x80);
regs.p.z = (regs.y == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_x_sp() {
switch(status.cycle_pos++) {
case 1:
regs.x = regs.sp;
regs.p.n = !!(regs.x & 0x80);
regs.p.z = (regs.x == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_sp_x() {
switch(status.cycle_pos++) {
case 1:
regs.sp = regs.x;
regs.p.n = !!(regs.sp & 0x80);
regs.p.z = (regs.sp == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_a_const() {
switch(status.cycle_pos++) {
case 1:
regs.a = op_read();
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_x_const() {
switch(status.cycle_pos++) {
case 1:
regs.x = op_read();
regs.p.n = !!(regs.x & 0x80);
regs.p.z = (regs.x == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_y_const() {
switch(status.cycle_pos++) {
case 1:
regs.y = op_read();
regs.p.n = !!(regs.y & 0x80);
regs.p.z = (regs.y == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_a_ix() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
regs.a = op_read(OPMODE_DP, regs.x);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_a_ixinc() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
break;
case 3:
regs.a = op_read(OPMODE_DP, regs.x++);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_a_dp() {
switch(status.cycle_pos++) {
case 1:
sp = op_read();
break;
case 2:
regs.a = op_read(OPMODE_DP, sp);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_x_dp() {
switch(status.cycle_pos++) {
case 1:
sp = op_read();
break;
case 2:
regs.x = op_read(OPMODE_DP, sp);
regs.p.n = !!(regs.x & 0x80);
regs.p.z = (regs.x == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_y_dp() {
switch(status.cycle_pos++) {
case 1:
sp = op_read();
break;
case 2:
regs.y = op_read(OPMODE_DP, sp);
regs.p.n = !!(regs.y & 0x80);
regs.p.z = (regs.y == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_a_dpx() {
switch(status.cycle_pos++) {
case 1:
sp = op_read();
break;
case 2:
break;
case 3:
regs.a = op_read(OPMODE_DP, sp + regs.x);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_x_dpy() {
switch(status.cycle_pos++) {
case 1:
sp = op_read();
break;
case 2:
break;
case 3:
regs.x = op_read(OPMODE_DP, sp + regs.y);
regs.p.n = !!(regs.x & 0x80);
regs.p.z = (regs.x == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_y_dpx() {
switch(status.cycle_pos++) {
case 1:
sp = op_read();
break;
case 2:
break;
case 3:
regs.y = op_read(OPMODE_DP, sp + regs.x);
regs.p.n = !!(regs.y & 0x80);
regs.p.z = (regs.y == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_a_addr() {
switch(status.cycle_pos++) {
case 1:
sp = op_read();
break;
case 2:
sp |= op_read() << 8;
break;
case 3:
regs.a = op_read(OPMODE_ADDR, sp);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_x_addr() {
switch(status.cycle_pos++) {
case 1:
sp = op_read();
break;
case 2:
sp |= op_read() << 8;
break;
case 3:
regs.x = op_read(OPMODE_ADDR, sp);
regs.p.n = !!(regs.x & 0x80);
regs.p.z = (regs.x == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_y_addr() {
switch(status.cycle_pos++) {
case 1:
sp = op_read();
break;
case 2:
sp |= op_read() << 8;
break;
case 3:
regs.y = op_read(OPMODE_ADDR, sp);
regs.p.n = !!(regs.y & 0x80);
regs.p.z = (regs.y == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_a_addrx() {
switch(status.cycle_pos++) {
case 1:
sp = op_read();
break;
case 2:
sp |= op_read() << 8;
break;
case 3:
break;
case 4:
regs.a = op_read(OPMODE_ADDR, sp + regs.x);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_a_addry() {
switch(status.cycle_pos++) {
case 1:
sp = op_read();
break;
case 2:
sp |= op_read() << 8;
break;
case 3:
break;
case 4:
regs.a = op_read(OPMODE_ADDR, sp + regs.y);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_a_idpx() {
switch(status.cycle_pos++) {
case 1:
dp = op_read() + regs.x;
break;
case 2:
break;
case 3:
sp = op_read(OPMODE_DP, dp);
break;
case 4:
sp |= op_read(OPMODE_DP, dp + 1) << 8;
break;
case 5:
regs.a = op_read(OPMODE_ADDR, sp);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_a_idpy() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
break;
case 3:
sp = op_read(OPMODE_DP, dp);
break;
case 4:
sp |= op_read(OPMODE_DP, dp + 1) << 8;
break;
case 5:
regs.a = op_read(OPMODE_ADDR, sp + regs.y);
regs.p.n = !!(regs.a & 0x80);
regs.p.z = (regs.a == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_dp_dp() {
switch(status.cycle_pos++) {
case 1:
sp = op_read();
break;
case 2:
dp = op_read();
break;
case 3:
rd = op_read(OPMODE_DP, sp);
break;
case 4:
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_dp_const() {
switch(status.cycle_pos++) {
case 1:
rd = op_read();
break;
case 2:
dp = op_read();
break;
case 3:
break;
case 4:
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_ix_a() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
break;
case 3:
op_write(OPMODE_DP, regs.x, regs.a);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_ixinc_a() {
switch(status.cycle_pos++) {
case 1:
break;
case 2:
break;
case 3:
op_write(OPMODE_DP, regs.x++, regs.a);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_dp_a() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
break;
case 3:
op_write(OPMODE_DP, dp, regs.a);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_dp_x() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
break;
case 3:
op_write(OPMODE_DP, dp, regs.x);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_dp_y() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
break;
case 3:
op_write(OPMODE_DP, dp, regs.y);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_dpx_a() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
break;
case 3:
break;
case 4:
op_write(OPMODE_DP, dp + regs.x, regs.a);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_dpy_x() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
break;
case 3:
break;
case 4:
op_write(OPMODE_DP, dp + regs.y, regs.x);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_dpx_y() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
break;
case 3:
break;
case 4:
op_write(OPMODE_DP, dp + regs.x, regs.y);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_addr_a() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
dp |= op_read() << 8;
break;
case 3:
break;
case 4:
op_write(OPMODE_ADDR, dp, regs.a);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_addr_x() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
dp |= op_read() << 8;
break;
case 3:
break;
case 4:
op_write(OPMODE_ADDR, dp, regs.x);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_addr_y() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
dp |= op_read() << 8;
break;
case 3:
break;
case 4:
op_write(OPMODE_ADDR, dp, regs.y);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_addrx_a() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
dp |= op_read() << 8;
break;
case 3:
break;
case 4:
break;
case 5:
op_write(OPMODE_ADDR, dp + regs.x, regs.a);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_addry_a() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
dp |= op_read() << 8;
break;
case 3:
break;
case 4:
break;
case 5:
op_write(OPMODE_ADDR, dp + regs.y, regs.a);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_idpx_a() {
switch(status.cycle_pos++) {
case 1:
sp = op_read() + regs.x;
break;
case 2:
break;
case 3:
dp = op_read(OPMODE_DP, sp);
break;
case 4:
dp |= op_read(OPMODE_DP, sp + 1) << 8;
break;
case 5:
break;
case 6:
op_write(OPMODE_ADDR, dp, regs.a);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov_idpy_a() {
switch(status.cycle_pos++) {
case 1:
sp = op_read();
break;
case 2:
break;
case 3:
dp = op_read(OPMODE_DP, sp);
break;
case 4:
dp |= op_read(OPMODE_DP, sp + 1) << 8;
break;
case 5:
break;
case 6:
op_write(OPMODE_ADDR, dp + regs.y, regs.a);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_movw_ya_dp() {
switch(status.cycle_pos++) {
case 1:
sp = op_read();
break;
case 2:
break;
case 3:
regs.a = op_read(OPMODE_DP, sp);
break;
case 4:
regs.y = op_read(OPMODE_DP, sp + 1);
regs.p.n = !!(regs.ya & 0x8000);
regs.p.z = (regs.ya == 0);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_movw_dp_ya() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
break;
case 3:
op_write(OPMODE_DP, dp, regs.a);
break;
case 4:
op_write(OPMODE_DP, dp + 1, regs.y);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov1_c_bit() {
switch(status.cycle_pos++) {
case 1:
sp = op_read();
break;
case 2:
sp |= op_read() << 8;
break;
case 3:
bit = sp >> 13;
sp &= 0x1fff;
rd = op_read(OPMODE_ADDR, sp);
regs.p.c = !!(rd & (1 << bit));
status.cycle_pos = 0;
break;
}
}
void bAPU::op_mov1_bit_c() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
dp |= op_read() << 8;
break;
case 3:
bit = dp >> 13;
dp &= 0x1fff;
rd = op_read(OPMODE_ADDR, dp);
if(regs.p.c)rd |= (1 << bit);
else rd &= ~(1 << bit);
break;
case 4:
op_write(OPMODE_ADDR, dp, rd);
status.cycle_pos = 0;
break;
}
}

1157
src/apu/bapu/bapu_op_pc.cpp Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,452 @@
void bAPU::op_inc_a() {
switch(status.cycle_pos++) {
case 1:
regs.a = op_inc(regs.a);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_inc_x() {
switch(status.cycle_pos++) {
case 1:
regs.x = op_inc(regs.x);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_inc_y() {
switch(status.cycle_pos++) {
case 1:
regs.y = op_inc(regs.y);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_dec_a() {
switch(status.cycle_pos++) {
case 1:
regs.a = op_dec(regs.a);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_dec_x() {
switch(status.cycle_pos++) {
case 1:
regs.x = op_dec(regs.x);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_dec_y() {
switch(status.cycle_pos++) {
case 1:
regs.y = op_dec(regs.y);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_asl_a() {
switch(status.cycle_pos++) {
case 1:
regs.a = op_asl(regs.a);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_lsr_a() {
switch(status.cycle_pos++) {
case 1:
regs.a = op_lsr(regs.a);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_rol_a() {
switch(status.cycle_pos++) {
case 1:
regs.a = op_rol(regs.a);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_ror_a() {
switch(status.cycle_pos++) {
case 1:
regs.a = op_ror(regs.a);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_inc_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd = op_inc(rd);
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_dec_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd = op_dec(rd);
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_asl_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd = op_asl(rd);
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_lsr_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd = op_lsr(rd);
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_rol_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd = op_rol(rd);
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_ror_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd = op_ror(rd);
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_inc_dpx() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
break;
case 3:
rd = op_read(OPMODE_DP, dp + regs.x);
break;
case 4:
rd = op_inc(rd);
op_write(OPMODE_DP, dp + regs.x, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_dec_dpx() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
break;
case 3:
rd = op_read(OPMODE_DP, dp + regs.x);
break;
case 4:
rd = op_dec(rd);
op_write(OPMODE_DP, dp + regs.x, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_asl_dpx() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
break;
case 3:
rd = op_read(OPMODE_DP, dp + regs.x);
break;
case 4:
rd = op_asl(rd);
op_write(OPMODE_DP, dp + regs.x, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_lsr_dpx() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
break;
case 3:
rd = op_read(OPMODE_DP, dp + regs.x);
break;
case 4:
rd = op_lsr(rd);
op_write(OPMODE_DP, dp + regs.x, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_rol_dpx() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
break;
case 3:
rd = op_read(OPMODE_DP, dp + regs.x);
break;
case 4:
rd = op_rol(rd);
op_write(OPMODE_DP, dp + regs.x, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_ror_dpx() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
break;
case 3:
rd = op_read(OPMODE_DP, dp + regs.x);
break;
case 4:
rd = op_ror(rd);
op_write(OPMODE_DP, dp + regs.x, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_inc_addr() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
dp |= op_read() << 8;
break;
case 3:
rd = op_read(OPMODE_ADDR, dp);
break;
case 4:
rd = op_inc(rd);
op_write(OPMODE_ADDR, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_dec_addr() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
dp |= op_read() << 8;
break;
case 3:
rd = op_read(OPMODE_ADDR, dp);
break;
case 4:
rd = op_dec(rd);
op_write(OPMODE_ADDR, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_asl_addr() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
dp |= op_read() << 8;
break;
case 3:
rd = op_read(OPMODE_ADDR, dp);
break;
case 4:
rd = op_asl(rd);
op_write(OPMODE_ADDR, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_lsr_addr() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
dp |= op_read() << 8;
break;
case 3:
rd = op_read(OPMODE_ADDR, dp);
break;
case 4:
rd = op_lsr(rd);
op_write(OPMODE_ADDR, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_rol_addr() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
dp |= op_read() << 8;
break;
case 3:
rd = op_read(OPMODE_ADDR, dp);
break;
case 4:
rd = op_rol(rd);
op_write(OPMODE_ADDR, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_ror_addr() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
dp |= op_read() << 8;
break;
case 3:
rd = op_read(OPMODE_ADDR, dp);
break;
case 4:
rd = op_ror(rd);
op_write(OPMODE_ADDR, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_incw_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd |= op_read(OPMODE_DP, dp + 1) << 8;
break;
case 4:
rd = op_incw(rd);
op_write(OPMODE_DP, dp + 1, rd >> 8);
break;
case 5:
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}
void bAPU::op_decw_dp() {
switch(status.cycle_pos++) {
case 1:
dp = op_read();
break;
case 2:
rd = op_read(OPMODE_DP, dp);
break;
case 3:
rd |= op_read(OPMODE_DP, dp + 1) << 8;
break;
case 4:
rd = op_decw(rd);
op_write(OPMODE_DP, dp + 1, rd >> 8);
break;
case 5:
op_write(OPMODE_DP, dp, rd);
status.cycle_pos = 0;
break;
}
}

View File

@@ -0,0 +1,256 @@
optbl[0x7d] = &bAPU::op_mov_a_x;
optbl[0xdd] = &bAPU::op_mov_a_y;
optbl[0x5d] = &bAPU::op_mov_x_a;
optbl[0xfd] = &bAPU::op_mov_y_a;
optbl[0x9d] = &bAPU::op_mov_x_sp;
optbl[0xbd] = &bAPU::op_mov_sp_x;
optbl[0xe8] = &bAPU::op_mov_a_const;
optbl[0xcd] = &bAPU::op_mov_x_const;
optbl[0x8d] = &bAPU::op_mov_y_const;
optbl[0xe6] = &bAPU::op_mov_a_ix;
optbl[0xbf] = &bAPU::op_mov_a_ixinc;
optbl[0xe4] = &bAPU::op_mov_a_dp;
optbl[0xf8] = &bAPU::op_mov_x_dp;
optbl[0xeb] = &bAPU::op_mov_y_dp;
optbl[0xf4] = &bAPU::op_mov_a_dpx;
optbl[0xf9] = &bAPU::op_mov_x_dpy;
optbl[0xfb] = &bAPU::op_mov_y_dpx;
optbl[0xe5] = &bAPU::op_mov_a_addr;
optbl[0xe9] = &bAPU::op_mov_x_addr;
optbl[0xec] = &bAPU::op_mov_y_addr;
optbl[0xf5] = &bAPU::op_mov_a_addrx;
optbl[0xf6] = &bAPU::op_mov_a_addry;
optbl[0xe7] = &bAPU::op_mov_a_idpx;
optbl[0xf7] = &bAPU::op_mov_a_idpy;
optbl[0xfa] = &bAPU::op_mov_dp_dp;
optbl[0x8f] = &bAPU::op_mov_dp_const;
optbl[0xc6] = &bAPU::op_mov_ix_a;
optbl[0xaf] = &bAPU::op_mov_ixinc_a;
optbl[0xc4] = &bAPU::op_mov_dp_a;
optbl[0xd8] = &bAPU::op_mov_dp_x;
optbl[0xcb] = &bAPU::op_mov_dp_y;
optbl[0xd4] = &bAPU::op_mov_dpx_a;
optbl[0xd9] = &bAPU::op_mov_dpy_x;
optbl[0xdb] = &bAPU::op_mov_dpx_y;
optbl[0xc5] = &bAPU::op_mov_addr_a;
optbl[0xc9] = &bAPU::op_mov_addr_x;
optbl[0xcc] = &bAPU::op_mov_addr_y;
optbl[0xd5] = &bAPU::op_mov_addrx_a;
optbl[0xd6] = &bAPU::op_mov_addry_a;
optbl[0xc7] = &bAPU::op_mov_idpx_a;
optbl[0xd7] = &bAPU::op_mov_idpy_a;
optbl[0xba] = &bAPU::op_movw_ya_dp;
optbl[0xda] = &bAPU::op_movw_dp_ya;
optbl[0xaa] = &bAPU::op_mov1_c_bit;
optbl[0xca] = &bAPU::op_mov1_bit_c;
optbl[0x2f] = &bAPU::op_bra;
optbl[0xf0] = &bAPU::op_beq;
optbl[0xd0] = &bAPU::op_bne;
optbl[0xb0] = &bAPU::op_bcs;
optbl[0x90] = &bAPU::op_bcc;
optbl[0x70] = &bAPU::op_bvs;
optbl[0x50] = &bAPU::op_bvc;
optbl[0x30] = &bAPU::op_bmi;
optbl[0x10] = &bAPU::op_bpl;
optbl[0x03] = &bAPU::op_bbs0;
optbl[0x13] = &bAPU::op_bbc0;
optbl[0x23] = &bAPU::op_bbs1;
optbl[0x33] = &bAPU::op_bbc1;
optbl[0x43] = &bAPU::op_bbs2;
optbl[0x53] = &bAPU::op_bbc2;
optbl[0x63] = &bAPU::op_bbs3;
optbl[0x73] = &bAPU::op_bbc3;
optbl[0x83] = &bAPU::op_bbs4;
optbl[0x93] = &bAPU::op_bbc4;
optbl[0xa3] = &bAPU::op_bbs5;
optbl[0xb3] = &bAPU::op_bbc5;
optbl[0xc3] = &bAPU::op_bbs6;
optbl[0xd3] = &bAPU::op_bbc6;
optbl[0xe3] = &bAPU::op_bbs7;
optbl[0xf3] = &bAPU::op_bbc7;
optbl[0x2e] = &bAPU::op_cbne_dp;
optbl[0xde] = &bAPU::op_cbne_dpx;
optbl[0x6e] = &bAPU::op_dbnz_dp;
optbl[0xfe] = &bAPU::op_dbnz_y;
optbl[0x5f] = &bAPU::op_jmp_addr;
optbl[0x1f] = &bAPU::op_jmp_iaddrx;
optbl[0x3f] = &bAPU::op_call;
optbl[0x4f] = &bAPU::op_pcall;
optbl[0x01] = &bAPU::op_tcall_0;
optbl[0x11] = &bAPU::op_tcall_1;
optbl[0x21] = &bAPU::op_tcall_2;
optbl[0x31] = &bAPU::op_tcall_3;
optbl[0x41] = &bAPU::op_tcall_4;
optbl[0x51] = &bAPU::op_tcall_5;
optbl[0x61] = &bAPU::op_tcall_6;
optbl[0x71] = &bAPU::op_tcall_7;
optbl[0x81] = &bAPU::op_tcall_8;
optbl[0x91] = &bAPU::op_tcall_9;
optbl[0xa1] = &bAPU::op_tcall_10;
optbl[0xb1] = &bAPU::op_tcall_11;
optbl[0xc1] = &bAPU::op_tcall_12;
optbl[0xd1] = &bAPU::op_tcall_13;
optbl[0xe1] = &bAPU::op_tcall_14;
optbl[0xf1] = &bAPU::op_tcall_15;
optbl[0x0f] = &bAPU::op_brk;
optbl[0x6f] = &bAPU::op_ret;
optbl[0x7f] = &bAPU::op_reti;
optbl[0x88] = &bAPU::op_adc_a_const;
optbl[0x28] = &bAPU::op_and_a_const;
optbl[0x68] = &bAPU::op_cmp_a_const;
optbl[0xc8] = &bAPU::op_cmp_x_const;
optbl[0xad] = &bAPU::op_cmp_y_const;
optbl[0x48] = &bAPU::op_eor_a_const;
optbl[0x08] = &bAPU::op_or_a_const;
optbl[0xa8] = &bAPU::op_sbc_a_const;
optbl[0x86] = &bAPU::op_adc_a_ix;
optbl[0x26] = &bAPU::op_and_a_ix;
optbl[0x66] = &bAPU::op_cmp_a_ix;
optbl[0x46] = &bAPU::op_eor_a_ix;
optbl[0x06] = &bAPU::op_or_a_ix;
optbl[0xa6] = &bAPU::op_sbc_a_ix;
optbl[0x84] = &bAPU::op_adc_a_dp;
optbl[0x24] = &bAPU::op_and_a_dp;
optbl[0x64] = &bAPU::op_cmp_a_dp;
optbl[0x3e] = &bAPU::op_cmp_x_dp;
optbl[0x7e] = &bAPU::op_cmp_y_dp;
optbl[0x44] = &bAPU::op_eor_a_dp;
optbl[0x04] = &bAPU::op_or_a_dp;
optbl[0xa4] = &bAPU::op_sbc_a_dp;
optbl[0x94] = &bAPU::op_adc_a_dpx;
optbl[0x34] = &bAPU::op_and_a_dpx;
optbl[0x74] = &bAPU::op_cmp_a_dpx;
optbl[0x54] = &bAPU::op_eor_a_dpx;
optbl[0x14] = &bAPU::op_or_a_dpx;
optbl[0xb4] = &bAPU::op_sbc_a_dpx;
optbl[0x85] = &bAPU::op_adc_a_addr;
optbl[0x25] = &bAPU::op_and_a_addr;
optbl[0x65] = &bAPU::op_cmp_a_addr;
optbl[0x1e] = &bAPU::op_cmp_x_addr;
optbl[0x5e] = &bAPU::op_cmp_y_addr;
optbl[0x45] = &bAPU::op_eor_a_addr;
optbl[0x05] = &bAPU::op_or_a_addr;
optbl[0xa5] = &bAPU::op_sbc_a_addr;
optbl[0x95] = &bAPU::op_adc_a_addrx;
optbl[0x96] = &bAPU::op_adc_a_addry;
optbl[0x35] = &bAPU::op_and_a_addrx;
optbl[0x36] = &bAPU::op_and_a_addry;
optbl[0x75] = &bAPU::op_cmp_a_addrx;
optbl[0x76] = &bAPU::op_cmp_a_addry;
optbl[0x55] = &bAPU::op_eor_a_addrx;
optbl[0x56] = &bAPU::op_eor_a_addry;
optbl[0x15] = &bAPU::op_or_a_addrx;
optbl[0x16] = &bAPU::op_or_a_addry;
optbl[0xb5] = &bAPU::op_sbc_a_addrx;
optbl[0xb6] = &bAPU::op_sbc_a_addry;
optbl[0x87] = &bAPU::op_adc_a_idpx;
optbl[0x27] = &bAPU::op_and_a_idpx;
optbl[0x67] = &bAPU::op_cmp_a_idpx;
optbl[0x47] = &bAPU::op_eor_a_idpx;
optbl[0x07] = &bAPU::op_or_a_idpx;
optbl[0xa7] = &bAPU::op_sbc_a_idpx;
optbl[0x97] = &bAPU::op_adc_a_idpy;
optbl[0x37] = &bAPU::op_and_a_idpy;
optbl[0x77] = &bAPU::op_cmp_a_idpy;
optbl[0x57] = &bAPU::op_eor_a_idpy;
optbl[0x17] = &bAPU::op_or_a_idpy;
optbl[0xb7] = &bAPU::op_sbc_a_idpy;
optbl[0x99] = &bAPU::op_adc_ix_iy;
optbl[0x39] = &bAPU::op_and_ix_iy;
optbl[0x79] = &bAPU::op_cmp_ix_iy;
optbl[0x59] = &bAPU::op_eor_ix_iy;
optbl[0x19] = &bAPU::op_or_ix_iy;
optbl[0xb9] = &bAPU::op_sbc_ix_iy;
optbl[0x89] = &bAPU::op_adc_dp_dp;
optbl[0x29] = &bAPU::op_and_dp_dp;
optbl[0x69] = &bAPU::op_cmp_dp_dp;
optbl[0x49] = &bAPU::op_eor_dp_dp;
optbl[0x09] = &bAPU::op_or_dp_dp;
optbl[0xa9] = &bAPU::op_sbc_dp_dp;
optbl[0x98] = &bAPU::op_adc_dp_const;
optbl[0x38] = &bAPU::op_and_dp_const;
optbl[0x78] = &bAPU::op_cmp_dp_const;
optbl[0x58] = &bAPU::op_eor_dp_const;
optbl[0x18] = &bAPU::op_or_dp_const;
optbl[0xb8] = &bAPU::op_sbc_dp_const;
optbl[0x7a] = &bAPU::op_addw_ya_dp;
optbl[0x5a] = &bAPU::op_cmpw_ya_dp;
optbl[0x9a] = &bAPU::op_subw_ya_dp;
optbl[0x4a] = &bAPU::op_and1_bit;
optbl[0x6a] = &bAPU::op_and1_notbit;
optbl[0x8a] = &bAPU::op_eor1_bit;
optbl[0xea] = &bAPU::op_not1_bit;
optbl[0x0a] = &bAPU::op_or1_bit;
optbl[0x2a] = &bAPU::op_or1_notbit;
optbl[0xbc] = &bAPU::op_inc_a;
optbl[0x3d] = &bAPU::op_inc_x;
optbl[0xfc] = &bAPU::op_inc_y;
optbl[0x9c] = &bAPU::op_dec_a;
optbl[0x1d] = &bAPU::op_dec_x;
optbl[0xdc] = &bAPU::op_dec_y;
optbl[0x1c] = &bAPU::op_asl_a;
optbl[0x5c] = &bAPU::op_lsr_a;
optbl[0x3c] = &bAPU::op_rol_a;
optbl[0x7c] = &bAPU::op_ror_a;
optbl[0xab] = &bAPU::op_inc_dp;
optbl[0x8b] = &bAPU::op_dec_dp;
optbl[0x0b] = &bAPU::op_asl_dp;
optbl[0x4b] = &bAPU::op_lsr_dp;
optbl[0x2b] = &bAPU::op_rol_dp;
optbl[0x6b] = &bAPU::op_ror_dp;
optbl[0xbb] = &bAPU::op_inc_dpx;
optbl[0x9b] = &bAPU::op_dec_dpx;
optbl[0x1b] = &bAPU::op_asl_dpx;
optbl[0x5b] = &bAPU::op_lsr_dpx;
optbl[0x3b] = &bAPU::op_rol_dpx;
optbl[0x7b] = &bAPU::op_ror_dpx;
optbl[0xac] = &bAPU::op_inc_addr;
optbl[0x8c] = &bAPU::op_dec_addr;
optbl[0x0c] = &bAPU::op_asl_addr;
optbl[0x4c] = &bAPU::op_lsr_addr;
optbl[0x2c] = &bAPU::op_rol_addr;
optbl[0x6c] = &bAPU::op_ror_addr;
optbl[0x3a] = &bAPU::op_incw_dp;
optbl[0x1a] = &bAPU::op_decw_dp;
optbl[0x00] = &bAPU::op_nop;
optbl[0xef] = &bAPU::op_sleep;
optbl[0xff] = &bAPU::op_stop;
optbl[0x9f] = &bAPU::op_xcn;
optbl[0xdf] = &bAPU::op_daa;
optbl[0xbe] = &bAPU::op_das;
optbl[0x60] = &bAPU::op_clrc;
optbl[0x20] = &bAPU::op_clrp;
optbl[0x80] = &bAPU::op_setc;
optbl[0x40] = &bAPU::op_setp;
optbl[0xe0] = &bAPU::op_clrv;
optbl[0xed] = &bAPU::op_notc;
optbl[0xa0] = &bAPU::op_ei;
optbl[0xc0] = &bAPU::op_di;
optbl[0x02] = &bAPU::op_set0_dp;
optbl[0x12] = &bAPU::op_clr0_dp;
optbl[0x22] = &bAPU::op_set1_dp;
optbl[0x32] = &bAPU::op_clr1_dp;
optbl[0x42] = &bAPU::op_set2_dp;
optbl[0x52] = &bAPU::op_clr2_dp;
optbl[0x62] = &bAPU::op_set3_dp;
optbl[0x72] = &bAPU::op_clr3_dp;
optbl[0x82] = &bAPU::op_set4_dp;
optbl[0x92] = &bAPU::op_clr4_dp;
optbl[0xa2] = &bAPU::op_set5_dp;
optbl[0xb2] = &bAPU::op_clr5_dp;
optbl[0xc2] = &bAPU::op_set6_dp;
optbl[0xd2] = &bAPU::op_clr6_dp;
optbl[0xe2] = &bAPU::op_set7_dp;
optbl[0xf2] = &bAPU::op_clr7_dp;
optbl[0x0e] = &bAPU::op_tset_addr_a;
optbl[0x4e] = &bAPU::op_tclr_addr_a;
optbl[0x2d] = &bAPU::op_push_a;
optbl[0x4d] = &bAPU::op_push_x;
optbl[0x6d] = &bAPU::op_push_y;
optbl[0x0d] = &bAPU::op_push_p;
optbl[0xae] = &bAPU::op_pop_a;
optbl[0xce] = &bAPU::op_pop_x;
optbl[0xee] = &bAPU::op_pop_y;
optbl[0x8e] = &bAPU::op_pop_p;
optbl[0xcf] = &bAPU::op_mul_ya;
optbl[0x9e] = &bAPU::op_div_ya_x;

168
src/apu/bapu/bapugen.cpp Normal file
View File

@@ -0,0 +1,168 @@
#include "../../lib/libbase.h"
#include "../../lib/libstring.h"
#include "../../lib/libstring.cpp"
FILE *fp, *fph, *fpt;
string data, line, part, subpart;
string output_table, output_header, output_op;
int op_count;
struct _op_list {
string name;
string arg;
}op_list[64];
int line_num;
void clear_op_list() {
op_count = 0;
for(int i=0;i<64;i++) {
strcpy(op_list[i].name, "");
for(int l=0;l<8;l++) {
strcpy(op_list[i].arg[l], "");
}
}
}
void gen_header() {
int i = line_num, l, n, z;
char t[4096];
clear_op_list();
while(1) {
z = op_count++;
strcpy(part, line[i]);
strrtrim(part, "),");
strrtrim(part, ") {");
split(subpart, "(", part);
strcpy(op_list[z].name, subpart[0]);
split(part, ", ", subpart[1]);
for(l=0;l<count(part);l++) {
strcpy(op_list[z].arg[l], part[l]);
}
if(!strend(line[i], " {"))break;
i++;
}
sprintf(output_op, "void bAPU::op_$$() {\r\n switch(status.cycle_pos++) {\r\n");
sprintf(output_header, "void op_$$();\r\n");
sprintf(output_table, "optbl[$0] = &bAPU::op_$$;\r\n");
line_num = i + 1;
}
void update_line(int i, int n) {
replace(line[i], "end;", "status.cycle_pos = 0;");
}
void gen_op() {
int i = line_num, n;
char t[4096];
while(1) {
if(!strcmp(line[i], "}"))break;
n = strdec(line[i]);
sprintf(t, "%d:", n);
strltrim(line[i], t);
sprintf(t, " case %d:\r\n", n);
strcat(output_op, t);
update_line(i, n);
if(strcmp(line[i], "")) {
strcat(output_op, " ");
strcat(output_op, line[i]);
strcat(output_op, "\r\n");
}
i++;
while(1) {
if((strptr(line[i])[1]) == ':' || (strptr(line[i])[2]) == ':' || !strcmp(line[i], "}"))break;
update_line(i, n);
strcat(output_op, " ");
strcat(output_op, line[i]);
strcat(output_op, "\r\n");
i++;
}
if(!strcmp(line[i], "}"))strcat(output_op, " status.cycle_pos = 0;\r\n");
strcat(output_op, " break;\r\n");
}
strcat(output_op, " }\r\n}");
line_num = i + 1;
}
void gen_final() {
string t;
int i, l;
for(i=0;i<op_count;i++) {
strcpy(t, output_op);
replace(t, "$$", op_list[i].name);
replace(t, "$0", op_list[i].arg[0]);
replace(t, "$1", op_list[i].arg[1]);
replace(t, "$2", op_list[i].arg[2]);
replace(t, "$3", op_list[i].arg[3]);
replace(t, "$4", op_list[i].arg[4]);
replace(t, "$5", op_list[i].arg[5]);
replace(t, "$6", op_list[i].arg[6]);
replace(t, "$7", op_list[i].arg[7]);
fprintf(fp, "%s\r\n\r\n", strptr(t));
strcpy(t, output_header);
replace(t, "$$", op_list[i].name);
fprintf(fph, "%s", strptr(t));
strcpy(t, output_table);
replace(t, "$$", op_list[i].name);
replace(t, "$0", op_list[i].arg[0]);
fprintf(fpt, "%s", strptr(t));
}
}
void generate(char *dest, char *src) {
fp = fopen(src, "rb");
fseek(fp, 0, SEEK_END);
int fsize = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *buf = (char*)malloc(fsize + 1);
fread(buf, 1, fsize, fp);
fclose(fp);
buf[fsize] = 0;
strcpy(data, buf);
free(buf);
replace(data, "\r\n", "\n");
split(line, "\n", data);
fp = fopen(dest, "wb");
line_num = 0;
while(line_num < count(line)) {
while(!strcmp(line[line_num], "") && line_num < count(line))line_num++;
if(line_num >= count(line))break;
gen_header();
gen_op();
gen_final();
}
fclose(fp);
}
int main() {
fph = fopen("bapu_op.h", "wb");
fpt = fopen("bapu_optable.cpp", "wb");
generate("bapu_op_mov.cpp", "op_mov.b");
generate("bapu_op_pc.cpp", "op_pc.b");
generate("bapu_op_read.cpp", "op_read.b");
generate("bapu_op_rmw.cpp", "op_rmw.b");
generate("bapu_op_misc.cpp", "op_misc.b");
fclose(fph);
fclose(fpt);
return 0;
}

3
src/apu/bapu/cc.bat Normal file
View File

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

1
src/apu/bapu/clean.bat Normal file
View File

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

164
src/apu/bapu/op_misc.b Normal file
View File

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

207
src/apu/bapu/op_mov.b Normal file
View File

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

166
src/apu/bapu/op_pc.b Normal file
View File

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

194
src/apu/bapu/op_read.b Normal file
View File

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

60
src/apu/bapu/op_rmw.b Normal file
View File

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

View File

@@ -0,0 +1,171 @@
#include "../../base.h"
uint8 bAPUSkip::spcram_read (uint16 addr) { return 0xff; }
void bAPUSkip::spcram_write(uint16 addr, uint8 value) {}
/*
This routine is very serious. It will eat holes through
the ROM to skip APU test conditions. Or in other words,
it will disable and/or force branches when neccesary.
It can very easily break or corrupt a game and prevent it
from being playable until the ROM is reloaded (ROM writes
are only performed in memory, of course).
However, this kind of brute force approach is required to
get many games playable without proper SPC700 emulation.
*/
uint8 bAPUSkip::port_read(uint8 port) {
port &= 3;
_apu_port *p = &apu_port[port];
int i, x, y, z, t;
uint32 addr;
addr = cpu->regs.pc.d;
p->read_addr[p->read_pos & 31] = addr;
//- lda $214x
// cmp $214x
// bne -
// cmp ???
// beq/bne -
__test1:
//look for an lda/cmp read pattern
if(addr == p->read_addr[(p->read_pos - 1) & 31])goto __test2;
if(addr != p->read_addr[(p->read_pos - 2) & 31])goto __test2;
if(addr == p->read_addr[(p->read_pos - 3) & 31])goto __test2;
if(addr != p->read_addr[(p->read_pos - 4) & 31])goto __test2;
if(p->read_addr[(p->read_pos - 1) & 31] != p->read_addr[(p->read_pos - 3) & 31])goto __test2;
//try and find compare opcode
for(i=0;i<24;i++) {
x = mem_bus->read(addr + i);
if(x == OP_CMP_CONST || x == OP_CPX_CONST || x == OP_CPY_CONST)break;
if(x == OP_CMP_ADDR || x == OP_CPX_ADDR || x == OP_CPY_ADDR) break;
if(x == OP_CMP_LONG)break;
}
if(i == 24)goto __test2;
//seek to next opcode
if(x == OP_CMP_CONST) {
i += (cpu->regs.p.m)?2:3;
} else if(x == OP_CPX_CONST || x == OP_CPY_CONST) {
i += (cpu->regs.p.x)?2:3;
} else if(x == OP_CMP_ADDR || x == OP_CPX_ADDR || x == OP_CPY_ADDR) {
i += 3;
} else { //(x == OP_CMP_LONG) {
i += 4;
}
x = mem_bus->read(addr + i);
if(x == OP_BNE) {
mem_bus->cart->write_protect(false);
mem_bus->write(addr + i, OP_NOP);
mem_bus->write(addr + i + 1, OP_NOP);
mem_bus->cart->write_protect(true);
} else if(x == OP_BEQ) {
mem_bus->cart->write_protect(false);
mem_bus->write(addr + i, OP_BRA);
mem_bus->cart->write_protect(true);
} else goto __test2;
goto __pass;
//- lda $214x
// cmp ???
// beq/bne -
__test2:
//look for a repeated read pattern
if(addr != p->read_addr[(p->read_pos - 1) & 31])goto __test3;
if(addr != p->read_addr[(p->read_pos - 2) & 31])goto __test3;
if(addr != p->read_addr[(p->read_pos - 3) & 31])goto __test3;
if(addr != p->read_addr[(p->read_pos - 4) & 31])goto __test3;
if(addr != p->read_addr[(p->read_pos - 5) & 31])goto __test3;
if(addr != p->read_addr[(p->read_pos - 6) & 31])goto __test3;
if(addr != p->read_addr[(p->read_pos - 7) & 31])goto __test3;
if(addr != p->read_addr[(p->read_pos - 8) & 31])goto __test3;
//try and find compare opcode
for(i=0;i<24;i++) {
x = mem_bus->read(addr + i);
if(x == OP_CMP_CONST || x == OP_CPX_CONST || x == OP_CPY_CONST)break;
if(x == OP_CMP_ADDR || x == OP_CPX_ADDR || x == OP_CPY_ADDR) break;
if(x == OP_CMP_LONG)break;
}
if(i == 24)goto __test3;
//seek to next opcode
if(x == OP_CMP_CONST) {
i += (cpu->regs.p.m)?2:3;
} else if(x == OP_CPX_CONST || x == OP_CPY_CONST) {
i += (cpu->regs.p.x)?2:3;
} else if(x == OP_CMP_ADDR || x == OP_CPX_ADDR || x == OP_CPY_ADDR) {
i += 3;
} else if(x == OP_CMP_LONG) {
i += 4;
}
x = mem_bus->read(addr + i);
if(x == OP_BNE) {
mem_bus->cart->write_protect(false);
mem_bus->write(addr + i, OP_NOP);
mem_bus->write(addr + i + 1, OP_NOP);
mem_bus->cart->write_protect(true);
} else if(x == OP_BEQ) {
mem_bus->cart->write_protect(false);
mem_bus->write(addr + i, OP_BRA);
mem_bus->cart->write_protect(true);
} else goto __test3;
goto __pass;
//fallback
__test3:
if(p->pos < 4) {
if(!(port & 1)) {
p->value = cpu->regs.a.l;
} else {
p->value = cpu->regs.a.h;
}
} else if(p->pos < 8) {
if(!(port & 1)) {
p->value = cpu->regs.x.l;
} else {
p->value = cpu->regs.x.h;
}
} else if(p->pos < 12) {
if(!(port & 1)) {
p->value = cpu->regs.y.l;
} else {
p->value = cpu->regs.y.h;
}
} else if(p->pos < 16) {
p->value = rand();
}
if(++p->pos == 16)p->pos = 0;
__pass:
p->read_pos++;
p->read_pos &= 31;
return p->value;
}
void bAPUSkip::port_write(uint8 port, uint8 value) {
port &= 3;
apu_port[port].value = value;
}
void bAPUSkip::run() {
snes->notify(SNES::APU_EXEC_OPCODE_BEGIN);
snes->notify(SNES::APU_EXEC_OPCODE_END);
}
void bAPUSkip::power() {
reset();
}
void bAPUSkip::reset() {
regs.a = 0x00;
regs.x = 0x00;
regs.y = 0x00;
regs.sp = 0x00;
regs.p = 0x02;
regs.pc = 0xffc0;
memset(&apu_port[0], 0, sizeof(_apu_port));
memset(&apu_port[1], 0, sizeof(_apu_port));
memset(&apu_port[2], 0, sizeof(_apu_port));
memset(&apu_port[3], 0, sizeof(_apu_port));
}

View File

@@ -0,0 +1,37 @@
class bAPUSkip : public APU {
private:
uint8 spcram[65536];
public:
struct _apu_port {
uint8 value;
uint8 step, pos;
uint32 read_addr[32], read_pos;
}apu_port[4];
enum {
OP_CMP_CONST = 0xc9,
OP_CPX_CONST = 0xe0,
OP_CPY_CONST = 0xc0,
OP_CMP_ADDR = 0xcd,
OP_CPX_ADDR = 0xec,
OP_CPY_ADDR = 0xcc,
OP_CMP_LONG = 0xcf,
OP_BNE = 0xd0,
OP_BEQ = 0xf0,
OP_BRA = 0x80,
OP_NOP = 0xea
};
uint8 spcram_read (uint16 addr);
void spcram_write(uint16 addr, uint8 value);
uint8 port_read (uint8 port);
void port_write (uint8 port, uint8 value);
uint8 *get_spcram_handle() { return spcram; }
void run();
uint32 cycles_executed() { return 12 * 24; }
void power();
void reset();
};

306
src/apu/dapu.cpp Normal file
View File

@@ -0,0 +1,306 @@
//virtual function, see src/cpu/dcpu.cpp
//for explanation of this function
bool APU::in_opcode() { return false; }
uint16 APU::__relb(int8 offset, int op_len) {
uint16 pc = regs.pc + op_len;
return pc + offset;
}
void APU::disassemble_opcode(char *output) {
char *s, t[512];
uint8 op, op0, op1;
uint16 opw, opdp0, opdp1;
s = output;
if(in_opcode() == true) {
strcpy(s, "..???? <APU within opcode>");
return;
}
sprintf(s, "..%0.4x ", regs.pc);
op = spcram_read(regs.pc);
op0 = spcram_read(regs.pc + 1);
op1 = spcram_read(regs.pc + 2);
opw = (op0) | (op1 << 8);
opdp0 = ((regs.p.p)?0x100:0x000) + op0;
opdp1 = ((regs.p.p)?0x100:0x000) + op1;
strcpy(t, " ");
switch(op) {
case 0x00:sprintf(t, "nop"); break;
case 0x01:sprintf(t, "tcall 0"); break;
case 0x02:sprintf(t, "set0 $%0.3x", opdp0); break;
case 0x03:sprintf(t, "bbs0 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x04:sprintf(t, "or a,$%0.3x", opdp0); break;
case 0x05:sprintf(t, "or a,$%0.4x", opw); break;
case 0x06:sprintf(t, "or a,(x)"); break;
case 0x07:sprintf(t, "or a,($%0.3x+x)", opdp0); break;
case 0x08:sprintf(t, "or a,#$%0.2x", op0); break;
case 0x09:sprintf(t, "or $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x0a:sprintf(t, "or1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x0b:sprintf(t, "asl $%0.3x", opdp0); break;
case 0x0c:sprintf(t, "asl $%0.4x", opw); break;
case 0x0d:sprintf(t, "push p"); break;
case 0x0e:sprintf(t, "tset $%0.4x,a", opw); break;
case 0x0f:sprintf(t, "brk"); break;
case 0x10:sprintf(t, "bpl $%0.4x", __relb(op0, 2)); break;
case 0x11:sprintf(t, "tcall 1"); break;
case 0x12:sprintf(t, "clr0 $%0.3x", opdp0); break;
case 0x13:sprintf(t, "bbc0 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x14:sprintf(t, "or a,$%0.3x+x", opdp0); break;
case 0x15:sprintf(t, "or a,$%0.4x+x", opw); break;
case 0x16:sprintf(t, "or a,$%0.4x+y", opw); break;
case 0x17:sprintf(t, "or a,($%0.3x)+y", opdp0); break;
case 0x18:sprintf(t, "or $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x19:sprintf(t, "or (x),(y)"); break;
case 0x1a:sprintf(t, "decw $%0.3x", opdp0); break;
case 0x1b:sprintf(t, "asl $%0.3x+x", opdp0); break;
case 0x1c:sprintf(t, "asl a"); break;
case 0x1d:sprintf(t, "dec x"); break;
case 0x1e:sprintf(t, "cmp x,$%0.4x", opw); break;
case 0x1f:sprintf(t, "jmp ($%0.4x+x)", opw); break;
case 0x20:sprintf(t, "clrp"); break;
case 0x21:sprintf(t, "tcall 2"); break;
case 0x22:sprintf(t, "set1 $%0.3x", opdp0); break;
case 0x23:sprintf(t, "bbs1 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x24:sprintf(t, "and a,$%0.3x", opdp0); break;
case 0x25:sprintf(t, "and a,$%0.4x", opw); break;
case 0x26:sprintf(t, "and a,(x)"); break;
case 0x27:sprintf(t, "and a,($%0.3x+x)", opdp0); break;
case 0x28:sprintf(t, "and a,#$%0.2x", op0); break;
case 0x29:sprintf(t, "and $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x2a:sprintf(t, "or1 c,!$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x2b:sprintf(t, "rol $%0.3x", opdp0); break;
case 0x2c:sprintf(t, "rol $%0.4x", opw); break;
case 0x2d:sprintf(t, "push a"); break;
case 0x2e:sprintf(t, "cbne $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x2f:sprintf(t, "bra $%0.4x", __relb(op0, 2)); break;
case 0x30:sprintf(t, "bmi $%0.4x", __relb(op0, 2)); break;
case 0x31:sprintf(t, "tcall 3"); break;
case 0x32:sprintf(t, "clr1 $%0.3x", opdp0); break;
case 0x33:sprintf(t, "bbc1 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x34:sprintf(t, "and a,$%0.3x+x", opdp0); break;
case 0x35:sprintf(t, "and a,$%0.4x+x", opw); break;
case 0x36:sprintf(t, "and a,$%0.4x+y", opw); break;
case 0x37:sprintf(t, "and a,($%0.3x)+y", opdp0); break;
case 0x38:sprintf(t, "and $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x39:sprintf(t, "and (x),(y)"); break;
case 0x3a:sprintf(t, "incw $%0.3x", opdp0); break;
case 0x3b:sprintf(t, "rol $%0.3x+x", opdp0); break;
case 0x3c:sprintf(t, "rol a"); break;
case 0x3d:sprintf(t, "inc x"); break;
case 0x3e:sprintf(t, "cmp x,$%0.3x", opdp0); break;
case 0x3f:sprintf(t, "call $%0.4x", opw); break;
case 0x40:sprintf(t, "setp"); break;
case 0x41:sprintf(t, "tcall 4"); break;
case 0x42:sprintf(t, "set2 $%0.3x", opdp0); break;
case 0x43:sprintf(t, "bbs2 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x44:sprintf(t, "eor a,$%0.3x", opdp0); break;
case 0x45:sprintf(t, "eor a,$%0.4x", opw); break;
case 0x46:sprintf(t, "eor a,(x)"); break;
case 0x47:sprintf(t, "eor a,($%0.3x+x)", opdp0); break;
case 0x48:sprintf(t, "eor a,#$%0.2x", op0); break;
case 0x49:sprintf(t, "eor $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x4a:sprintf(t, "and1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x4b:sprintf(t, "lsr $%0.3x", opdp0); break;
case 0x4c:sprintf(t, "lsr $%0.4x", opw); break;
case 0x4d:sprintf(t, "push x"); break;
case 0x4e:sprintf(t, "tclr $%0.4x,a", opw); break;
case 0x4f:sprintf(t, "pcall $ff%0.2x", op0); break;
case 0x50:sprintf(t, "bvc $%0.4x", __relb(op0, 2)); break;
case 0x51:sprintf(t, "tcall 5"); break;
case 0x52:sprintf(t, "clr2 $%0.3x", opdp0); break;
case 0x53:sprintf(t, "bbc2 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x54:sprintf(t, "eor a,$%0.3x+x", opdp0); break;
case 0x55:sprintf(t, "eor a,$%0.4x+x", opw); break;
case 0x56:sprintf(t, "eor a,$%0.4x+y", opw); break;
case 0x57:sprintf(t, "eor a,($%0.3x)+y", opdp0); break;
case 0x58:sprintf(t, "eor $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x59:sprintf(t, "eor (x),(y)"); break;
case 0x5a:sprintf(t, "cmpw ya,$%0.3x", opdp0); break;
case 0x5b:sprintf(t, "lsr $%0.3x+x", opdp0); break;
case 0x5c:sprintf(t, "lsr a"); break;
case 0x5d:sprintf(t, "mov x,a"); break;
case 0x5e:sprintf(t, "cmp y,$%0.4x", opw); break;
case 0x5f:sprintf(t, "jmp $%0.4x", opw); break;
case 0x60:sprintf(t, "clrc"); break;
case 0x61:sprintf(t, "tcall 6"); break;
case 0x62:sprintf(t, "set3 $%0.3x", opdp0); break;
case 0x63:sprintf(t, "bbs3 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x64:sprintf(t, "cmp a,$%0.3x", opdp0); break;
case 0x65:sprintf(t, "cmp a,$%0.4x", opw); break;
case 0x66:sprintf(t, "cmp a,(x)"); break;
case 0x67:sprintf(t, "cmp a,($%0.3x+x)", opdp0); break;
case 0x68:sprintf(t, "cmp a,#$%0.2x", op0); break;
case 0x69:sprintf(t, "cmp $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x6a:sprintf(t, "and1 c,!$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x6b:sprintf(t, "ror $%0.3x", opdp0); break;
case 0x6c:sprintf(t, "ror $%0.4x", opw); break;
case 0x6d:sprintf(t, "push y"); break;
case 0x6e:sprintf(t, "dbnz $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x6f:sprintf(t, "ret"); break;
case 0x70:sprintf(t, "bvs $%0.4x", __relb(op0, 2)); break;
case 0x71:sprintf(t, "tcall 7"); break;
case 0x72:sprintf(t, "clr3 $%0.3x", opdp0); break;
case 0x73:sprintf(t, "bbc3 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x74:sprintf(t, "cmp a,$%0.3x+x", opdp0); break;
case 0x75:sprintf(t, "cmp a,$%0.4x+x", opw); break;
case 0x76:sprintf(t, "cmp a,$%0.4x+y", opw); break;
case 0x77:sprintf(t, "cmp a,($%0.3x)+y", opdp0); break;
case 0x78:sprintf(t, "cmp $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x79:sprintf(t, "cmp (x),(y)"); break;
case 0x7a:sprintf(t, "addw ya,$%0.3x", opdp0); break;
case 0x7b:sprintf(t, "ror $%0.3x+x", opdp0); break;
case 0x7c:sprintf(t, "ror a"); break;
case 0x7d:sprintf(t, "mov a,x"); break;
case 0x7e:sprintf(t, "cmp y,$%0.3x", opdp0); break;
case 0x7f:sprintf(t, "reti"); break;
case 0x80:sprintf(t, "setc"); break;
case 0x81:sprintf(t, "tcall 8"); break;
case 0x82:sprintf(t, "set4 $%0.3x", opdp0); break;
case 0x83:sprintf(t, "bbs4 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x84:sprintf(t, "adc a,$%0.3x", opdp0); break;
case 0x85:sprintf(t, "adc a,$%0.4x", opw); break;
case 0x86:sprintf(t, "adc a,(x)"); break;
case 0x87:sprintf(t, "adc a,($%0.3x+x)", opdp0); break;
case 0x88:sprintf(t, "adc a,#$%0.2x", op0); break;
case 0x89:sprintf(t, "adc $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0x8a:sprintf(t, "eor1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0x8b:sprintf(t, "dec $%0.3x", opdp0); break;
case 0x8c:sprintf(t, "dec $%0.4x", opw); break;
case 0x8d:sprintf(t, "mov y,#$%0.2x", op0); break;
case 0x8e:sprintf(t, "pop p"); break;
case 0x8f:sprintf(t, "mov $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x90:sprintf(t, "bcc $%0.4x", __relb(op0, 2)); break;
case 0x91:sprintf(t, "tcall 9"); break;
case 0x92:sprintf(t, "clr4 $%0.3x", opdp0); break;
case 0x93:sprintf(t, "bbc4 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0x94:sprintf(t, "adc a,$%0.3x+x", opdp0); break;
case 0x95:sprintf(t, "adc a,$%0.4x+x", opw); break;
case 0x96:sprintf(t, "adc a,$%0.4x+y", opw); break;
case 0x97:sprintf(t, "adc a,($%0.3x)+y", opdp0); break;
case 0x98:sprintf(t, "adc $%0.3x,#$%0.2x", opdp1, op0); break;
case 0x99:sprintf(t, "adc (x),(y)"); break;
case 0x9a:sprintf(t, "subw ya,$%0.3x", opdp0); break;
case 0x9b:sprintf(t, "dec $%0.3x+x", opdp0); break;
case 0x9c:sprintf(t, "dec a"); break;
case 0x9d:sprintf(t, "mov x,sp"); break;
case 0x9e:sprintf(t, "div ya,x"); break;
case 0x9f:sprintf(t, "xcn a"); break;
case 0xa0:sprintf(t, "ei"); break;
case 0xa1:sprintf(t, "tcall 10"); break;
case 0xa2:sprintf(t, "set5 $%0.3x", opdp0); break;
case 0xa3:sprintf(t, "bbs5 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xa4:sprintf(t, "sbc a,$%0.3x", opdp0); break;
case 0xa5:sprintf(t, "sbc a,$%0.4x", opw); break;
case 0xa6:sprintf(t, "sbc a,(x)"); break;
case 0xa7:sprintf(t, "sbc a,($%0.3x+x)", opdp0); break;
case 0xa8:sprintf(t, "sbc a,#$%0.2x", op0); break;
case 0xa9:sprintf(t, "sbc $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0xaa:sprintf(t, "mov1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0xab:sprintf(t, "inc $%0.3x", opdp0); break;
case 0xac:sprintf(t, "inc $%0.4x", opw); break;
case 0xad:sprintf(t, "cmp y,#$%0.2x", op0); break;
case 0xae:sprintf(t, "pop a"); break;
case 0xaf:sprintf(t, "mov (x)+,a"); break;
case 0xb0:sprintf(t, "bcs $%0.4x", __relb(op0, 2)); break;
case 0xb1:sprintf(t, "tcall 11"); break;
case 0xb2:sprintf(t, "clr5 $%0.3x", opdp0); break;
case 0xb3:sprintf(t, "bbc5 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xb4:sprintf(t, "sbc a,$%0.3x+x", opdp0); break;
case 0xb5:sprintf(t, "sbc a,$%0.4x+x", opw); break;
case 0xb6:sprintf(t, "sbc a,$%0.4x+y", opw); break;
case 0xb7:sprintf(t, "sbc a,($%0.3x)+y", opdp0); break;
case 0xb8:sprintf(t, "sbc $%0.3x,#$%0.2x", opdp1, op0); break;
case 0xb9:sprintf(t, "sbc (x),(y)"); break;
case 0xba:sprintf(t, "movw ya,$%0.3x", opdp0); break;
case 0xbb:sprintf(t, "inc $%0.3x+x", opdp0); break;
case 0xbc:sprintf(t, "inc a"); break;
case 0xbd:sprintf(t, "mov sp,x"); break;
case 0xbe:sprintf(t, "das a"); break;
case 0xbf:sprintf(t, "mov a,(x)+"); break;
case 0xc0:sprintf(t, "di"); break;
case 0xc1:sprintf(t, "tcall 12"); break;
case 0xc2:sprintf(t, "set6 $%0.3x", opdp0); break;
case 0xc3:sprintf(t, "bbs6 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xc4:sprintf(t, "mov $%0.3x,a", opdp0); break;
case 0xc5:sprintf(t, "mov $%0.4x,a", opw); break;
case 0xc6:sprintf(t, "mov (x),a"); break;
case 0xc7:sprintf(t, "mov ($%0.3x+x),a", opdp0); break;
case 0xc8:sprintf(t, "cmp x,#$%0.2x", op0); break;
case 0xc9:sprintf(t, "mov $%0.4x,x", opw); break;
case 0xca:sprintf(t, "mov1 $%0.4x:%d,c", opw & 0x1fff, opw >> 13); break;
case 0xcb:sprintf(t, "mov $%0.3x,y", opdp0); break;
case 0xcc:sprintf(t, "mov $%0.4x,y", opw); break;
case 0xcd:sprintf(t, "mov x,#$%0.2x", op0); break;
case 0xce:sprintf(t, "pop x"); break;
case 0xcf:sprintf(t, "mul ya"); break;
case 0xd0:sprintf(t, "bne $%0.4x", __relb(op0, 2)); break;
case 0xd1:sprintf(t, "tcall 13"); break;
case 0xd2:sprintf(t, "clr6 $%0.3x", opdp0); break;
case 0xd3:sprintf(t, "bbc6 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xd4:sprintf(t, "mov $%0.3x+x,a", opdp0); break;
case 0xd5:sprintf(t, "mov $%0.4x+x,a", opw); break;
case 0xd6:sprintf(t, "mov $%0.4x+y,a", opw); break;
case 0xd7:sprintf(t, "mov ($%0.3x)+y,a", opdp0); break;
case 0xd8:sprintf(t, "mov $%0.3x,x", opdp0); break;
case 0xd9:sprintf(t, "mov $%0.3x+y,x", opdp0); break;
case 0xda:sprintf(t, "movw $%0.3x,ya", opdp0); break;
case 0xdb:sprintf(t, "mov $%0.3x+x,y", opdp0); break;
case 0xdc:sprintf(t, "dec y"); break;
case 0xdd:sprintf(t, "mov a,y"); break;
case 0xde:sprintf(t, "cbne $%0.3x+x,$%0.4x", opdp0, __relb(op1, 3));break;
case 0xdf:sprintf(t, "daa a"); break;
case 0xe0:sprintf(t, "clrv"); break;
case 0xe1:sprintf(t, "tcall 14"); break;
case 0xe2:sprintf(t, "set7 $%0.3x", opdp0); break;
case 0xe3:sprintf(t, "bbs7 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xe4:sprintf(t, "mov a,$%0.3x", opdp0); break;
case 0xe5:sprintf(t, "mov a,$%0.4x", opw); break;
case 0xe6:sprintf(t, "mov a,(x)"); break;
case 0xe7:sprintf(t, "mov a,($%0.3x+x)", opdp0); break;
case 0xe8:sprintf(t, "mov a,#$%0.2x", op0); break;
case 0xe9:sprintf(t, "mov x,$%0.4x", opw); break;
case 0xea:sprintf(t, "not1 c,$%0.4x:%d", opw & 0x1fff, opw >> 13); break;
case 0xeb:sprintf(t, "mov y,$%0.3x", opdp0); break;
case 0xec:sprintf(t, "mov y,$%0.4x", opw); break;
case 0xed:sprintf(t, "notc"); break;
case 0xee:sprintf(t, "pop y"); break;
case 0xef:sprintf(t, "sleep"); break;
case 0xf0:sprintf(t, "beq $%0.4x", __relb(op0, 2)); break;
case 0xf1:sprintf(t, "tcall 15"); break;
case 0xf2:sprintf(t, "clr7 $%0.3x", opdp0); break;
case 0xf3:sprintf(t, "bbc7 $%0.3x,$%0.4x", opdp0, __relb(op1, 3)); break;
case 0xf4:sprintf(t, "mov a,$%0.3x+x", opdp0); break;
case 0xf5:sprintf(t, "mov a,$%0.4x+x", opw); break;
case 0xf6:sprintf(t, "mov a,$%0.4x+y", opw); break;
case 0xf7:sprintf(t, "mov a,($%0.3x)+y", opdp0); break;
case 0xf8:sprintf(t, "mov x,$%0.3x", opdp0); break;
case 0xf9:sprintf(t, "mov x,$%0.3x+y", opdp0); break;
case 0xfa:sprintf(t, "mov $%0.3x,$%0.3x", opdp1, opdp0); break;
case 0xfb:sprintf(t, "mov y,$%0.3x+x", opdp0); break;
case 0xfc:sprintf(t, "inc y"); break;
case 0xfd:sprintf(t, "mov y,a"); break;
case 0xfe:sprintf(t, "dbnz y,$%0.4x", __relb(op0, 2)); break;
case 0xff:sprintf(t, "stop"); break;
}
t[strlen(t)] = ' ';
strcat(s, t);
sprintf(t, "A:%0.2x X:%0.2x Y:%0.2x SP:01%0.2x YA:%0.4x ",
regs.a, regs.x, regs.y, regs.sp, regs.ya);
strcat(s, t);
sprintf(t, "%c%c%c%c%c%c%c%c",
(regs.p.n)?'N':'n',
(regs.p.v)?'V':'v',
(regs.p.p)?'P':'p',
(regs.p.b)?'B':'b',
(regs.p.h)?'H':'h',
(regs.p.i)?'I':'i',
(regs.p.z)?'Z':'z',
(regs.p.c)?'C':'c');
strcat(s, t);
}

41
src/apu/iplrom.h Normal file
View File

@@ -0,0 +1,41 @@
//This is the IPLROM for the SPC700 coprocessor.
//This array is *read-only*. The SPC700 does not
//allow writing to the IPLROM, all writes are
//instead mapped to the extended SPC700 RAM region,
//accessible when $f1 bit 7 is clear.
const uint8 APU::iplrom[64] = {
/*ffc0*/ 0xcd, 0xef, //mov x,#$ef
/*ffc2*/ 0xbd, //mov sp,x
/*ffc3*/ 0xe8, 0x00, //mov a,#$00
/*ffc5*/ 0xc6, //mov (x),a
/*ffc6*/ 0x1d, //dec x
/*ffc7*/ 0xd0, 0xfc, //bne $ffc5
/*ffc9*/ 0x8f, 0xaa, 0xf4, //mov $f4,#$aa
/*ffcc*/ 0x8f, 0xbb, 0xf5, //mov $f5,#$bb
/*ffcf*/ 0x78, 0xcc, 0xf4, //cmp $f4,#$cc
/*ffd2*/ 0xd0, 0xfb, //bne $ffcf
/*ffd4*/ 0x2f, 0x19, //bra $ffef
/*ffd6*/ 0xeb, 0xf4, //mov y,$f4
/*ffd8*/ 0xd0, 0xfc, //bne $ffd6
/*ffda*/ 0x7e, 0xf4, //cmp y,$f4
/*ffdc*/ 0xd0, 0x0b, //bne $ffe9
/*ffde*/ 0xe4, 0xf5, //mov a,$f5
/*ffe0*/ 0xcb, 0xf4, //mov $f4,y
/*ffe2*/ 0xd7, 0x00, //mov ($00)+y,a
/*ffe4*/ 0xfc, //inc y
/*ffe5*/ 0xd0, 0xf3, //bne $ffda
/*ffe7*/ 0xab, 0x01, //inc $01
/*ffe9*/ 0x10, 0xef, //bpl $ffda
/*ffeb*/ 0x7e, 0xf4, //cmp y,$f4
/*ffed*/ 0x10, 0xeb, //bpl $ffda
/*ffef*/ 0xba, 0xf6, //movw ya,$f6
/*fff1*/ 0xda, 0x00, //movw $00,ya
/*fff3*/ 0xba, 0xf4, //movw ya,$f4
/*fff5*/ 0xc4, 0xf4, //mov $f4,a
/*fff7*/ 0xdd, //mov a,y
/*fff8*/ 0x5d, //mov x,a
/*fff9*/ 0xd0, 0xdb, //bne $ffd6
/*fffb*/ 0x1f, 0x00, 0x00, //jmp ($0000+x)
/*fffe*/ 0xc0, 0xff //---reset vector location ($ffc0)
};

View File

@@ -1,10 +1,36 @@
#include "lib/libbase.h"
//this should be declared in the port-specific makefiles
//#define ARCH_LSB
//#define ARCH_MSB
//structs
typedef struct {
uint8 *data;
uint32 size;
}lfile;
#ifndef ARCH_LSB
#ifndef ARCH_MSB
#define ARCH_LSB
#endif
#endif
#include <time.h>
#include "lib/libbase.h"
#include "lib/libvector.h"
#include "lib/libstring.h"
#include "lib/libconfig.h"
inline uint16 read16(uint8 *addr, uint pos) {
#ifdef ARCH_LSB
return *((uint16*)(addr + pos));
#else
return (addr[pos]) | (addr[pos + 1] << 8);
#endif
}
#if defined(_WIN32)
#define _WIN32_
#undef _UNIX_
#elif defined(__GNUC__)
#define _UNIX_
#undef _WIN32_
#else
#error "unknown architecture"
#endif
//platform-specific global functions
void *memalloc(uint32 size, char *name = 0, ...);

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

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

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

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

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

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

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

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

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

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

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

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

View File

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

View File

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

View File

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

View File

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

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

@@ -0,0 +1,28 @@
Config config_file;
namespace config {
SNES::VideoColorAdjust SNES::video_color_curve(&config_file, "snes.video_color_curve",
"Applies contrast adjust filter to video output when enabled\n"
"Works by lowering the brightness of darker colors,\n"
"while leaving brighter colors alone; thus reducing saturation",
true, Setting::TRUE_FALSE);
SNES::VideoColorAdjust SNES::video_color_adjust_mode(&config_file, "snes.video_color_adjust_mode",
"Selects color adjustment filter for video output\n"
" 0 = Normal (no filter, rgb555)\n"
" 1 = Grayscale mode (l5)\n"
" 2 = VGA mode (rgb332)\n"
" 3 = Genesis mode (rgb333)",
0, Setting::DEC);
void SNES::VideoColorAdjust::set(uint32 _data) {
data = _data;
::snes->update_color_lookup_table();
}
Setting SNES::mute(&config_file, "snes.mute",
"Mutes SNES audio output when enabled",
true, Setting::TRUE_FALSE);
};

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

@@ -0,0 +1,15 @@
extern Config config_file;
namespace config {
extern struct SNES {
static class VideoColorAdjust : public Setting {
public:
void set(uint32 _data);
SettingOperators(VideoColorAdjust);
} video_color_curve, video_color_adjust_mode;
static Setting mute;
} snes;
};

View File

@@ -1,169 +1,104 @@
#include "../../base.h"
#include "bcpu_op_adc.cpp"
#include "bcpu_op_and.cpp"
#include "bcpu_op_cmp.cpp"
#include "bcpu_op_eor.cpp"
#include "bcpu_op_incdec.cpp"
#include "bcpu_op_lda.cpp"
#include "bcpu_op_misc.cpp"
#include "bcpu_op_ora.cpp"
#include "bcpu_opfn.cpp"
#include "bcpu_op_read.cpp"
#include "bcpu_op_rmw.cpp"
#include "bcpu_op_write.cpp"
#include "bcpu_op_pc.cpp"
#include "bcpu_op_sbc.cpp"
#include "bcpu_op_shift.cpp"
#include "bcpu_op_sta.cpp"
#include "bcpu_op_stack.cpp"
#include "bcpu_op_misc.cpp"
#include "bcpu_exec.cpp"
#include "bcpu_mmio.cpp"
#include "bcpu_dma.cpp"
uint8 bCPU::pio_status() {
return status.pio;
}
#include "bcpu_timing.cpp"
/***********
*** IRQ ***
***********
cycles:
[1] pbr,pc ; io
[2] pbr,pc ; io
[3] 0,s ; pbr
[4] 0,s-1 ; pch
[5] 0,s-2 ; pcl
[6] 0,s-3 ; p
[7] 0,va ; aavl
[8] 0,va+1 ; aavh
*/
void bCPU::irq(uint16 addr) {
if(cpustate == CPUSTATE_WAI) {
regs.pc.w++;
cpustate = CPUSTATE_RUN;
}
#include "bcpu_int.cpp"
clock->add_cc1_cycles(mem_bus->speed(regs.pc)); //1
clock->add_cc1_cycles(6); //2
stack_write(regs.pc.b); //3
stack_write(regs.pc.h); //4
stack_write(regs.pc.l); //5
stack_write(regs.p); //6
rd.l = op_read(OPMODE_ADDR, addr); //7
rd.h = op_read(OPMODE_ADDR, addr + 1); //8
regs.pc.b = 0x00;
regs.pc.w = rd.w;
regs.p.d = 0;
regs.p.i = 1;
snes->notify(SNES::CPU_EXEC_OPCODE);
}
uint8 bCPU::pio_status() { return status.pio; }
void bCPU::run() {
uint16 v, h, hc, vs;
v = clock->vcounter();
h = clock->hcounter();
hc = clock->hcycles();
vs = clock->visible_scanlines();
if(run_state.hdma) {
exec_hdma();
return;
}
//HDMA test
if(v < vs && h >= 278) {
if(status.hdma_triggered == false) {
status.hdma_triggered = true;
dma->hdma_run();
if(run_state.dma) {
exec_dma();
return;
}
if(run_state.irq) {
irq_run();
return;
}
if(run_state.stp) {
exec_cycle();
return;
}
if(status.cycle_pos == 0) {
//interrupts only trigger on opcode edges
if(time.nmi_pending == true) {
time.nmi_pending = false;
aa.w = 0xffea;
run_state.irq = true;
return;
}
if(time.irq_pending == true) {
time.irq_pending = false;
aa.w = 0xffee;
run_state.irq = true;
return;
}
}
switch(cpustate) {
case CPUSTATE_RUN:
case CPUSTATE_WAI:
//NMI test
if(v >= (vs + 1) && status.nmi_triggered == false) {
if((v == (vs + 1) && hc >= 12) || (v > (vs + 1))) {
status.nmi_triggered = true;
status.nmi_pin = 0;
if(status.nmi_enabled == true) {
irq(0xffea);
return;
}
}
}
//IRQ test
if(!regs.p.i) {
if(status.virq_enabled == true && status.virq_enabled == true) {
if(v == status.virq_pos && h >= status.hirq_pos && status.irq_pin == 1) {
status.irq_triggered = true;
status.irq_pin = 0;
irq(0xffee);
return;
}
} else if(status.virq_enabled == true) {
if(v == status.virq_pos && status.irq_pin == 1) {
status.irq_triggered = true;
status.irq_pin = 0;
irq(0xffee);
return;
}
} else if(status.hirq_enabled == true) {
if(h >= status.hirq_pos && status.irq_pin == 1) {
status.irq_triggered = true;
status.irq_pin = 0;
irq(0xffee);
return;
}
}
}
exec_opcode();
break;
case CPUSTATE_DMA:
dma->run();
break;
case CPUSTATE_STP:
exec_opcode();
break;
}
exec_cycle();
}
void bCPU::scanline() {
uint16 v = clock->vcounter();
status.hdma_triggered = false;
time.hdma_triggered = false;
if(v == 225 && status.auto_joypad_poll == true) {
snes->poll_input();
//When the SNES auto-polls the joypads, it writes 1, then 0 to
//$4016, then reads from each 16 times to get the joypad state
//information. As a result, the joypad read positions are set
//to 16 after such a poll. Position 16 is the controller
//connected status bit.
if(vcounter() == 225 && status.auto_joypad_poll == true) {
snes->poll_input(SNES::DEV_JOYPAD1);
snes->poll_input(SNES::DEV_JOYPAD2);
//When the SNES auto-polls the joypads, it writes 1, then 0 to
//$4016, then reads from each 16 times to get the joypad state
//information. As a result, the joypad read positions are set
//to 16 after such a poll. Position 16 is the controller
//connected status bit.
status.joypad1_read_pos = 16;
}
if(status.virq_enabled == false) {
status.irq_pin = 1;
status.joypad2_read_pos = 16;
}
}
void bCPU::frame() {
status.hdma_triggered = false;
time.nmi_read = 1;
time.nmi_line = 1;
time.nmi_transition = 0;
status.nmi_triggered = false;
status.r4210_read = false;
status.irq_pin = 1;
dma->hdma_initialize();
if(cpu_version == 2) {
time.hdmainit_trigger_pos = 12 + dma_counter();
} else {
time.hdmainit_trigger_pos = 12 + 8 - dma_counter();
}
time.hdmainit_triggered = false;
}
void bCPU::power() {
region = snes->region();
regs.a = regs.x = regs.y = 0x0000;
regs.s = 0x01ff;
reset();
}
void bCPU::reset() {
/* reset vector location */
//reset vector location
regs.pc = mem_bus->read(0xfffc) | (mem_bus->read(0xfffd) << 8);
/* registers are not fully reset by SNES */
//registers are not fully reset by SNES
regs.x.h = 0x00;
regs.y.h = 0x00;
regs.s.h = 0x01;
@@ -171,131 +106,145 @@ void bCPU::reset() {
regs.db = 0x00;
regs.p = 0x34;
regs.e = 1;
regs.mdr = 0x00;
cpustate = CPUSTATE_RUN;
dma->reset();
time_reset();
mmio_reset();
dma_reset();
optbl = optbl_e;
run_state.hdma = false;
run_state.dma = false;
run_state.irq = false;
run_state.wai = false;
run_state.stp = false;
status.hdma_triggered = false;
status.cycle_pos = 0;
status.cycle_count = 0;
status.cycles_executed = 0;
status.nmi_triggered = false;
status.nmi_pin = 1;
status.r4210_read = false;
apu_port[0] = 0x00;
apu_port[1] = 0x00;
apu_port[2] = 0x00;
apu_port[3] = 0x00;
status.irq_triggered = false;
status.irq_pin = 1;
frame();
//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);
}
uint8 bCPU::port_read(uint8 port) {
return apu_port[port & 3];
}
void bCPU::port_write(uint8 port, uint8 value) {
apu_port[port & 3] = value;
}
void bCPU::cpu_c2() {
if(regs.d.l != 0x00) {
clock->add_cc1_cycles(6);
cpu_io();
}
}
void bCPU::cpu_c4(uint16 a, uint16 b) {
if(((a & 0xff00) != (b & 0xff00)) || !regs.p.x) {
clock->add_cc1_cycles(6);
void bCPU::cpu_c4(uint16 x, uint16 y) {
if(!regs.p.x && (x & 0xff00) != (y & 0xff00)) {
cpu_io();
}
}
void bCPU::cpu_c6(uint16 a) {
if(regs.e) {
if((regs.pc.w & 0xff00) != (a & 0xff00)) {
clock->add_cc1_cycles(6);
}
void bCPU::cpu_c6(uint16 addr) {
if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) {
cpu_io();
}
}
/* 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() {
clock->add_cc1_cycles(6);
status.cycle_count = 6;
pre_exec_cycle();
add_cycles(6);
}
uint8 bCPU::mem_read(uint32 addr) {
status.cycle_count = mem_bus->speed(addr);
pre_exec_cycle();
add_cycles(status.cycle_count - 4);
regs.mdr = mem_bus->read(addr);
add_cycles(4);
return regs.mdr;
}
void bCPU::mem_write(uint32 addr, uint8 value) {
status.cycle_count = mem_bus->speed(addr);
pre_exec_cycle();
add_cycles(status.cycle_count);
mem_bus->write(addr, value);
}
uint32 bCPU::op_addr(uint8 mode, uint32 addr) {
switch(mode) {
case OPMODE_ADDR:
addr &= 0xffff;
break;
case OPMODE_LONG:
addr &= 0xffffff;
break;
case OPMODE_DBR:
addr = ((regs.db << 16) + addr) & 0xffffff;
break;
case OPMODE_PBR:
addr &= 0xffff;
addr = (regs.pc.b << 16) + addr;
break;
case OPMODE_DP:
addr &= 0xffff;
addr = (regs.d + addr) & 0xffff;
break;
case OPMODE_SP:
addr &= 0xffff;
addr = (regs.s + addr) & 0xffff;
break;
}
return addr;
}
uint8 bCPU::op_read() {
uint8 r;
r = mem_bus->read(regs.pc);
clock->add_cc1_cycles(mem_bus->speed(regs.pc));
r = mem_read(regs.pc.d);
regs.pc.w++;
return r;
}
uint8 bCPU::op_read(uint8 mode, uint32 addr) {
uint8 r;
switch(mode) {
case OPMODE_ADDR:
addr &= 0xffff;
break;
case OPMODE_LONG:
addr &= 0xffffff;
break;
case OPMODE_DBR:
addr &= 0xffffff;
addr = (regs.db << 16) + addr;
break;
case OPMODE_PBR:
addr &= 0xffff;
addr = (regs.pc.b << 16) | addr;
break;
case OPMODE_DP:
addr &= 0xffff;
addr = (regs.d + addr) & 0xffff;
break;
case OPMODE_SP:
addr &= 0xffff;
addr = (regs.s + addr) & 0xffff;
break;
}
r = mem_bus->read(addr);
clock->add_cc1_cycles(mem_bus->speed(addr));
return r;
addr = op_addr(mode, addr);
return mem_read(addr);
}
void bCPU::op_write(uint8 mode, uint32 addr, uint8 value) {
switch(mode) {
case OPMODE_ADDR:
addr &= 0xffff;
break;
case OPMODE_LONG:
addr &= 0xffffff;
break;
case OPMODE_DBR:
addr &= 0xffffff;
addr = (regs.db << 16) + addr;
break;
case OPMODE_PBR:
addr &= 0xffff;
addr = (regs.pc.b << 16) | addr;
break;
case OPMODE_DP:
addr &= 0xffff;
addr = (regs.d + addr) & 0xffff;
break;
case OPMODE_SP:
addr &= 0xffff;
addr = (regs.s + addr) & 0xffff;
break;
}
mem_bus->write(addr, value);
clock->add_cc1_cycles(mem_bus->speed(addr));
addr = op_addr(mode, addr);
mem_write(addr, value);
}
uint8 bCPU::stack_read() {
byte r;
if(regs.e) {
regs.s.l++;
} else {
regs.s.w++;
}
r = mem_bus->read(regs.s);
clock->add_cc1_cycles(mem_bus->speed(regs.s));
return r;
return mem_read(regs.s);
}
void bCPU::stack_write(uint8 value) {
mem_bus->write(regs.s, value);
clock->add_cc1_cycles(mem_bus->speed(regs.s));
mem_write(regs.s, value);
if(regs.e) {
regs.s.l--;
} else {
@@ -304,13 +253,10 @@ void bCPU::stack_write(uint8 value) {
}
bCPU::bCPU() {
dma = new bDMA(this);
mmio = new bCPUMMIO(this);
init_op_tables();
}
bCPU::~bCPU() {
delete(mmio);
delete(dma);
}

View File

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

250
src/cpu/bcpu/bcpu_dma.cpp Normal file
View File

@@ -0,0 +1,250 @@
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 index) {
uint8 x;
if(sdd1->dma_active() == true) {
x = sdd1->dma_read();
} else {
x = mem_bus->read(dma_addr(i));
}
mem_bus->write(0x2100 | ((channel[i].destaddr + index) & 0xff), x);
add_cycles(8);
channel[i].xfersize--;
}
void bCPU::dma_mmiotocpu(uint8 i, uint8 index) {
uint8 x;
x = mem_bus->read(0x2100 | ((channel[i].destaddr + index) & 0xff));
mem_bus->write(dma_addr(i), x);
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() {
int i;
for(i=0;i<8;i++) {
if(channel[i].active == false)continue;
//first byte transferred?
if(channel[i].read_index == 0) {
sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr),
channel[i].xfersize);
}
switch(channel[i].xfermode) {
case 0:dma_write(i, 0); break; //0
case 1:dma_write(i, channel[i].read_index & 1); break; //0,1
case 2:dma_write(i, 0); break; //0,0
case 3:dma_write(i, (channel[i].read_index >> 1) & 1);break; //0,0,1,1
case 4:dma_write(i, channel[i].read_index & 3); break; //0,1,2,3
case 5:dma_write(i, channel[i].read_index & 1); break; //0,1,0,1
case 6:dma_write(i, 0); break; //0,0 [2]
case 7:dma_write(i, (channel[i].read_index >> 1) & 1);break; //0,0,1,1 [3]
}
channel[i].read_index++;
dma_add_cycles(8);
if(channel[i].xfersize == 0) {
channel[i].active = 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++);
}
uint16 bCPU::hdma_mmio(uint8 i) {
uint8 l = channel[i].read_index;
uint16 index;
switch(channel[i].xfermode) {
case 0:index = 0; break; //0
case 1:index = l & 1; break; //0,1
case 2:index = 0; break; //0,0
case 3:index = (l >> 1) & 1;break; //0,0,1,1
case 4:index = l & 3; break; //0,1,2,3
case 5:index = l & 1; break; //0,1,0,1
case 6:index = 0; break; //0,0 [2]
case 7:index = (l >> 1) & 1;break; //0,0,1,1 [3]
}
return (0x2100 | ((channel[i].destaddr + index) & 0xff));
}
uint8 bCPU::hdma_read(uint8 i) {
if(channel[i].direction == DMA_MMIOTOCPU) {
return mem_bus->read(hdma_mmio(i));
} else if(!channel[i].hdma_indirect) {
return mem_bus->read(hdma_addr(i));
} else {
return mem_bus->read(hdma_iaddr(i));
}
}
void bCPU::hdma_write(uint8 i, uint8 x) {
if(channel[i].direction == DMA_CPUTOMMIO) {
mem_bus->write(hdma_mmio(i), x);
} else if(!channel[i].hdma_indirect) {
mem_bus->write(hdma_addr(i), x);
} else {
mem_bus->write(hdma_iaddr(i), x);
}
add_cycles(8);
hdma_add_cycles(8);
}
void bCPU::hdma_update(uint8 i) {
channel[i].hdma_line_counter = mem_bus->read(hdma_addr(i));
add_cycles(8);
hdma_add_cycles(8);
if(channel[i].hdma_indirect) {
channel[i].hdma_iaddr = mem_bus->read(hdma_addr(i)) << 8;
add_cycles(8);
hdma_add_cycles(8);
}
if(channel[i].hdma_line_counter == 0) {
channel[i].hdma_active = false;
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 |= mem_bus->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_active)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++) {
hdma_write(i, hdma_read(i));
}
}
channel[i].hdma_line_counter--;
channel[i].hdma_do_transfer = !!(channel[i].hdma_line_counter & 0x80);
if((channel[i].hdma_line_counter & 0x7f) == 0) {
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_active)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_active = 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() {
for(int i=0;i<8;i++) {
channel[i].read_index = 0;
channel[i].active = false;
channel[i].hdma_enabled = false;
channel[i].dmap = 0x00;
channel[i].direction = 0;
channel[i].hdma_indirect = false;
channel[i].incmode = 1;
channel[i].fixedxfer = false;
channel[i].xfermode = 0;
channel[i].destaddr = 0;
channel[i].srcaddr = 0;
channel[i].xfersize = 0x0000;
//xfersize and hdma_iaddr are of union { uint16 };
//channel[i].hdma_iaddr = 0x0000;
channel[i].hdma_ibank = 0;
channel[i].hdma_addr = 0x0000;
channel[i].hdma_line_counter = 0x00;
channel[i].hdma_unknown = 0x00;
channel[i].hdma_active = false;
channel[i].hdma_do_transfer = false;
}
}

View File

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

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

@@ -0,0 +1,67 @@
/*
[IRQ cycles]
[0] pbr,pc ; opcode
[1] pbr,pc ; io
[2] 0,s ; pbr
[3] 0,s-1 ; pch
[4] 0,s-2 ; pcl
[5] 0,s-3 ; p
[6] 0,va ; aavl
[7] 0,va+1 ; aavh
*/
void bCPU::irq_run() {
//WDC documentation is incorrect, first cycle
//is a memory read fetch from PBR:PC
switch(status.cycle_pos++) {
case 0: add_cycles(mem_bus->speed(regs.pc.d)); break;
case 1: add_cycles(6); break;
case 2: stack_write(regs.pc.b); break;
case 3: stack_write(regs.pc.h); break;
case 4: stack_write(regs.pc.l); break;
case 5: stack_write(regs.p); break;
case 6: rd.l = op_read(OPMODE_ADDR, aa.w); break;
case 7: rd.h = op_read(OPMODE_ADDR, aa.w + 1);
regs.pc.b = 0x00;
regs.pc.w = rd.w;
regs.p.i = 1;
regs.p.d = 0;
//let debugger know the new IRQ opcode address
snes->notify(SNES::CPU_EXEC_OPCODE_END);
status.cycle_pos = 0;
run_state.irq = false;
break;
}
}
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;
if(regs.p.i)return false;
return true;
}

View File

@@ -2,9 +2,11 @@ void bCPU::mmio_reset() {
//$2181-$2183
status.wram_addr = 0x000000;
//$4016
//$4016-$4017
status.joypad1_strobe_value = 0x00;
status.joypad2_strobe_value = 0x00;
status.joypad1_read_pos = 0;
status.joypad2_read_pos = 0;
//$4200
status.nmi_enabled = false;
@@ -41,29 +43,22 @@ uint8 r;
return r;
}
//???
uint8 bCPU::mmio_r21c2() {
return 0x20;
}
//???
uint8 bCPU::mmio_r21c3() {
return 0x00;
}
/*
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.
*/
//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 = 0x00;
uint8 r;
r = regs.mdr & 0xfc;
if(status.joypad1_strobe_value == 1) {
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B);
} else {
@@ -85,65 +80,98 @@ uint8 r = 0x00;
}
if(++status.joypad1_read_pos > 17)status.joypad1_read_pos = 17;
}
return r;
}
//JOYSER1
//7-5 = MDR
//4-2 = Always 1
//1-0 = Joypad serial data
uint8 bCPU::mmio_r4017() {
uint8 r;
r = regs.mdr & 0xe0;
r |= 0x1c;
if(status.joypad2_strobe_value == 1) {
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_B);
} else {
switch(status.joypad2_read_pos) {
case 0:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_B); break;
case 1:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_Y); break;
case 2:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_SELECT);break;
case 3:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_START); break;
case 4:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_UP); break;
case 5:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_DOWN); break;
case 6:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_LEFT); break;
case 7:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_RIGHT); break;
case 8:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_A); break;
case 9:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_X); break;
case 10:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_L); break;
case 11:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_R); break;
case 16:r |= 1;break; //joypad connected bit
default:r |= 1;break; //after 16th read, all subsequent reads return 1
}
if(++status.joypad2_read_pos > 17)status.joypad2_read_pos = 17;
}
return r;
}
//RDNMI
//7 = NMI acknowledge
//6-4 = MDR
//3-0 = CPU (5a22) version
uint8 bCPU::mmio_r4210() {
uint8 r = 0x00;
uint16 v, h, hcycles, visible_scanlines;
v = clock->vcounter();
h = clock->hcounter();
hcycles = clock->hcycles();
visible_scanlines = clock->visible_scanlines();
if(status.r4210_read == false) {
if(v == 0 && hcycles < 2) {
r |= 0x80;
status.r4210_read = true;
} else if(v == (visible_scanlines + 1) && hcycles >= 2) {
r |= 0x80;
status.r4210_read = true;
} else if(v >= (visible_scanlines + 1)) {
r |= 0x80;
status.r4210_read = true;
}
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 |= 0x40;
r |= 0x02; //cpu version number
status.nmi_pin = 1;
r |= (cpu_version & 0x0f);
return r;
}
//TIMEUP
//7 = IRQ acknowledge
//6-0 = MDR
uint8 bCPU::mmio_r4211() {
uint8 r = 0x00;
r |= 0x40;
if(status.irq_triggered == true)r |= 0x80;
status.irq_triggered = false;
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;
uint16 v, h, hcycles, visible_scanlines;
r = 0x00;
uint8 r;
r = regs.mdr & 0x3e;
v = clock->vcounter();
h = clock->hcounter();
hcycles = clock->hcycles();
visible_scanlines = clock->visible_scanlines();
uint16 vs = overscan() ? 240 : 225;
//auto joypad polling
if(v >= (visible_scanlines + 1) && v <= (visible_scanlines + 3))r |= 0x01;
if(time.v >= vs && time.v <= (vs + 2))r |= 0x01;
//hblank
if(hcycles <= 4 || hcycles >= 1098)r |= 0x40;
if(time.hc <= 2 || time.hc >= 1096)r |= 0x40;
//vblank
if(v == 0 && hcycles < 2)r |= 0x80;
if(v == (visible_scanlines + 1) && hcycles >= 2)r |= 0x80;
if(v > (visible_scanlines + 1))r |= 0x80;
if(time.v >= vs)r |= 0x80;
return r;
}
@@ -174,8 +202,8 @@ uint8 bCPU::mmio_r4217() {
//JOY1L
uint8 bCPU::mmio_r4218() {
uint8 r = 0x00;
uint16 v = clock->vcounter();
uint8 r = 0x00;
uint16 v = vcounter();
if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled
//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_A) << 7;
@@ -187,8 +215,8 @@ uint16 v = clock->vcounter();
//JOY1H
uint8 bCPU::mmio_r4219() {
uint8 r = 0x00;
uint16 v = clock->vcounter();
uint8 r = 0x00;
uint16 v = vcounter();
if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled
//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B) << 7;
@@ -202,13 +230,130 @@ uint16 v = clock->vcounter();
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::DEV_JOYPAD2, SNES::JOYPAD_A) << 7;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_X) << 6;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_L) << 5;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_R) << 4;
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::DEV_JOYPAD2, SNES::JOYPAD_B) << 7;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_Y) << 6;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_SELECT) << 5;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_START) << 4;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_UP) << 3;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_DOWN) << 2;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_LEFT) << 1;
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_RIGHT);
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 bCPUMMIO::read(uint32 addr) {
clock->sync();
uint i;
//APU
if(addr >= 0x2140 && addr <= 0x217f) {
return apu->port_read(addr & 3);
}
//HDMA
if(addr >= 0x4300 && addr <= 0x437f) {
i = (addr >> 4) & 7;
switch(addr & 0xf) {
case 0x0:return cpu->mmio_r43x0(i);
case 0x1:return cpu->mmio_r43x1(i);
case 0x2:return cpu->mmio_r43x2(i);
case 0x3:return cpu->mmio_r43x3(i);
case 0x4:return cpu->mmio_r43x4(i);
case 0x5:return cpu->mmio_r43x5(i);
case 0x6:return cpu->mmio_r43x6(i);
case 0x7:return cpu->mmio_r43x7(i);
case 0x8:return cpu->mmio_r43x8(i);
case 0x9:return cpu->mmio_r43x9(i);
case 0xa:return cpu->mmio_r43xa(i);
case 0xb:return cpu->mmio_r43xb(i);
case 0xc:return cpu->regs.mdr; //unmapped
case 0xd:return cpu->regs.mdr; //unmapped
case 0xe:return cpu->regs.mdr; //unmapped
case 0xf:return cpu->mmio_r43xb(i); //mirror of 43xb
}
}
switch(addr) {
case 0x2180:return cpu->mmio_r2180(); //WMDATA
case 0x21c2:return cpu->mmio_r21c2(); //???
case 0x21c3:return cpu->mmio_r21c3(); //???
case 0x4016:return cpu->mmio_r4016(); //JOYSER0
case 0x4017:return cpu->mmio_r4017(); //JOYSER1
case 0x4210:return cpu->mmio_r4210(); //RDNMI
case 0x4211:return cpu->mmio_r4211(); //TIMEUP
case 0x4212:return cpu->mmio_r4212(); //HVBJOY
@@ -219,8 +364,12 @@ uint8 bCPUMMIO::read(uint32 addr) {
case 0x4217:return cpu->mmio_r4217(); //RDMPYH
case 0x4218:return cpu->mmio_r4218(); //JOY1L
case 0x4219:return cpu->mmio_r4219(); //JOY1H
case 0x421a:return cpu->mmio_r421a(); //JOY2L
case 0x421b:return cpu->mmio_r421b(); //JOY2H
case 0x421c:case 0x421d:case 0x421e:case 0x421f:return 0x00;
}
return 0x00;
return cpu->regs.mdr;
}
//WMDATA
@@ -250,19 +399,43 @@ void bCPU::mmio_w2183(uint8 value) {
//JOYSER0
void bCPU::mmio_w4016(uint8 value) {
status.joypad1_strobe_value = (value & 1);
status.joypad1_strobe_value = !!(value & 1);
if(value == 1) {
snes->poll_input();
snes->poll_input(SNES::DEV_JOYPAD1);
status.joypad1_read_pos = 0;
}
}
//JOYSER1
void bCPU::mmio_w4017(uint8 value) {
status.joypad2_strobe_value = !!(value & 1);
if(value == 1) {
snes->poll_input(SNES::DEV_JOYPAD2);
status.joypad2_read_pos = 0;
}
}
//NMITIMEN
void bCPU::mmio_w4200(uint8 value) {
status.nmi_enabled = !!(value & 0x80);
status.virq_enabled = !!(value & 0x20);
status.hirq_enabled = !!(value & 0x10);
status.auto_joypad_poll = !!(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
@@ -296,42 +469,48 @@ void bCPU::mmio_w4205(uint8 value) {
//WRDIVB
void bCPU::mmio_w4206(uint8 value) {
status.div_b = value;
status.r4214 = (status.div_b)?status.div_a / status.div_b:0;
status.r4216 = (status.div_b)?status.div_a % status.div_b:0;
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;
update_interrupts();
}
//HTIMEH
void bCPU::mmio_w4208(uint8 value) {
status.hirq_pos = (status.hirq_pos & 0x00ff) | (value << 8);
update_interrupts();
}
//VTIMEL
void bCPU::mmio_w4209(uint8 value) {
status.virq_pos = (status.virq_pos & 0xff00) | value;
update_interrupts();
}
//VTIMEH
void bCPU::mmio_w420a(uint8 value) {
status.virq_pos = (status.virq_pos & 0x00ff) | (value << 8);
update_interrupts();
}
//DMAEN
void bCPU::mmio_w420b(uint8 value) {
int len;
if(value != 0x00) {
clock->add_cc1_cycles(18);
run_state.dma = true;
status.dma_state = DMASTATE_DMASYNC;
}
for(int i=0;i<8;i++) {
if(value & (1 << i)) {
dma->channel[i].active = true;
dma->channel[i].hdma_active = false;
clock->add_cc1_cycles(8);
cpustate = CPUSTATE_DMA;
channel[i].active = true;
channel[i].hdma_enabled = false;
channel[i].hdma_active = false;
channel[i].read_index = 0;
}
}
}
@@ -339,68 +518,119 @@ void bCPU::mmio_w420b(uint8 value) {
//HDMAEN
void bCPU::mmio_w420c(uint8 value) {
for(int i=0;i<8;i++) {
dma->channel[i].hdma_active = !!(value & (1 << i));
channel[i].hdma_enabled = !!(value & (1 << i));
channel[i].hdma_active = !!(value & (1 << i));
}
}
//MEMSEL
void bCPU::mmio_w420d(uint8 value) {
mem_bus->fastROM = value & 1;
mem_bus->set_speed(value & 1);
}
//DMAPx
void bCPU::mmio_w43x0(uint8 value, uint8 i) {
dma->channel[i].direction = !!(value & 0x80);
dma->channel[i].hdma_indirect = !!(value & 0x40);
dma->channel[i].incmode = (value & 0x10)?-1:1;
dma->channel[i].fixedxfer = !!(value & 0x08);
dma->channel[i].xfermode = value & 7;
channel[i].dmap = value;
channel[i].direction = !!(value & 0x80);
channel[i].hdma_indirect = !!(value & 0x40);
channel[i].incmode = (value & 0x10)?-1:1;
channel[i].fixedxfer = !!(value & 0x08);
channel[i].xfermode = value & 7;
}
//BBADx
void bCPU::mmio_w43x1(uint8 value, uint8 i) {
dma->channel[i].destaddr = value;
channel[i].destaddr = value;
}
//A1TxL
void bCPU::mmio_w43x2(uint8 value, uint8 i) {
dma->channel[i].srcaddr = (dma->channel[i].srcaddr & 0xffff00) | value;
channel[i].srcaddr = (channel[i].srcaddr & 0xff00) | value;
}
//A1TxH
void bCPU::mmio_w43x3(uint8 value, uint8 i) {
dma->channel[i].srcaddr = (dma->channel[i].srcaddr & 0xff00ff) | (value << 8);
channel[i].srcaddr = (channel[i].srcaddr & 0x00ff) | (value << 8);
}
//A1Bx
void bCPU::mmio_w43x4(uint8 value, uint8 i) {
dma->channel[i].srcaddr = (dma->channel[i].srcaddr & 0x00ffff) | (value << 16);
channel[i].srcbank = value;
}
//DASxL
void bCPU::mmio_w43x5(uint8 value, uint8 i) {
dma->channel[i].xfersize = (dma->channel[i].xfersize & 0xff00) | value;
channel[i].xfersize = (channel[i].xfersize & 0xff00) | value;
}
//DASxH
void bCPU::mmio_w43x6(uint8 value, uint8 i) {
dma->channel[i].xfersize = (dma->channel[i].xfersize & 0x00ff) | (value << 8);
channel[i].xfersize = (channel[i].xfersize & 0x00ff) | (value << 8);
}
//DASBx
void bCPU::mmio_w43x7(uint8 value, uint8 i) {
dma->channel[i].hdma_indirect_bank = value;
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 bCPUMMIO::write(uint32 addr, uint8 value) {
int i;
clock->sync();
uint8 i;
//APU
if(addr >= 0x2140 && addr <= 0x217f) {
cpu->port_write(addr & 3, value);
return;
}
//HDMA
if(addr >= 0x4300 && addr <= 0x437f) {
i = (addr >> 4) & 7;
switch(addr & 0xf) {
case 0x0:cpu->mmio_w43x0(value, i);return;
case 0x1:cpu->mmio_w43x1(value, i);return;
case 0x2:cpu->mmio_w43x2(value, i);return;
case 0x3:cpu->mmio_w43x3(value, i);return;
case 0x4:cpu->mmio_w43x4(value, i);return;
case 0x5:cpu->mmio_w43x5(value, i);return;
case 0x6:cpu->mmio_w43x6(value, i);return;
case 0x7:cpu->mmio_w43x7(value, i);return;
case 0x8:cpu->mmio_w43x8(value, i);return;
case 0x9:cpu->mmio_w43x9(value, i);return;
case 0xa:cpu->mmio_w43xa(value, i);return;
case 0xb:cpu->mmio_w43xb(value, i);return;
case 0xc:return; //unmapped
case 0xd:return; //unmapped
case 0xe:return; //unmapped
case 0xf:cpu->mmio_w43xb(value, i);return; //mirror of 43xb
}
}
switch(addr) {
case 0x2180:cpu->mmio_w2180(value);return; //WMDATA
case 0x2181:cpu->mmio_w2181(value);return; //WMADDL
case 0x2182:cpu->mmio_w2182(value);return; //WMADDM
case 0x2183:cpu->mmio_w2183(value);return; //WMADDH
case 0x4016:cpu->mmio_w4016(value);return; //JOYSER0
case 0x4017:cpu->mmio_w4017(value);return; //JOYSER1
case 0x4200:cpu->mmio_w4200(value);return; //NMITIMEN
case 0x4201:cpu->mmio_w4201(value);return; //WRIO
case 0x4202:cpu->mmio_w4202(value);return; //WRMPYA
@@ -415,288 +645,9 @@ int i;
case 0x420b:cpu->mmio_w420b(value);return; //DMAEN
case 0x420c:cpu->mmio_w420c(value);return; //HDMAEN
case 0x420d:cpu->mmio_w420d(value);return; //MEMSEL
//DMAPx
case 0x4300:case 0x4310:case 0x4320:case 0x4330:
case 0x4340:case 0x4350:case 0x4360:case 0x4370:
cpu->mmio_w43x0(value, (addr >> 4) & 7);
return;
//BBADx
case 0x4301:case 0x4311:case 0x4321:case 0x4331:
case 0x4341:case 0x4351:case 0x4361:case 0x4371:
cpu->mmio_w43x1(value, (addr >> 4) & 7);
return;
//A1TxL
case 0x4302:case 0x4312:case 0x4322:case 0x4332:
case 0x4342:case 0x4352:case 0x4362:case 0x4372:
cpu->mmio_w43x2(value, (addr >> 4) & 7);
return;
//A1TxH
case 0x4303:case 0x4313:case 0x4323:case 0x4333:
case 0x4343:case 0x4353:case 0x4363:case 0x4373:
cpu->mmio_w43x3(value, (addr >> 4) & 7);
return;
//A1Bx
case 0x4304:case 0x4314:case 0x4324:case 0x4334:
case 0x4344:case 0x4354:case 0x4364:case 0x4374:
cpu->mmio_w43x4(value, (addr >> 4) & 7);
return;
//DASxL
case 0x4305:case 0x4315:case 0x4325:case 0x4335:
case 0x4345:case 0x4355:case 0x4365:case 0x4375:
cpu->mmio_w43x5(value, (addr >> 4) & 7);
return;
//DASxH
case 0x4306:case 0x4316:case 0x4326:case 0x4336:
case 0x4346:case 0x4356:case 0x4366:case 0x4376:
cpu->mmio_w43x6(value, (addr >> 4) & 7);
return;
//DASBx
case 0x4307:case 0x4317:case 0x4327:case 0x4337:
case 0x4347:case 0x4357:case 0x4367:case 0x4377:
cpu->mmio_w43x7(value, (addr >> 4) & 7);
return;
}
}
bCPUMMIO::bCPUMMIO(bCPU *_cpu) {
cpu = _cpu;
}
uint16 bDMA::dma_cputommio(uint8 i, uint8 index) {
uint8 x;
x = mem_bus->read(channel[i].srcaddr);
mem_bus->write(0x2100 | ((channel[i].destaddr + index) & 0xff), x);
if(channel[i].fixedxfer == false) {
channel[i].srcaddr = (channel[i].srcaddr & 0xff0000) + ((channel[i].srcaddr + channel[i].incmode) & 0xffff);
}
clock->add_cc1_cycles(8);
return --channel[i].xfersize;
}
uint16 bDMA::dma_mmiotocpu(uint8 i, uint8 index) {
uint8 x;
x = mem_bus->read(0x2100 | ((channel[i].destaddr + index) & 0xff));
mem_bus->write(channel[i].srcaddr, x);
if(channel[i].fixedxfer == false) {
channel[i].srcaddr = (channel[i].srcaddr & 0xff0000) + ((channel[i].srcaddr + channel[i].incmode) & 0xffff);
}
clock->add_cc1_cycles(8);
return --channel[i].xfersize;
}
void bDMA::dma_xfer_type0(uint8 i) {
if(channel[i].direction == 0) {
if(dma_cputommio(i, 0) == 0)return;
} else {
if(dma_mmiotocpu(i, 0) == 0)return;
}
}
void bDMA::dma_xfer_type1(uint8 i) {
if(channel[i].direction == 0) {
if(dma_cputommio(i, 0) == 0)return;
if(dma_cputommio(i, 1) == 0)return;
} else {
if(dma_mmiotocpu(i, 0) == 0)return;
if(dma_mmiotocpu(i, 1) == 0)return;
}
}
void bDMA::dma_xfer_type2(uint8 i) {
if(channel[i].direction == 0) {
if(dma_cputommio(i, 0) == 0)return;
if(dma_cputommio(i, 0) == 0)return;
} else {
if(dma_mmiotocpu(i, 0) == 0)return;
if(dma_mmiotocpu(i, 0) == 0)return;
}
}
void bDMA::dma_xfer_type3(uint8 i) {
if(channel[i].direction == 0) {
if(dma_cputommio(i, 0) == 0)return;
if(dma_cputommio(i, 0) == 0)return;
if(dma_cputommio(i, 1) == 0)return;
if(dma_cputommio(i, 1) == 0)return;
} else {
if(dma_mmiotocpu(i, 0) == 0)return;
if(dma_mmiotocpu(i, 0) == 0)return;
if(dma_mmiotocpu(i, 1) == 0)return;
if(dma_mmiotocpu(i, 1) == 0)return;
}
}
void bDMA::dma_xfer_type4(uint8 i) {
if(channel[i].direction == 0) {
if(dma_cputommio(i, 0) == 0)return;
if(dma_cputommio(i, 1) == 0)return;
if(dma_cputommio(i, 2) == 0)return;
if(dma_cputommio(i, 3) == 0)return;
} else {
if(dma_mmiotocpu(i, 0) == 0)return;
if(dma_mmiotocpu(i, 1) == 0)return;
if(dma_mmiotocpu(i, 2) == 0)return;
if(dma_mmiotocpu(i, 3) == 0)return;
}
}
void bDMA::dma_xfer_type5(uint8 i) {
if(channel[i].direction == 0) {
if(dma_cputommio(i, 0) == 0)return;
if(dma_cputommio(i, 1) == 0)return;
if(dma_cputommio(i, 0) == 0)return;
if(dma_cputommio(i, 1) == 0)return;
} else {
if(dma_mmiotocpu(i, 0) == 0)return;
if(dma_mmiotocpu(i, 1) == 0)return;
if(dma_mmiotocpu(i, 0) == 0)return;
if(dma_mmiotocpu(i, 1) == 0)return;
}
}
void bDMA::run() {
for(int i=0;i<8;i++) {
if(channel[i].active == false)continue;
switch(channel[i].xfermode) {
case 0:dma_xfer_type0(i);break;
case 1:dma_xfer_type1(i);break;
case 2:dma_xfer_type2(i);break;
case 3:dma_xfer_type3(i);break;
case 4:dma_xfer_type4(i);break;
case 5:dma_xfer_type5(i);break;
case 6:dma_xfer_type2(i);break;
case 7:dma_xfer_type3(i);break;
}
if(channel[i].xfersize == 0) {
channel[i].active = false;
}
return;
}
cpu->cpustate = bCPU::CPUSTATE_RUN;
}
void bDMA::hdma_write(uint8 i, uint8 l, uint8 x) {
switch(channel[i].xfermode) {
case 0:mem_bus->write(0x2100 | ((channel[i].destaddr) & 0xff), x);break;
case 1:mem_bus->write(0x2100 | ((channel[i].destaddr + l) & 0xff), x);break;
case 2:mem_bus->write(0x2100 | ((channel[i].destaddr) & 0xff), x);break;
case 3:mem_bus->write(0x2100 | ((channel[i].destaddr + (l >> 1)) & 0xff), x);break;
case 4:mem_bus->write(0x2100 | ((channel[i].destaddr + l) & 0xff), x);break;
case 5:mem_bus->write(0x2100 | ((channel[i].destaddr + (l & 1)) & 0xff), x);break;
case 6:mem_bus->write(0x2100 | ((channel[i].destaddr) & 0xff), x);break;
case 7:mem_bus->write(0x2100 | ((channel[i].destaddr + (l >> 1)) & 0xff), x);break;
}
}
void bDMA::hdma_run() {
int l, xferlen;
uint8 x, active_channels = 0;
for(int i=0;i<8;i++) {
if(channel[i].hdma_completed == true)continue;
clock->add_cc1_cycles(8);
active_channels++;
if(channel[i].hdma_line_counter == 0) {
channel[i].hdma_line_counter = mem_bus->read(channel[i].hdma_address++);
// channel[i].r43x8 = channel[i].hdma_address;
if(channel[i].hdma_line_counter == 0) {
channel[i].hdma_completed = true;
continue;
}
if(channel[i].hdma_line_counter > 0x80) {
channel[i].hdma_repeat = true;
channel[i].hdma_line_counter -= 0x80;
} else {
channel[i].hdma_repeat = false;
}
channel[i].hdma_first_line = true;
if(channel[i].hdma_indirect == false) {
channel[i].hdma_iaddress = channel[i].hdma_address;
} else {
channel[i].hdma_iaddress = mem_bus->read(channel[i].hdma_address);
channel[i].hdma_iaddress |= mem_bus->read(channel[i].hdma_address + 1) << 8;
channel[i].hdma_iaddress |= channel[i].hdma_indirect_bank << 16;
channel[i].hdma_address += 2;
clock->add_cc1_cycles(16);
}
}
channel[i].hdma_line_counter--;
if(channel[i].hdma_first_line == false && channel[i].hdma_repeat == false)continue;
channel[i].hdma_first_line = false;
if(channel[i].hdma_indirect == false) {
channel[i].hdma_iaddress = channel[i].hdma_address;
}
switch(channel[i].xfermode) {
case 0: xferlen = 1;break;
case 1:case 2:case 6: xferlen = 2;break;
case 3:case 4:case 5:case 7:xferlen = 4;break;
}
for(l=0;l<xferlen;l++) {
x = mem_bus->read(channel[i].hdma_iaddress++);
if(channel[i].hdma_indirect == false) {
channel[i].hdma_address++;
}
hdma_write(i, l, x);
clock->add_cc1_cycles(8);
}
}
if(active_channels != 0) {
clock->add_cc1_cycles(18);
}
}
void bDMA::hdma_initialize() {
uint8 active_channels = 0;
for(int i=0;i<8;i++) {
if(channel[i].hdma_active == false) {
channel[i].hdma_completed = true;
continue;
}
active_channels++;
channel[i].hdma_first_line = true;
channel[i].hdma_repeat = false;
channel[i].hdma_line_counter = 0;
channel[i].hdma_address = channel[i].srcaddr;
channel[i].hdma_completed = false;
if(channel[i].hdma_indirect == false) {
clock->add_cc1_cycles(8);
} else {
clock->add_cc1_cycles(24);
}
}
if(active_channels != 0) {
clock->add_cc1_cycles(18);
}
}
void bDMA::reset() {
for(int i=0;i<8;i++) {
channel[i].active = false;
channel[i].hdma_active = false;
channel[i].direction = 0;
channel[i].hdma_indirect = false;
channel[i].incmode = 1;
channel[i].fixedxfer = false;
channel[i].xfermode = 0;
channel[i].destaddr = 0;
channel[i].srcaddr = 0;
channel[i].xfersize = 0;
channel[i].hdma_indirect_bank = 0;
channel[i].hdma_first_line = false;
channel[i].hdma_repeat = false;
channel[i].hdma_line_counter = 0;
channel[i].hdma_address = 0;
channel[i].hdma_iaddress = 0;
channel[i].hdma_completed = true;
}
}
bDMA::bDMA(bCPU *_cpu) {
cpu = _cpu;
reset();
}

256
src/cpu/bcpu/bcpu_op.h Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

File diff suppressed because it is too large Load Diff

1110
src/cpu/bcpu/bcpu_op_rmw.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

295
src/cpu/bcpu/bcpu_opfn.cpp Normal file
View File

@@ -0,0 +1,295 @@
//op_read
inline void bCPU::op_adc_b() {
int32 r = regs.a.l + rd.l + regs.p.c;
//bcd
if(regs.p.d) {
if(((r ) & 15) > 9)r += 6;
if(((r >> 4) & 15) > 9)r += 6 << 4;
}
regs.p.n = !!(r & 0x80);
regs.p.v = !!(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
regs.p.z = ((uint8)r == 0);
regs.p.c = (r > 0xff);
regs.a.l = r;
}
inline void bCPU::op_adc_w() {
int32 r = regs.a.w + rd.w + regs.p.c;
//bcd
if(regs.p.d) {
if(((r ) & 15) > 9)r += 6;
if(((r >> 4) & 15) > 9)r += 6 << 4;
if(((r >> 8) & 15) > 9)r += 6 << 8;
if(((r >> 12) & 15) > 9)r += 6 << 12;
}
regs.p.n = !!(r & 0x8000);
regs.p.v = !!(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.p.c = (r > 0xffff);
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 = regs.a.l - rd.l - !regs.p.c;
//bcd
if(regs.p.d) {
if(((r ) & 15) > 9)r -= 6;
if(((r >> 4) & 15) > 9)r -= 6 << 4;
}
regs.p.n = !!(r & 0x80);
regs.p.v = !!((regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
regs.p.z = ((byte)r == 0);
regs.p.c = (r >= 0);
regs.a.l = r;
}
inline void bCPU::op_sbc_w() {
int32 r = regs.a.w - rd.w - !regs.p.c;
//bcd
if(regs.p.d) {
if(((r ) & 15) > 9)r -= 6;
if(((r >> 4) & 15) > 9)r -= 6 << 4;
if(((r >> 8) & 15) > 9)r -= 6 << 8;
if(((r >> 12) & 15) > 9)r -= 6 << 12;
}
regs.p.n = !!(r & 0x8000);
regs.p.v = !!((regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
regs.p.z = ((word)r == 0);
regs.p.c = (r >= 0);
regs.a.w = r;
}
//op_rmw
inline void bCPU::op_inc_b() {
rd.l++;
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void bCPU::op_inc_w() {
rd.w++;
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void bCPU::op_dec_b() {
rd.l--;
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void bCPU::op_dec_w() {
rd.w--;
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void bCPU::op_asl_b() {
regs.p.c = !!(rd.l & 0x80);
rd.l <<= 1;
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void bCPU::op_asl_w() {
regs.p.c = !!(rd.w & 0x8000);
rd.w <<= 1;
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void bCPU::op_lsr_b() {
regs.p.c = rd.l & 1;
rd.l >>= 1;
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void bCPU::op_lsr_w() {
regs.p.c = rd.w & 1;
rd.w >>= 1;
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void bCPU::op_rol_b() {
uint16 c = regs.p.c;
regs.p.c = !!(rd.l & 0x80);
rd.l <<= 1;
rd.l |= c;
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void bCPU::op_rol_w() {
uint16 c = regs.p.c;
regs.p.c = !!(rd.w & 0x8000);
rd.w <<= 1;
rd.w |= c;
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void bCPU::op_ror_b() {
uint16 c = (regs.p.c)?0x80:0;
regs.p.c = rd.l & 1;
rd.l >>= 1;
rd.l |= c;
regs.p.n = !!(rd.l & 0x80);
regs.p.z = (rd.l == 0);
}
inline void bCPU::op_ror_w() {
uint16 c = (regs.p.c)?0x8000:0;
regs.p.c = rd.w & 1;
rd.w >>= 1;
rd.w |= c;
regs.p.n = !!(rd.w & 0x8000);
regs.p.z = (rd.w == 0);
}
inline void bCPU::op_trb_b() {
regs.p.z = ((rd.l & regs.a.l) == 0);
rd.l &= ~regs.a.l;
}
inline void bCPU::op_trb_w() {
regs.p.z = ((rd.w & regs.a.w) == 0);
rd.w &= ~regs.a.w;
}
inline void bCPU::op_tsb_b() {
regs.p.z = ((rd.l & regs.a.l) == 0);
rd.l |= regs.a.l;
}
inline void bCPU::op_tsb_w() {
regs.p.z = ((rd.w & regs.a.w) == 0);
rd.w |= regs.a.w;
}

View File

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

View File

@@ -0,0 +1,356 @@
/* 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::hcounter() { return get_hcounter(); }
uint16 bCPU::hcycles() { 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; }
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;
//positions that can never be latched
//region_scanlines() = 262/NTSC, 312/PAL
//PAL results are unverified on hardware
if(v == 240 && hc == 339 && interlace() == false && interlace_field() == 1)return false;
if(v == (region_scanlines() - 1) && hc == 339 && interlace() == false)return false;
if(v == region_scanlines() && interlace() == false)return false;
if(v == region_scanlines() && hc == 339)return false;
if(v > region_scanlines())return false;
if(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;
//positions that can never be latched
//region_scanlines() = 262/NTSC, 312/PAL
//PAL results are unverified on hardware
if(vpos == 240 && hpos == 339 && interlace() == false && interlace_field() == 1)goto _nolatch;
if(vpos == (region_scanlines() - 1) && hpos == 339 && interlace() == false)goto _nolatch;
if(vpos == region_scanlines() && interlace() == false)goto _nolatch;
if(vpos == region_scanlines() && hpos == 339)goto _nolatch;
if(vpos > region_scanlines())goto _nolatch;
if(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;
}
}
}
//all scanlines are 1364 cycles long, except scanline 240
//on non-interlace odd-frames, which is 1360 cycles long.
//[NTSC]
//interlace mode has 525 scanlines: 263 on the even frame,
//and 262 on the odd.
//non-interlace mode has 524 scanlines: 262 scanlines on
//both even and odd frames.
//[PAL] <PAL info is unverified on hardware>
//interlace mode has 625 scanlines: 313 on the even frame,
//and 312 on the odd.
//non-interlace mode has 624 scanlines: 312 scanlines on
//both even and odd frames.
//
//cycles per frame:
// 263 * 1364 = 358732
// 262 * 1364 = 357368
// 262 * 1364 - 4 = 357364
void bCPU::inc_vcounter() {
time.v++;
if(time.v >= time.frame_lines) {
time.v = 0;
time.interlace_field ^= 1;
if(time.interlace == true && time.interlace_field == 0) {
time.frame_lines = time.region_scanlines + 1;
} else {
time.frame_lines = time.region_scanlines;
}
}
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;
update_interrupts();
}
//all dots are 4 cycles long, except dots 323 and 327. dots 323 and 327
//are 6 cycles long. this holds true for all scanlines except scanline
//240 on non-interlace odd frames. the reason for this is because this
//scanline is only 1360 cycles long, instead of 1364 like all other
//scanlines.
//this makes the effective range of hscan_pos 0-339 at all times.
//dot 323 range = { 1292, 1294, 1296 }
//dot 327 range = { 1310, 1312, 1314 }
uint16 bCPU::get_hcounter() {
if(time.v == 240 && time.interlace == false && time.interlace_field == 1) {
return time.hc >> 2;
}
return (time.hc - ((time.hc > 1292) << 1) - ((time.hc > 1310) << 1)) >> 2;
}
uint32 bCPU::cycles_executed() {
uint32 r = status.cycles_executed;
status.cycles_executed = 0;
return r;
}
void bCPU::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;
inc_vcounter();
poll_interrupts(cycles);
if(time.v == 0) {
frame();
ppu->frame();
snes->frame();
}
scanline();
ppu->scanline();
snes->scanline();
time.line_rendered = false;
}
if(time.hdmainit_triggered == false) {
if(time.hc + cycles >= time.hdmainit_trigger_pos || time.v) {
time.hdmainit_triggered = true;
hdmainit_activate();
}
}
if(time.dram_refreshed == false) {
if(time.hc + cycles >= time.dram_refresh_pos) {
time.dram_refreshed = true;
status.cycles_executed += 40;
cycles = (time.hc + cycles) - time.dram_refresh_pos;
time.hc = time.dram_refresh_pos + 40;
if(cpu_version == 2) {
if(time.v != 240 || time.interlace != false || time.interlace_field != 1) {
if(time.dram_refresh_pos == 534) {
time.dram_refresh_pos = 538;
} else {
time.dram_refresh_pos = 534;
}
}
}
}
}
if(time.line_rendered == false) {
//rendering should start at H=18 (+256=274), but since the
//current PPU emulation renders the entire scanline at once,
//PPU register changes mid-scanline do not show up.
//therefore, wait a few dots before rendering the scanline
if(time.hc + cycles >= (48 * 4)) {
time.line_rendered = true;
ppu->render_scanline();
}
}
if(time.hdma_triggered == false) {
if(time.v <= (overscan() ? 239 : 224)) {
if(time.hc + cycles >= 1106) {
time.hdma_triggered = true;
hdma_activate();
}
}
}
time.hc += cycles;
}
void bCPU::time_reset() {
time.v = 0;
time.hc = 0;
//upon SNES reset, start at scanline 0 non-interlace
time.interlace = false;
time.interlace_field = false;
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 = 262;
break;
case PAL:
time.region_scanlines = 312;
break;
}
time.frame_lines = time.region_scanlines;
}

View File

@@ -0,0 +1,73 @@
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 hcycles();
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 inc_vcounter();
inline uint16 get_hcounter();
inline void add_cycles(int cycles);
inline void time_reset();

174
src/cpu/bcpu/bcpugen.cpp Normal file
View File

@@ -0,0 +1,174 @@
#include "../../lib/libbase.h"
#include "../../lib/libstring.h"
#include "../../lib/libstring.cpp"
FILE *fp, *fph, *fpt;
string data, line, part, subpart;
string output_table, output_header, output_op;
int op_count;
struct _op_list {
string name;
string arg;
}op_list[64];
int line_num;
void clear_op_list() {
op_count = 0;
for(int i=0;i<64;i++) {
strcpy(op_list[i].name, "");
for(int l=0;l<8;l++) {
strcpy(op_list[i].arg[l], "");
}
}
}
void gen_header() {
int i = line_num, l, n, z;
char t[4096];
clear_op_list();
while(1) {
z = op_count++;
strcpy(part, line[i]);
strrtrim(part, "),");
strrtrim(part, ") {");
split(subpart, "(", part);
strcpy(op_list[z].name, subpart[0]);
split(part, ", ", subpart[1]);
for(l=0;l<count(part);l++) {
strcpy(op_list[z].arg[l], part[l]);
}
if(!strend(line[i], " {"))break;
i++;
}
sprintf(output_op, "void bCPU::op_$$() {\r\n switch(status.cycle_pos++) {\r\n");
sprintf(output_header, "void op_$$();\r\n");
sprintf(output_table, "optbl[$0] = &bCPU::op_$$;\r\n");
line_num = i + 1;
}
void update_line(int i, int n) {
char t[4096];
replace(line[i], "end;", "status.cycle_pos = 0;");
replace(line[i], "skip;", "status.cycle_pos++;");
}
void gen_op() {
int i = line_num, n, c;
char t[4096];
while(1) {
if(!strcmp(line[i], "}"))break;
n = strdec(line[i]);
sprintf(t, "%d:", n);
strltrim(line[i], t);
sprintf(t, " case %d:\r\n", n);
strcat(output_op, t);
update_line(i, n);
if(strcmp(line[i], "")) {
strcat(output_op, " ");
strcat(output_op, line[i]);
strcat(output_op, "\r\n");
}
i++;
while(1) {
if((strptr(line[i])[1]) == ':' || !strcmp(line[i], "}"))break;
update_line(i, n);
strcat(output_op, " ");
strcat(output_op, line[i]);
strcat(output_op, "\r\n");
i++;
}
if(!strcmp(line[i], "}")) {
strcat(output_op, " status.cycle_pos = 0;\r\n");
}
strcat(output_op, " break;\r\n");
}
strcat(output_op, " }\r\n}");
line_num = i + 1;
}
void gen_final() {
string t;
int i, l;
for(i=0;i<op_count;i++) {
strcpy(t, output_op);
replace(t, "$$", op_list[i].name);
replace(t, "$0", op_list[i].arg[0]);
replace(t, "$1", op_list[i].arg[1]);
replace(t, "$2", op_list[i].arg[2]);
replace(t, "$3", op_list[i].arg[3]);
replace(t, "$4", op_list[i].arg[4]);
replace(t, "$5", op_list[i].arg[5]);
replace(t, "$6", op_list[i].arg[6]);
replace(t, "$7", op_list[i].arg[7]);
fprintf(fp, "%s\r\n\r\n", strptr(t));
strcpy(t, output_header);
replace(t, "$$", op_list[i].name);
fprintf(fph, "%s", strptr(t));
strcpy(t, output_table);
replace(t, "$$", op_list[i].name);
replace(t, "$0", op_list[i].arg[0]);
fprintf(fpt, "%s", strptr(t));
}
}
void generate(char *dest, char *src) {
fp = fopen(src, "rb");
fseek(fp, 0, SEEK_END);
int fsize = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *buf = (char*)malloc(fsize + 1);
fread(buf, 1, fsize, fp);
fclose(fp);
buf[fsize] = 0;
strcpy(data, buf);
free(buf);
replace(data, "\r\n", "\n");
split(line, "\n", data);
fp = fopen(dest, "wb");
line_num = 0;
while(line_num < count(line)) {
while(!strcmp(line[line_num], "") && line_num < count(line))line_num++;
if(line_num >= count(line))break;
gen_header();
gen_op();
gen_final();
}
fclose(fp);
}
int main() {
fph = fopen("bcpu_op.h", "wb");
fpt = fopen("bcpu_optable.cpp", "wb");
generate("bcpu_op_read.cpp", "op_read.b");
generate("bcpu_op_rmw.cpp", "op_rmw.b");
generate("bcpu_op_write.cpp", "op_write.b");
generate("bcpu_op_pc.cpp", "op_pc.b");
generate("bcpu_op_misc.cpp", "op_misc.b");
fclose(fph);
fclose(fpt);
return 0;
}

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

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

8
src/cpu/bcpu/clean.bat Normal file
View File

@@ -0,0 +1,8 @@
@del *.exe
@del bcpu_op_misc.cpp
@del bcpu_op_pc.cpp
@del bcpu_op_read.cpp
@del bcpu_op_rmw.cpp
@del bcpu_op_write.cpp
@del bcpu_optable.cpp
@del bcpu_op.h

280
src/cpu/bcpu/op_misc.b Normal file
View File

@@ -0,0 +1,280 @@
nop(0xea) {
1:last_cycle();
cpu_io();
}
wdm(0x42) {
1:last_cycle();
op_read();
}
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_read();
2:sp = op_read();
3:regs.db = dp;
rd.l = op_read(OPMODE_LONG, (sp << 16) | regs.x.w);
4:op_write(OPMODE_LONG, (dp << 16) | regs.y.w, rd.l);
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_read();
if(regs.e)skip;
2:stack_write(regs.pc.b);
3:stack_write(regs.pc.h);
4:stack_write(regs.pc.l);
5:stack_write(regs.p);
6:rd.l = op_read(OPMODE_LONG, (regs.e)?$1:$3);
7:last_cycle();
rd.h = op_read(OPMODE_LONG, (regs.e)?$2:$4);
regs.pc.b = 0x00;
regs.pc.w = rd.w;
regs.p.i = 1;
regs.p.d = 0;
}
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();
if(run_state.wai) {
//this can be cleared within last_cycle()
regs.pc.w--;
}
}
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_read();
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;
regs.p.n = !!(regs.s.l & 0x80);
regs.p.z = (regs.s.l == 0);
} else {
regs.s.w = regs.x.w;
regs.p.n = !!(regs.s.w & 0x8000);
regs.p.z = (regs.s.w == 0);
}
}
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:stack_write(regs.$2.h);
3:last_cycle();
stack_write(regs.$2.l);
}
phb(0x8b, regs.db),
phk(0x4b, regs.pc.b),
php(0x08, regs.p) {
1:cpu_io();
2:last_cycle();
stack_write($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 = stack_read();
if($1) {
regs.p.n = !!(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0);
end;
}
4:last_cycle();
regs.$2.h = stack_read();
regs.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 = stack_read();
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 = stack_read();
if(regs.e)regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
}
pea(0xf4) {
1:aa.l = op_read();
2:aa.h = op_read();
3:stack_write(aa.h);
4:last_cycle();
stack_write(aa.l);
}
pei(0xd4) {
1:dp = op_read();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
5:stack_write(aa.h);
6:last_cycle();
stack_write(aa.l);
}
per(0x62) {
1:aa.l = op_read();
2:aa.h = op_read();
3:cpu_io();
rd.w = regs.pc.d + (int16)aa.w;
4:stack_write(rd.h);
5:last_cycle();
stack_write(rd.l);
}

159
src/cpu/bcpu/op_pc.b Normal file
View File

@@ -0,0 +1,159 @@
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_read();
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_read();
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_read();
2:rd.h = op_read();
3:last_cycle();
cpu_io();
regs.pc.w = regs.pc.d + (int16)rd.w;
}
jmp_addr(0x4c) {
1:rd.l = op_read();
2:last_cycle();
rd.h = op_read();
regs.pc.w = rd.w;
}
jmp_long(0x5c) {
1:rd.l = op_read();
2:rd.h = op_read();
3:last_cycle();
rd.b = op_read();
regs.pc.d = rd.d & 0xffffff;
}
jmp_iaddr(0x6c) {
1:aa.l = op_read();
2:aa.h = op_read();
3:rd.l = op_read(OPMODE_ADDR, aa.w);
4:last_cycle();
rd.h = op_read(OPMODE_ADDR, aa.w + 1);
regs.pc.w = rd.w;
}
jmp_iaddrx(0x7c) {
1:aa.l = op_read();
2:aa.h = op_read();
3:cpu_io();
4:rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w);
5:last_cycle();
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
}
jmp_iladdr(0xdc) {
1:aa.l = op_read();
2:aa.h = op_read();
3:rd.l = op_read(OPMODE_ADDR, aa.w);
4:rd.h = op_read(OPMODE_ADDR, aa.w + 1);
5:last_cycle();
rd.b = op_read(OPMODE_ADDR, aa.w + 2);
regs.pc.d = rd.d & 0xffffff;
}
jsr_addr(0x20) {
1:aa.l = op_read();
2:aa.h = op_read();
3:cpu_io();
4:regs.pc.w--;
stack_write(regs.pc.h);
5:last_cycle();
stack_write(regs.pc.l);
regs.pc.w = aa.w;
}
jsr_long(0x22) {
1:aa.l = op_read();
2:aa.h = op_read();
3:stack_write(regs.pc.b);
4:cpu_io();
5:aa.b = op_read();
6:regs.pc.w--;
stack_write(regs.pc.h);
7:last_cycle();
stack_write(regs.pc.l);
regs.pc.d = aa.d & 0xffffff;
}
jsr_iaddrx(0xfc) {
1:aa.l = op_read();
2:stack_write(regs.pc.h);
3:stack_write(regs.pc.l);
4:aa.h = op_read();
5:cpu_io();
6:rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w);
7:last_cycle();
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
}
rti(0x40) {
1:cpu_io();
2:cpu_io();
3:regs.p = stack_read();
if(regs.e)regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
4:rd.l = stack_read();
5:rd.h = stack_read();
if(regs.e) {
regs.pc.w = rd.w;
end;
}
6:last_cycle();
rd.b = stack_read();
regs.pc.d = rd.d & 0xffffff;
}
rts(0x60) {
1:cpu_io();
2:cpu_io();
3:rd.l = stack_read();
4:rd.h = stack_read();
5:last_cycle();
cpu_io();
regs.pc.w = rd.w;
regs.pc.w++;
}
rtl(0x6b) {
1:cpu_io();
2:cpu_io();
3:rd.l = stack_read();
4:rd.h = stack_read();
5:last_cycle();
rd.b = stack_read();
regs.pc.d = rd.d & 0xffffff;
regs.pc.w++;
}

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

@@ -0,0 +1,317 @@
adc_const(0x69, adc, regs.p.m),
and_const(0x29, and, regs.p.m),
cmp_const(0xc9, cmp, regs.p.m),
cpx_const(0xe0, cpx, regs.p.x),
cpy_const(0xc0, cpy, regs.p.x),
eor_const(0x49, eor, regs.p.m),
lda_const(0xa9, lda, regs.p.m),
ldx_const(0xa2, ldx, regs.p.x),
ldy_const(0xa0, ldy, regs.p.x),
ora_const(0x09, ora, regs.p.m),
sbc_const(0xe9, sbc, regs.p.m) {
1:if($2)last_cycle();
rd.l = op_read();
if($2) { op_$1_b(); end; }
2:last_cycle();
rd.h = op_read();
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_read();
2:aa.h = op_read();
3:if($2)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w);
if($2) { op_$1_b(); end; }
4:last_cycle();
rd.h = op_read(OPMODE_DBR, 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_read();
2:aa.h = op_read();
3:cpu_c4(aa.w, aa.w + regs.x.w);
4:if($2)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w + regs.x.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_read(OPMODE_DBR, 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_read();
2:aa.h = op_read();
3:cpu_c4(aa.w, aa.w + regs.y.w);
4:if($2)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_read(OPMODE_DBR, 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_read();
2:aa.h = op_read();
3:aa.b = op_read();
4:if($2)last_cycle();
rd.l = op_read(OPMODE_LONG, aa.d);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_read(OPMODE_LONG, 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_read();
2:aa.h = op_read();
3:aa.b = op_read();
4:if($2)last_cycle();
rd.l = op_read(OPMODE_LONG, aa.d + regs.x.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_read(OPMODE_LONG, aa.d + regs.x.w + 1);
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_read();
2:cpu_c2();
3:if($2)last_cycle();
rd.l = op_read(OPMODE_DP, dp);
if($2) { op_$1_b(); end; }
4:last_cycle();
rd.h = op_read(OPMODE_DP, 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_read();
2:cpu_c2();
3:cpu_io();
4:if($2)last_cycle();
rd.l = op_read(OPMODE_DP, dp + regs.x.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
op_$1_w();
}
ldx_dpy(0xb6, ldx, regs.p.x) {
1:dp = op_read();
2:cpu_c2();
3:cpu_io();
4:if($2)last_cycle();
rd.l = op_read(OPMODE_DP, dp + regs.y.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_read(OPMODE_DP, 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_read();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
5:if($2)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w);
if($2) { op_$1_b(); end; }
6:last_cycle();
rd.h = op_read(OPMODE_DBR, 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_read();
2:cpu_c2();
3:cpu_io();
4:aa.l = op_read(OPMODE_DP, dp + regs.x.w);
5:aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
6:if($2)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_read(OPMODE_DBR, 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_read();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
5:cpu_c4(aa.w, aa.w + regs.y.w);
6:if($2)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1);
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_read();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
5:aa.b = op_read(OPMODE_DP, dp + 2);
6:if($2)last_cycle();
rd.l = op_read(OPMODE_LONG, aa.d);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_read(OPMODE_LONG, 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_read();
2:cpu_c2();
3:aa.l = op_read(OPMODE_DP, dp);
4:aa.h = op_read(OPMODE_DP, dp + 1);
5:aa.b = op_read(OPMODE_DP, dp + 2);
6:if($2)last_cycle();
rd.l = op_read(OPMODE_LONG, aa.d + regs.y.w);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_read(OPMODE_LONG, aa.d + regs.y.w + 1);
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_read();
2:cpu_io();
3:if($2)last_cycle();
rd.l = op_read(OPMODE_SP, sp);
if($2) { op_$1_b(); end; }
4:last_cycle();
rd.h = op_read(OPMODE_SP, 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_read();
2:cpu_io();
3:aa.l = op_read(OPMODE_SP, sp);
4:aa.h = op_read(OPMODE_SP, sp + 1);
5:cpu_io();
6:if(regs.p.m)last_cycle();
rd.l = op_read(OPMODE_DBR, aa.w + regs.y.w);
if(regs.p.m) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1);
op_$1_w();
}
bit_const(0x89) {
1:if(regs.p.m)last_cycle();
rd.l = op_read();
if(regs.p.m) {
regs.p.z = ((rd.l & regs.a.l) == 0);
end;
}
2:last_cycle();
rd.h = op_read();
regs.p.z = ((rd.w & regs.a.w) == 0);
}

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

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

181
src/cpu/bcpu/op_write.b Normal file
View File

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

View File

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

View File

@@ -2,43 +2,67 @@
class CPU {
public:
//CPU version number
//* 1 and 2 are known
//* reported by $4210
//* affects DRAM refresh behavior
uint8 cpu_version;
//timing
virtual uint16 vcounter() = 0;
virtual uint16 hcounter() = 0;
virtual uint16 hcycles() = 0;
virtual bool interlace() = 0;
virtual bool interlace_field() = 0;
virtual bool overscan() = 0;
virtual uint16 region_scanlines() = 0;
virtual void set_interlace(bool r) = 0;
virtual void set_overscan (bool r) = 0;
MMIO *mmio;
CPURegs regs;
virtual uint8 port_read (uint8 port) = 0;
virtual void port_write(uint8 port, uint8 value) = 0;
enum {
FLAG_N = 0x80, FLAG_V = 0x40,
FLAG_M = 0x20, FLAG_X = 0x10,
FLAG_D = 0x08, FLAG_I = 0x04,
FLAG_Z = 0x02, FLAG_C = 0x01
};
virtual uint8 pio_status() = 0;
virtual void run() = 0;
virtual void scanline() = 0;
virtual void frame() = 0;
virtual void power() = 0;
virtual void reset() = 0;
virtual uint8 pio_status() = 0;
virtual void run() = 0;
virtual uint32 cycles_executed() = 0;
virtual void scanline() = 0;
virtual void frame() = 0;
virtual void power() = 0;
virtual void reset() = 0;
//opcode disassembler
enum {
OPTYPE_DP = 0, //dp
OPTYPE_DPX, //dp,x
OPTYPE_DPY, //dp,y
OPTYPE_IDP, //(dp)
OPTYPE_IDPX, //(dp,x)
OPTYPE_IDPY, //(dp),y
OPTYPE_ILDP, //[dp]
OPTYPE_ILDPY, //[dp],y
OPTYPE_ADDR, //addr
OPTYPE_ADDRX, //addr,x
OPTYPE_ADDRY, //addr,y
OPTYPE_IADDRX, //(addr,x)
OPTYPE_ILADDR, //[addr]
OPTYPE_LONG, //long
OPTYPE_LONGX, //long, x
OPTYPE_SR, //sr,s
OPTYPE_ISRY, //(sr,s),y
OPTYPE_ADDR_PC, //pbr:addr
OPTYPE_IADDR_PC //pbr:(addr)
};
enum {
OPTYPE_DP = 0, //dp
OPTYPE_DPX, //dp,x
OPTYPE_DPY, //dp,y
OPTYPE_IDP, //(dp)
OPTYPE_IDPX, //(dp,x)
OPTYPE_IDPY, //(dp),y
OPTYPE_ILDP, //[dp]
OPTYPE_ILDPY, //[dp],y
OPTYPE_ADDR, //addr
OPTYPE_ADDRX, //addr,x
OPTYPE_ADDRY, //addr,y
OPTYPE_IADDRX, //(addr,x)
OPTYPE_ILADDR, //[addr]
OPTYPE_LONG, //long
OPTYPE_LONGX, //long, x
OPTYPE_SR, //sr,s
OPTYPE_ISRY, //(sr,s),y
OPTYPE_ADDR_PC, //pbr:addr
OPTYPE_IADDR_PC //pbr:(addr)
};
//see dcpu.cpp for notes on this function
virtual bool in_opcode();
void disassemble_opcode(char *output);
uint32 resolve_offset(uint8 offset_type, uint32 addr);
uint8 opcode_length();

View File

@@ -2,40 +2,47 @@ class CPURegFlags {
private:
template <uint8 B> class bit {
public:
uint8 b;
inline operator bool() { return (b & B); }
inline operator = (bool i) { (i) ? b |= B : b &= ~B; return (b & B); }
inline operator & (bool i) { if(i)b &= ~B; return (b & B); }
inline operator | (bool i) { if(i)b |= B; return (b & B); }
inline operator ^ (bool i) { if(i)b ^= B; return (b & B); }
uint8 _b;
inline operator bool() { return (_b & B); }
inline bool operator = (bool i) { (i) ? _b |= B : _b &= ~B; return (_b & B); }
inline bool operator & (bool i) { if(i)_b &= ~B; return (_b & B); }
inline bool operator &= (bool i) { if(i)_b &= ~B; return (_b & B); }
inline bool operator | (bool i) { if(i)_b |= B; return (_b & B); }
inline bool operator |= (bool i) { if(i)_b |= B; return (_b & B); }
inline bool operator ^ (bool i) { if(i)_b ^= B; return (_b & B); }
inline bool operator ^= (bool i) { if(i)_b ^= B; return (_b & B); }
};
public:
union {
uint8 b;
union {
uint8 _b;
bit<0x80> n;
bit<0x40> v;
bit<0x20> m;
bit<0x10> x;
bit<0x20> m, p;
bit<0x10> x, b;
bit<0x08> d;
bit<0x04> i;
bit<0x02> z;
bit<0x01> c;
};
};
CPURegFlags() { b = 0; }
inline operator uint8() { return b; }
inline unsigned operator = (uint8 i) { b = i; return b; }
inline unsigned operator &= (uint8 i) { b &= i; return b; }
inline unsigned operator |= (uint8 i) { b |= i; return b; }
inline unsigned operator ^= (uint8 i) { b ^= i; return b; }
CPURegFlags() { _b = 0; }
inline operator uint8() { return _b; }
inline unsigned operator = (uint8 i) { _b = i; return _b; }
inline unsigned operator &= (uint8 i) { _b &= i; return _b; }
inline unsigned operator |= (uint8 i) { _b |= i; return _b; }
inline unsigned operator ^= (uint8 i) { _b ^= i; return _b; }
};
class CPUReg16 {
public:
union {
union {
uint16 w;
#ifdef ARCH_LSB
struct { uint8 l, h; };
};
#else
struct { uint8 h, l; };
#endif;
};
CPUReg16() { w = 0; }
inline operator uint16() { return w; }
@@ -53,11 +60,16 @@ public:
class CPUReg24 {
public:
union {
uint16 w;
union {
uint32 d;
struct { uint8 l, h, b; };
};
#ifdef ARCH_LSB
struct { uint16 w, null_w; };
struct { uint8 l, h, b, null_b; };
#else
struct { uint16 null_w, w; };
struct { uint8 null_b, b, h, l; };
#endif
};
CPUReg24() { d = 0; }
inline operator uint32() { return (d & 0xffffff); }
@@ -79,6 +91,7 @@ CPUReg24 pc;
CPUReg16 a, x, y, s, d;
CPURegFlags p;
uint8 db;
uint8 mdr; //memory data register (openbus)
bool e;
CPURegs() { db = 0; e = false; }
CPURegs() { db = 0; mdr = 0x00; e = false; }
};

View File

@@ -1,3 +1,17 @@
//this is a virtual function.
//in opcode-based CPU emulators, the main emulation routine
//will only be able to call the disassemble_opcode() function
//on clean opcode edges. but with cycle-based CPU emulators,
//the CPU may be in the middle of executing an opcode when the
//emulator (e.g. debugger) wants to disassemble an opcode. this
//would mean that important registers may not reflect what they
//did at the start of the opcode (especially regs.pc), so in
//cycle-based emulators, this function should be overridden to
//reflect whether or not an opcode has only been partially
//executed. if not, the debugger should abort attempts to skip,
//disable, or disassemble the current opcode.
bool CPU::in_opcode() { return false; }
uint16 CPU::__relb(int8 offset) {
uint32 addr;
addr = (regs.pc.d & 0xff0000) | ((regs.pc.d + 2) & 0xffff);
@@ -81,16 +95,24 @@ uint32 r = 0;
}
void CPU::disassemble_opcode(char *output) {
char *s = output;
char *s;
char t[256];
uint8 op, op0, op1, op2;
sprintf(s, "%0.6x ", regs.pc.d);
static CPUReg24 pc;
s = output;
//TODO: This should wrap around the bank byte
op = mem_bus->read(regs.pc.d);
op0 = mem_bus->read(regs.pc.d + 1);
op1 = mem_bus->read(regs.pc.d + 2);
op2 = mem_bus->read(regs.pc.d + 3);
if(in_opcode() == true) {
strcpy(s, "?????? <CPU within opcode>");
return;
}
pc.d = regs.pc.d;
sprintf(s, "%0.6x ", pc.d);
op = mem_bus->read(pc.d); pc.w++;
op0 = mem_bus->read(pc.d); pc.w++;
op1 = mem_bus->read(pc.d); pc.w++;
op2 = mem_bus->read(pc.d);
switch(op) {
case 0x00:sprintf(t, "brk #$%0.2x ", op0);break;
@@ -378,7 +400,7 @@ uint8 op, op0, op1, op2;
strcat(s, " ");
sprintf(t, "A:%0.4x X:%0.4x Y:%0.4x S:%0.4x D:%0.4x DB:%0.2x ",
regs.a.w, regs.x.w, regs.y.w, regs.s.w, regs.d, regs.db);
regs.a.w, regs.x.w, regs.y.w, regs.s.w, regs.d.w, regs.db);
strcat(s, t);
if(regs.e) {
sprintf(t, "%c%c%c%c%c%c%c%c",
@@ -431,6 +453,10 @@ static uint8 op_len_tbl[256] = {
6,2,2,2, 2,2,2,2, 1,5,1,1, 3,3,3,4, //0xen
2,2,2,2, 3,2,2,2, 1,3,1,1, 3,3,3,4 //0xfn
};
if(in_opcode() == true) {
return 0;
}
op = mem_bus->read(regs.pc.d);
len = op_len_tbl[op];
if(len == 5)return (regs.p.m)?2:3;

586
src/dsp/bdsp/bdsp.cpp Normal file
View File

@@ -0,0 +1,586 @@
#include "../../base.h"
#include "bdsp_tables.cpp"
uint8 bDSP::read_8 (uint16 addr) { return (spcram[addr]); }
uint16 bDSP::read_16 (uint16 addr) { return (spcram[(addr + 1) & 0xffff] << 8) + (spcram[addr]); }
void bDSP::write_8 (uint16 addr, uint8 data) { spcram[addr] = data; }
void bDSP::write_16(uint16 addr, uint16 data) { spcram[addr++] = data; spcram[addr] = data >> 8; }
uint8 bDSP::read(uint8 addr) {
int i, v, n;
addr &= 127;
v = addr >> 4;
n = addr & 15;
switch(addr) {
case 0x00:case 0x10:case 0x20:case 0x30:
case 0x40:case 0x50:case 0x60:case 0x70:
return voice[v].VOLL;
case 0x01:case 0x11:case 0x21:case 0x31:
case 0x41:case 0x51:case 0x61:case 0x71:
return voice[v].VOLR;
case 0x02:case 0x12:case 0x22:case 0x32:
case 0x42:case 0x52:case 0x62:case 0x72:
return voice[v].PITCH >> 8;
case 0x03:case 0x13:case 0x23:case 0x33:
case 0x43:case 0x53:case 0x63:case 0x73:
return voice[v].PITCH;
case 0x04:case 0x14:case 0x24:case 0x34:
case 0x44:case 0x54:case 0x64:case 0x74:
return voice[v].SRCN;
case 0x05:case 0x15:case 0x25:case 0x35:
case 0x45:case 0x55:case 0x65:case 0x75:
return voice[v].ADSR1;
case 0x06:case 0x16:case 0x26:case 0x36:
case 0x46:case 0x56:case 0x66:case 0x76:
return voice[v].ADSR2;
case 0x07:case 0x17:case 0x27:case 0x37:
case 0x47:case 0x57:case 0x67:case 0x77:
return voice[v].GAIN;
case 0x08:case 0x18:case 0x28:case 0x38:
case 0x48:case 0x58:case 0x68:case 0x78:
return voice[v].ENVX;
case 0x09:case 0x19:case 0x29:case 0x39:
case 0x49:case 0x59:case 0x69:case 0x79:
return voice[v].OUTX;
case 0x0f:case 0x1f:case 0x2f:case 0x3f:
case 0x4f:case 0x5f:case 0x6f:case 0x7f:
return status.FIR[v];
case 0x0c:return status.MVOLL;
case 0x1c:return status.MVOLR;
case 0x2c:return status.EVOLL;
case 0x3c:return status.EVOLR;
case 0x4c:return status.KON;
case 0x5c:return status.KOFF;
case 0x6c:return status.FLG;
case 0x7c:return status.ENDX;
case 0x0d:return status.EFB;
case 0x2d:return status.PMON;
case 0x3d:return status.NON;
case 0x4d:return status.EON;
case 0x5d:return status.DIR;
case 0x6d:return status.ESA;
case 0x7d:return status.EDL;
}
return dspram[addr];
}
void bDSP::write(uint8 addr, uint8 data) {
int i, v, n;
//0x80-0xff is a read-only mirror of 0x00-0x7f
if(addr & 0x80)return;
v = addr >> 4;
n = addr & 15;
switch(addr) {
case 0x00:case 0x10:case 0x20:case 0x30:
case 0x40:case 0x50:case 0x60:case 0x70:
voice[v].VOLL = data;
break;
case 0x01:case 0x11:case 0x21:case 0x31:
case 0x41:case 0x51:case 0x61:case 0x71:
voice[v].VOLR = data;
break;
case 0x02:case 0x12:case 0x22:case 0x32:
case 0x42:case 0x52:case 0x62:case 0x72:
voice[v].PITCH &= 0xff00;
voice[v].PITCH |= data;
break;
case 0x03:case 0x13:case 0x23:case 0x33:
case 0x43:case 0x53:case 0x63:case 0x73:
voice[v].PITCH &= 0x00ff;
voice[v].PITCH |= data << 8;
break;
case 0x04:case 0x14:case 0x24:case 0x34:
case 0x44:case 0x54:case 0x64:case 0x74:
//voice[v].SRCN = data;
//below is anomie's code, but TRAC says writing SRCN doesn't affect anything until a
//BRR-with-end block is encountered, where it loads the loop address from the new SRCN
if(voice[v].SRCN != data) {
voice[v].SRCN = data;
voice[v].brr_ptr = read_16((status.DIR << 8) + (voice[v].SRCN << 2) + ((voice[v].brr_looped)?2:0));
voice[v].brr_index = 0;
}
break;
case 0x05:case 0x15:case 0x25:case 0x35:
case 0x45:case 0x55:case 0x65:case 0x75:
voice[v].ADSR1 = data;
voice[v].AdjustEnvelope();
break;
case 0x06:case 0x16:case 0x26:case 0x36:
case 0x46:case 0x56:case 0x66:case 0x76:
voice[v].ADSR2 = data;
//sustain_level = 0-7, 7 is a special case handled by ATTACK envx mode
voice[v].env_sustain = (voice[v].ADSR_sus_level() + 1) << 8;
voice[v].AdjustEnvelope();
break;
case 0x07:case 0x17:case 0x27:case 0x37:
case 0x47:case 0x57:case 0x67:case 0x77:
voice[v].GAIN = data;
voice[v].AdjustEnvelope();
break;
case 0x08:case 0x18:case 0x28:case 0x38:
case 0x48:case 0x58:case 0x68:case 0x78:
voice[v].ENVX = data;
break;
case 0x09:case 0x19:case 0x29:case 0x39:
case 0x49:case 0x59:case 0x69:case 0x79:
voice[v].OUTX = data;
break;
case 0x0f:case 0x1f:case 0x2f:case 0x3f:
case 0x4f:case 0x5f:case 0x6f:case 0x7f:
status.FIR[v] = data;
break;
case 0x0c:status.MVOLL = data;break;
case 0x1c:status.MVOLR = data;break;
case 0x2c:status.EVOLL = data;break;
case 0x3c:status.EVOLR = data;break;
case 0x4c:
status.KON = data;
// status.kon = data;
status.key_flag = true;
break;
case 0x5c:
status.KOFF = data;
status.key_flag = true;
break;
case 0x6c:
status.FLG = data;
status.key_flag = true;
status.noise_rate = RateTable[data & 0x1f];
break;
case 0x7c:
//read-only register, writes clear all bits of ENDX
status.ENDX = 0;
break;
case 0x0d:status.EFB = data;break;
case 0x2d:status.PMON = data;break;
case 0x3d:status.NON = data;break;
case 0x4d:status.EON = data;break;
case 0x5d:status.DIR = data;break;
case 0x6d:status.ESA = data;break;
case 0x7d:
status.EDL = data;
status.echo_size = (data & 0x0f) << 11;
break;
}
dspram[addr] = data;
}
void bDSP::power() {
int v;
spcram = apu->get_spcram_handle();
memset(dspram, 0x00, 128);
for(v=0;v<8;v++) {
voice[v].VOLL = 0;
voice[v].VOLR = 0;
voice[v].PITCH = 0;
voice[v].SRCN = 0;
voice[v].ADSR1 = 0;
voice[v].ADSR2 = 0;
voice[v].GAIN = 0;
status.FIR[v] = 0;
}
status.MVOLL = status.MVOLR = 0;
status.EVOLL = status.EVOLR = 0;
status.ENDX = 0;
status.EFB = 0;
status.PMON = 0;
status.NON = 0;
status.EON = 0;
status.DIR = 0;
status.ESA = 0;
status.EDL = 0;
status.echo_size = 0;
status.echo_target = 0;
reset();
}
void bDSP::reset() {
int v;
status.KON = 0x00;
status.KOFF = 0x00;
status.FLG |= 0xe0;
//status.kon = 0x00;
status.key_flag = false;
status.noise_ctr = 0;
status.noise_rate = 0;
status.noise_sample = 0x4000;
status.echo_index = 0;
status.fir_buffer_index = 0;
for(v=0;v<8;v++) {
voice[v].ENVX = 0;
voice[v].OUTX = 0;
voice[v].pitch_ctr = 0;
voice[v].brr_index = 0;
voice[v].brr_ptr = read_16((status.DIR << 8) + (voice[v].SRCN << 2));
voice[v].brr_looped = false;
voice[v].brr_data[0] = 0;
voice[v].brr_data[1] = 0;
voice[v].brr_data[2] = 0;
voice[v].brr_data[3] = 0;
voice[v].brr_data_index = 0;
voice[v].envx = 0;
voice[v].env_ctr = 0;
voice[v].env_rate = 0;
voice[v].env_state = SILENCE;
voice[v].env_mode = DIRECT;
status.fir_buffer[0][v] = 0;
status.fir_buffer[1][v] = 0;
}
dsp_counter = 0;
}
int32 bDSP::clamp(int32 bits, int32 x) {
int32 b = 1 << (bits - 1);
if(x > (b - 1)) {
return (b - 1);
} else if(x < -b) {
return -b;
} else {
return x;
}
}
int32 bDSP::clip(int32 bits, int32 x) {
int32 b = 1 << (bits - 1);
if(x & b) {
return x | ~(b - 1);
} else {
return x & (b - 1);
}
}
uint32 bDSP::run() {
int v, d;
uint8 pmon;
int32 sample;
int32 msamplel, msampler;
int32 esamplel, esampler;
int32 fir_samplel, fir_sampler;
pmon = status.PMON & ~status.NON & ~1;
if(!(dsp_counter++ & 1) && status.key_flag) {
for(v=0;v<8;v++) {
uint8 mask = 1 << v;
if(status.soft_reset()) {
if(voice[v].env_state != SILENCE) {
voice[v].env_state = SILENCE;
voice[v].AdjustEnvelope();
}
} else if(status.KOFF & mask) {
if(voice[v].env_state != SILENCE && voice[v].env_state != RELEASE) {
voice[v].env_state = RELEASE;
voice[v].AdjustEnvelope();
}
} else if(status.KON & mask) { //status.kon
status.KON &= ~mask; //new code
status.ENDX &= ~mask; //new code
voice[v].brr_ptr = read_16((status.DIR << 8) + (voice[v].SRCN << 2));
voice[v].brr_index = -9;
voice[v].brr_looped = false;
voice[v].brr_data[0] = 0;
voice[v].brr_data[1] = 0;
voice[v].brr_data[2] = 0;
voice[v].brr_data[3] = 0;
voice[v].envx = 0;
voice[v].env_state = ATTACK;
voice[v].AdjustEnvelope();
}
}
// status.ENDX &= ~status.kon;
// status.kon = 0;
status.key_flag = false;
}
//update noise
status.noise_ctr += status.noise_rate;
if(status.noise_ctr >= 0x7800) {
status.noise_ctr -= 0x7800;
status.noise_sample = (status.noise_sample >> 1) |
(((status.noise_sample << 14) ^ (status.noise_sample << 13)) & 0x4000);
}
msamplel = msampler = 0;
esamplel = esampler = 0;
for(v=0;v<8;v++) {
if(voice[v].brr_index < -1) {
voice[v].brr_index++;
voice[v].OUTX = voice[v].outx = 0;
voice[v].ENVX = 0;
continue;
}
if(voice[v].brr_index >= 0) {
if(pmon & (1 << v)) {
voice[v].pitch_ctr += (voice[v].pitch_rate() * (voice[v - 1].outx + 0x8000)) >> 15;
} else {
voice[v].pitch_ctr += voice[v].pitch_rate();
}
} else {
voice[v].pitch_ctr = 0x3000;
voice[v].brr_index = 0;
}
//decode BRR samples
while(voice[v].pitch_ctr >= 0) {
voice[v].pitch_ctr -= 0x1000;
voice[v].brr_data_index++;
voice[v].brr_data_index &= 3;
if(voice[v].brr_index == 0) {
voice[v].brr_header = read_8(voice[v].brr_ptr);
if(voice[v].brr_header_flags() & BRR_END) {
status.ENDX |= (1 << v);
}
if(voice[v].brr_header_flags() == BRR_END) {
voice[v].env_state = SILENCE;
voice[v].AdjustEnvelope();
}
}
#define S(x) voice[v].brr_data[(voice[v].brr_data_index + (x)) & 3]
if(voice[v].env_state != SILENCE) {
sample = read_8(voice[v].brr_ptr + 1 + (voice[v].brr_index >> 1));
if(voice[v].brr_index & 1) {
sample = clip(4, sample);
} else {
sample = clip(4, sample >> 4);
}
if(voice[v].brr_header_shift() <= 12) {
sample = (sample << voice[v].brr_header_shift() >> 1);
} else {
sample &= ~0x7ff;
}
switch(voice[v].brr_header_filter()) {
case 0: //direct
break;
case 1: //15/16
sample += S(-1) + ((-S(-1)) >> 4);
break;
case 2: //61/32 - 15/16
sample += (S(-1) << 1) + ((-((S(-1) << 1) + S(-1))) >> 5)
- S(-2) + (S(-2) >> 4);
break;
case 3: //115/64 - 13/16
sample += (S(-1) << 1) + ((-(S(-1) + (S(-1) << 2) + (S(-1) << 3))) >> 6)
- S(-2) + (((S(-2) << 1) + S(-2)) >> 4);
break;
}
S(0) = sample = clip(15, clamp(16, sample));
} else {
S(0) = sample = 0;
}
if(++voice[v].brr_index > 15) {
voice[v].brr_index = 0;
if(voice[v].brr_header_flags() & BRR_END) {
voice[v].brr_ptr = read_16((status.DIR << 8) + (voice[v].SRCN << 2) + 2);
voice[v].brr_looped = true;
} else {
voice[v].brr_ptr += 9;
}
}
}
//volume envelope adjust
voice[v].env_ctr += voice[v].env_rate;
if(voice[v].env_ctr >= 0x7800) {
voice[v].env_ctr -= 0x7800;
switch(voice[v].env_mode) {
case DIRECT:
voice[v].env_rate = 0;
break;
case LINEAR_DEC:
voice[v].envx -= 32;
if(voice[v].envx <= 0) {
voice[v].envx = 0;
voice[v].env_rate = 0;
voice[v].env_mode = DIRECT;
}
break;
case LINEAR_INC:
voice[v].envx += 32;
if(voice[v].envx >= 0x7ff) {
voice[v].envx = 0x7ff;
voice[v].env_rate = 0;
voice[v].env_mode = DIRECT;
if(voice[v].ADSR_enabled() && voice[v].env_state == ATTACK) {
voice[v].env_state = ((voice[v].env_sustain == 0x800) ? SUSTAIN : DECAY);
voice[v].AdjustEnvelope();
}
}
break;
case EXP_DEC:
//multiply by 255/256ths
voice[v].envx -= ((voice[v].envx - 1) >> 8) + 1;
if(voice[v].ADSR_enabled() && voice[v].env_state == DECAY && voice[v].envx <= voice[v].env_sustain) {
voice[v].env_state = SUSTAIN;
voice[v].AdjustEnvelope();
} else if(voice[v].envx <= 0) {
voice[v].envx = 0;
voice[v].env_rate = 0;
voice[v].env_mode = DIRECT;
}
break;
case BENT_INC:
if(voice[v].envx < 0x600) {
voice[v].envx += 32;
} else {
voice[v].envx += 8;
if(voice[v].envx >= 0x7ff) {
voice[v].envx = 0x7ff;
voice[v].env_rate = 0;
voice[v].env_mode = DIRECT;
}
}
break;
case FAST_ATTACK:
voice[v].envx += 0x400;
if(voice[v].envx >= 0x7ff) {
voice[v].envx = 0x7ff;
//attack raises to max. envx, if sustain is also set to max. envx, skip decay phase
voice[v].env_state = ((voice[v].env_sustain == 0x800) ? SUSTAIN : DECAY);
voice[v].AdjustEnvelope();
}
break;
case RELEASE_DEC:
voice[v].envx -= 8;
if(voice[v].envx <= 0) {
voice[v].env_state = SILENCE;
voice[v].AdjustEnvelope();
}
break;
}
}
voice[v].ENVX = voice[v].envx >> 4;
//gaussian interpolation / noise
if(status.NON & (1 << v)) {
sample = status.noise_sample;
} else {
d = voice[v].pitch_ctr >> 4; //-256 <= sample <= -1
sample = ((GaussTable[ -1-d] * S(-3)) >> 11);
sample += ((GaussTable[255-d] * S(-2)) >> 11);
sample += ((GaussTable[512+d] * S(-1)) >> 11);
sample = clip (15, sample);
sample += ((GaussTable[256+d] * S( 0)) >> 11);
sample = clamp(15, sample);
}
#undef S
//envelope / volume adjust
sample = (sample * voice[v].envx) >> 11;
voice[v].outx = sample << 1;
voice[v].OUTX = sample >> 7;
if(!status.mute()) {
msamplel += ((sample * voice[v].VOLL) >> 7) << 1;
msampler += ((sample * voice[v].VOLR) >> 7) << 1;
}
if((status.EON & (1 << v)) && status.echo_write()) {
esamplel += ((sample * voice[v].VOLL) >> 7) << 1;
esampler += ((sample * voice[v].VOLR) >> 7) << 1;
}
}
//echo (FIR) adjust
#define F(c,x) status.fir_buffer[c][(status.fir_buffer_index+(x)) & 7]
status.fir_buffer_index++;
F(0,0) = read_16((status.ESA << 8) + status.echo_index);
F(1,0) = read_16((status.ESA << 8) + status.echo_index + 2);
fir_samplel = (F(0,-0) * status.FIR[7] +
F(0,-1) * status.FIR[6] +
F(0,-2) * status.FIR[5] +
F(0,-3) * status.FIR[4] +
F(0,-4) * status.FIR[3] +
F(0,-5) * status.FIR[2] +
F(0,-6) * status.FIR[1] +
F(0,-7) * status.FIR[0]);
fir_sampler = (F(1,-0) * status.FIR[7] +
F(1,-1) * status.FIR[6] +
F(1,-2) * status.FIR[5] +
F(1,-3) * status.FIR[4] +
F(1,-4) * status.FIR[3] +
F(1,-5) * status.FIR[2] +
F(1,-6) * status.FIR[1] +
F(1,-7) * status.FIR[0]);
#undef F
//update echo buffer
if(status.echo_write()) {
esamplel += (fir_samplel * status.EFB) >> 14;
esampler += (fir_sampler * status.EFB) >> 14;
esamplel = clamp(16, esamplel);
esampler = clamp(16, esampler);
write_16((status.ESA << 8) + status.echo_index, esamplel);
write_16((status.ESA << 8) + status.echo_index + 2, esampler);
}
status.echo_index += 4;
if(status.echo_index >= status.echo_target) {
status.echo_index = 0;
status.echo_target = status.echo_size;
}
//main output adjust
if(!status.mute()) {
msamplel = (msamplel * status.MVOLL) >> 7;
msampler = (msampler * status.MVOLR) >> 7;
msamplel += (fir_samplel * status.EVOLL) >> 14;
msampler += (fir_sampler * status.EVOLR) >> 14;
msamplel = clamp(16, msamplel);
msampler = clamp(16, msampler);
}
return (uint32)(((uint16)msamplel) | ((uint16)msampler << 16));
}
bDSP::bDSP() {}
bDSP::~bDSP() {}

176
src/dsp/bdsp/bdsp.h Normal file
View File

@@ -0,0 +1,176 @@
class bDSP : public DSP {
private:
uint8 dspram[128];
uint8 *spcram;
uint32 dsp_counter;
enum {
BRR_END = 1,
BRR_LOOP = 2
};
uint8 read_8 (uint16 addr);
uint16 read_16 (uint16 addr);
void write_8 (uint16 addr, uint8 data);
void write_16(uint16 addr, uint16 data);
public:
static const uint16 RateTable[32];
static const int16 GaussTable[512];
enum EnvelopeStates {
ATTACK,
DECAY,
SUSTAIN,
RELEASE,
SILENCE
};
enum EnvelopeModes {
DIRECT,
LINEAR_DEC,
EXP_DEC,
LINEAR_INC,
BENT_INC,
FAST_ATTACK,
RELEASE_DEC
};
private:
struct Status {
//$0c,$1c
int8 MVOLL, MVOLR;
//$2c,$3c
int8 EVOLL, EVOLR;
//$4c,$5c
uint8 KON, KOFF;
//$6c
uint8 FLG;
//$7c
uint8 ENDX;
//$0d
int8 EFB;
//$2d,$3d,$4d
uint8 PMON, NON, EON;
//$5d
uint8 DIR;
//$6d,$7d
uint8 ESA, EDL;
//$xf
int8 FIR[8];
//internal variables
//uint8 kon;
bool key_flag;
int16 noise_ctr, noise_rate;
uint16 noise_sample;
uint16 echo_index, echo_size, echo_target;
int16 fir_buffer[2][8];
uint8 fir_buffer_index;
//functions
bool soft_reset() { return !!(FLG & 0x80); }
bool mute() { return !!(FLG & 0x40); }
bool echo_write() { return !(FLG & 0x20); }
} status;
struct Voice {
//$x0-$x1
int8 VOLL, VOLR;
//$x2-$x3
int16 PITCH;
//$x4
uint8 SRCN;
//$x5-$x7
uint8 ADSR1, ADSR2, GAIN;
//$x8-$x9
uint8 ENVX, OUTX;
//internal variables
int16 pitch_ctr;
int8 brr_index;
uint16 brr_ptr;
uint8 brr_header;
bool brr_looped;
int16 brr_data[4];
uint8 brr_data_index;
int16 envx;
uint16 env_ctr, env_rate, env_sustain;
enum EnvelopeStates env_state;
enum EnvelopeModes env_mode;
int16 outx;
//functions
int16 pitch_rate() { return PITCH & 0x3fff; }
uint8 brr_header_shift() { return brr_header >> 4; }
uint8 brr_header_filter() { return (brr_header >> 2) & 3; }
uint8 brr_header_flags() { return brr_header & 3; }
bool ADSR_enabled() { return !!(ADSR1 & 0x80); }
uint8 ADSR_decay() { return (ADSR1 >> 4) & 7; }
uint8 ADSR_attack() { return ADSR1 & 15; }
uint8 ADSR_sus_level() { return ADSR2 >> 5; }
uint8 ADSR_sus_rate() { return ADSR2 & 31; }
void AdjustEnvelope() {
if(env_state == SILENCE) {
env_mode = DIRECT;
env_rate = 0;
envx = 0;
} else if(env_state == RELEASE) {
env_mode = RELEASE_DEC;
env_rate = 0x7800;
} else if(ADSR_enabled()) {
switch(env_state) {
case ATTACK:
env_rate = RateTable[(ADSR_attack() << 1) + 1];
env_mode = (env_rate == 0x7800) ? FAST_ATTACK : LINEAR_INC;
break;
case DECAY:
env_rate = RateTable[(ADSR_decay() << 1) + 0x10];
env_mode = EXP_DEC;
break;
case SUSTAIN:
env_rate = RateTable[ADSR_sus_rate()];
env_mode = (env_rate == 0) ? DIRECT : EXP_DEC;
break;
}
} else if(GAIN & 0x80) {
switch(GAIN & 0x60) {
case 0x00:env_mode = LINEAR_DEC; break;
case 0x20:env_mode = EXP_DEC; break;
case 0x40:env_mode = LINEAR_INC; break;
case 0x60:env_mode = BENT_INC; break;
}
env_rate = RateTable[GAIN & 0x1f];
} else {
env_mode = DIRECT;
env_rate = 0;
envx = (GAIN & 0x7f) << 4;
}
}
} voice[8];
int32 clamp(int32 bits, int32 x);
int32 clip (int32 bits, int32 x);
public:
uint8 read (uint8 addr);
void write(uint8 addr, uint8 data);
void power();
void reset();
uint32 run();
bDSP();
~bDSP();
};

View File

@@ -0,0 +1,73 @@
const uint16 bDSP::RateTable[32] = {
0x0000, 0x000F, 0x0014, 0x0018, 0x001E, 0x0028, 0x0030, 0x003C,
0x0050, 0x0060, 0x0078, 0x00A0, 0x00C0, 0x00F0, 0x0140, 0x0180,
0x01E0, 0x0280, 0x0300, 0x03C0, 0x0500, 0x0600, 0x0780, 0x0A00,
0x0C00, 0x0F00, 0x1400, 0x1800, 0x1E00, 0x2800, 0x3C00, 0x7800
};
const int16 bDSP::GaussTable[512] = {
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001,
0x001, 0x001, 0x001, 0x002, 0x002, 0x002, 0x002, 0x002,
0x002, 0x002, 0x003, 0x003, 0x003, 0x003, 0x003, 0x004,
0x004, 0x004, 0x004, 0x004, 0x005, 0x005, 0x005, 0x005,
0x006, 0x006, 0x006, 0x006, 0x007, 0x007, 0x007, 0x008,
0x008, 0x008, 0x009, 0x009, 0x009, 0x00A, 0x00A, 0x00A,
0x00B, 0x00B, 0x00B, 0x00C, 0x00C, 0x00D, 0x00D, 0x00E,
0x00E, 0x00F, 0x00F, 0x00F, 0x010, 0x010, 0x011, 0x011,
0x012, 0x013, 0x013, 0x014, 0x014, 0x015, 0x015, 0x016,
0x017, 0x017, 0x018, 0x018, 0x019, 0x01A, 0x01B, 0x01B,
0x01C, 0x01D, 0x01D, 0x01E, 0x01F, 0x020, 0x020, 0x021,
0x022, 0x023, 0x024, 0x024, 0x025, 0x026, 0x027, 0x028,
0x029, 0x02A, 0x02B, 0x02C, 0x02D, 0x02E, 0x02F, 0x030,
0x031, 0x032, 0x033, 0x034, 0x035, 0x036, 0x037, 0x038,
0x03A, 0x03B, 0x03C, 0x03D, 0x03E, 0x040, 0x041, 0x042,
0x043, 0x045, 0x046, 0x047, 0x049, 0x04A, 0x04C, 0x04D,
0x04E, 0x050, 0x051, 0x053, 0x054, 0x056, 0x057, 0x059,
0x05A, 0x05C, 0x05E, 0x05F, 0x061, 0x063, 0x064, 0x066,
0x068, 0x06A, 0x06B, 0x06D, 0x06F, 0x071, 0x073, 0x075,
0x076, 0x078, 0x07A, 0x07C, 0x07E, 0x080, 0x082, 0x084,
0x086, 0x089, 0x08B, 0x08D, 0x08F, 0x091, 0x093, 0x096,
0x098, 0x09A, 0x09C, 0x09F, 0x0A1, 0x0A3, 0x0A6, 0x0A8,
0x0AB, 0x0AD, 0x0AF, 0x0B2, 0x0B4, 0x0B7, 0x0BA, 0x0BC,
0x0BF, 0x0C1, 0x0C4, 0x0C7, 0x0C9, 0x0CC, 0x0CF, 0x0D2,
0x0D4, 0x0D7, 0x0DA, 0x0DD, 0x0E0, 0x0E3, 0x0E6, 0x0E9,
0x0EC, 0x0EF, 0x0F2, 0x0F5, 0x0F8, 0x0FB, 0x0FE, 0x101,
0x104, 0x107, 0x10B, 0x10E, 0x111, 0x114, 0x118, 0x11B,
0x11E, 0x122, 0x125, 0x129, 0x12C, 0x130, 0x133, 0x137,
0x13A, 0x13E, 0x141, 0x145, 0x148, 0x14C, 0x150, 0x153,
0x157, 0x15B, 0x15F, 0x162, 0x166, 0x16A, 0x16E, 0x172,
0x176, 0x17A, 0x17D, 0x181, 0x185, 0x189, 0x18D, 0x191,
0x195, 0x19A, 0x19E, 0x1A2, 0x1A6, 0x1AA, 0x1AE, 0x1B2,
0x1B7, 0x1BB, 0x1BF, 0x1C3, 0x1C8, 0x1CC, 0x1D0, 0x1D5,
0x1D9, 0x1DD, 0x1E2, 0x1E6, 0x1EB, 0x1EF, 0x1F3, 0x1F8,
0x1FC, 0x201, 0x205, 0x20A, 0x20F, 0x213, 0x218, 0x21C,
0x221, 0x226, 0x22A, 0x22F, 0x233, 0x238, 0x23D, 0x241,
0x246, 0x24B, 0x250, 0x254, 0x259, 0x25E, 0x263, 0x267,
0x26C, 0x271, 0x276, 0x27B, 0x280, 0x284, 0x289, 0x28E,
0x293, 0x298, 0x29D, 0x2A2, 0x2A6, 0x2AB, 0x2B0, 0x2B5,
0x2BA, 0x2BF, 0x2C4, 0x2C9, 0x2CE, 0x2D3, 0x2D8, 0x2DC,
0x2E1, 0x2E6, 0x2EB, 0x2F0, 0x2F5, 0x2FA, 0x2FF, 0x304,
0x309, 0x30E, 0x313, 0x318, 0x31D, 0x322, 0x326, 0x32B,
0x330, 0x335, 0x33A, 0x33F, 0x344, 0x349, 0x34E, 0x353,
0x357, 0x35C, 0x361, 0x366, 0x36B, 0x370, 0x374, 0x379,
0x37E, 0x383, 0x388, 0x38C, 0x391, 0x396, 0x39B, 0x39F,
0x3A4, 0x3A9, 0x3AD, 0x3B2, 0x3B7, 0x3BB, 0x3C0, 0x3C5,
0x3C9, 0x3CE, 0x3D2, 0x3D7, 0x3DC, 0x3E0, 0x3E5, 0x3E9,
0x3ED, 0x3F2, 0x3F6, 0x3FB, 0x3FF, 0x403, 0x408, 0x40C,
0x410, 0x415, 0x419, 0x41D, 0x421, 0x425, 0x42A, 0x42E,
0x432, 0x436, 0x43A, 0x43E, 0x442, 0x446, 0x44A, 0x44E,
0x452, 0x455, 0x459, 0x45D, 0x461, 0x465, 0x468, 0x46C,
0x470, 0x473, 0x477, 0x47A, 0x47E, 0x481, 0x485, 0x488,
0x48C, 0x48F, 0x492, 0x496, 0x499, 0x49C, 0x49F, 0x4A2,
0x4A6, 0x4A9, 0x4AC, 0x4AF, 0x4B2, 0x4B5, 0x4B7, 0x4BA,
0x4BD, 0x4C0, 0x4C3, 0x4C5, 0x4C8, 0x4CB, 0x4CD, 0x4D0,
0x4D2, 0x4D5, 0x4D7, 0x4D9, 0x4DC, 0x4DE, 0x4E0, 0x4E3,
0x4E5, 0x4E7, 0x4E9, 0x4EB, 0x4ED, 0x4EF, 0x4F1, 0x4F3,
0x4F5, 0x4F6, 0x4F8, 0x4FA, 0x4FB, 0x4FD, 0x4FF, 0x500,
0x502, 0x503, 0x504, 0x506, 0x507, 0x508, 0x50A, 0x50B,
0x50C, 0x50D, 0x50E, 0x50F, 0x510, 0x511, 0x511, 0x512,
0x513, 0x514, 0x514, 0x515, 0x516, 0x516, 0x517, 0x517,
0x517, 0x518, 0x518, 0x518, 0x518, 0x518, 0x519, 0x519
};

9
src/dsp/dsp.h Normal file
View File

@@ -0,0 +1,9 @@
class DSP {
public:
virtual uint8 read (uint8 addr) = 0;
virtual void write(uint8 addr, uint8 data) = 0;
virtual void power() = 0;
virtual void reset() = 0;
virtual uint32 run() = 0;
};

View File

@@ -1,8 +1,7 @@
#include "reader/reader.h"
#define BSNES_VERSION "0.013"
#define BSNES_TITLE "bsnes v" BSNES_VERSION
#include "clock/clock.h"
#include "clock/bclock/bclock.h"
extern Clock *clock;
#include "reader/reader.h"
#include "memory/memory.h"
#include "memory/bmemory/bmemory.h"
@@ -13,6 +12,15 @@ extern MemBus *mem_bus;
#include "cpu/bcpu/bcpu.h"
extern CPU *cpu;
#include "apu/apu.h"
#include "apu/bapu/bapu.h"
#include "apu/bapuskip/bapuskip.h"
extern APU *apu;
#include "dsp/dsp.h"
#include "dsp/bdsp/bdsp.h"
extern DSP *dsp;
#include "ppu/ppu.h"
#include "ppu/bppu/bppu.h"
extern PPU *ppu;
@@ -20,10 +28,22 @@ extern PPU *ppu;
#include "snes/snes.h"
extern SNES *snes;
#include "chip/srtc/srtc.h"
#include "chip/sdd1/sdd1.h"
extern SRTC *srtc;
extern SDD1 *sdd1;
#include "config/config.h"
#ifdef INTERFACE_MAIN
Clock *clock;
MemBus *mem_bus;
CPU *cpu;
PPU *ppu;
SNES *snes;
#include "config/config.cpp"
MemBus *mem_bus;
CPU *cpu;
APU *apu;
DSP *dsp;
PPU *ppu;
SNES *snes;
SRTC *srtc;
SDD1 *sdd1;
#endif

View File

@@ -1,5 +1,5 @@
/*
libbase : version 0.01 ~byuu
libbase : version 0.03 ~byuu (08/20/05)
*/
#ifndef __LIBBASE
@@ -10,10 +10,23 @@
#include <stdarg.h>
#include <string.h>
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define zerofree(__n) if(__n) { free(__n); __n = 0; }
typedef unsigned int uint;
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long ulong;
typedef unsigned char bool8;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned long uint32;

View File

@@ -1,304 +1,161 @@
#include "libbase.h"
#include "libconfig.h"
bool config_item::changed() {
return (is_string == true) ? (*strsource != strdef) : (*source != def);
void Setting::toggle() {
data ^= 1;
set(data);
}
config_item::config_item() {
is_string = false;
source = 0;
strsource = 0;
def = 0;
strdef = "";
type = 0;
name = "";
uint Setting::get() {
return data;
}
void config::add(uint32 *variable, char *name, uint32 def, uint32 type) {
int n;
if(item_count >= 4096)return;
n = item_count;
void Setting::set(uint _data) {
printf("%s %d\n", name, _data);
data = _data;
item[n] = new config_item();
item[n]->is_string = false;
item[n]->name = name;
item[n]->source = variable;
item[n]->def = def;
item[n]->type = type;
*item[n]->source = item[n]->def;
item_count++;
}
void config::add(string *variable, char *name, char *def, uint32 type) {
int n;
if(item_count >= 4096)return;
n = item_count;
item[n] = new config_item();
item[n]->is_string = true;
item[n]->name = name;
item[n]->strsource = variable;
item[n]->strdef = def;
*item[n]->strsource = item[n]->strdef;
item_count++;
}
uint32 config::find(char *name) {
for(int i=0;i<item_count;i++) {
if(item[i]->name == name) {
return i;
}
if(type != DEC && type != HEX) {
//data is a boolean type
data &= 1;
}
return null;
}
uint32 config::get(char *name) {
int i = find(name);
if(i == null)return 0;
return *item[i]->source;
}
string &config::strget(char *name) {
int i = find(name);
if(i == null) {
static string not_found;
not_found = "";
return not_found;
Setting::Setting(Config *_parent, char *_name, char *_desc, uint _data, uint _type) {
int s;
if(_parent) {
_parent->add(this);
}
return *item[i]->strsource;
s = strlen(_name);
name = (char*)malloc(s + 1);
strcpy(name, _name);
if(_desc) {
s = strlen(_desc);
desc = (char*)malloc(s + 1);
strcpy(desc, _desc);
} else {
desc = (char*)malloc(1);
*desc = 0;
}
data = _data;
def = _data;
type = _type;
}
void config::set(char *name, uint32 value) {
int i = find(name);
if(i == null)return;
*item[i]->source = value;
void Config::add(Setting *setting) {
list[list_count++] = setting;
}
void config::set(char *name, char *value) {
int i = find(name);
if(i == null)return;
*item[i]->strsource = value;
uint Config::string_to_uint(uint type, char *input) {
if(!strcmp(input, "true") ||
!strcmp(input, "enabled") ||
!strcmp(input, "on") ||
!strcmp(input, "yes")
) {
return (uint)true;
}
if(!strcmp(input, "false") ||
!strcmp(input, "disabled") ||
!strcmp(input, "off") ||
!strcmp(input, "no")
) {
return (uint)false;
}
if(!strbegin(input, "0x")) {
return strhex(input + 2);
}
return strdec(input);
}
void config::load(char *fn) {
char *Config::uint_to_string(uint type, uint input) {
static char output[512];
switch(type) {
case Setting::TRUE_FALSE:
sprintf(output, "%s", (input & 1)?"true":"false");
break;
case Setting::ENABLED_DISABLED:
sprintf(output, "%s", (input & 1)?"enabled":"disabled");
break;
case Setting::ON_OFF:
sprintf(output, "%s", (input & 1)?"on":"off");
break;
case Setting::YES_NO:
sprintf(output, "%s", (input & 1)?"yes":"no");
break;
case Setting::DEC:
sprintf(output, "%d", input);
break;
case Setting::HEX:
sprintf(output, "0x%x", input);
break;
}
return output;
}
bool Config::load(char *fn) {
FILE *fp;
char *buffer;
int i, fsize;
uint32 l;
fp = fopen(fn, "rb");
/* file doesn't exist yet, do nothing */
if(!fp)return;
if(!fp)return false;
//load the config file into memory
fseek(fp, 0, SEEK_END);
fsize = ftell(fp);
int fsize = ftell(fp);
fseek(fp, 0, SEEK_SET);
/* blank file, do nothing */
if(fsize == 0) {
fclose(fp);
return;
}
buffer = (char*)malloc(fsize + 1);
char *buffer = (char*)malloc(fsize + 1);
fread(buffer, 1, fsize, fp);
fclose(fp);
buffer[fsize] = 0;
data = buffer;
*(buffer + fsize) = 0;
strcpy(data, buffer);
free(buffer);
replace(data, "\r\n", "\n");
qreplace(data, "\t", " ");
//split the file into lines
replace(data, "\r\n", "\n");
qreplace(data, "\t", "");
qreplace(data, " ", "");
split(line, "\n", data);
for(i=0;i<count(line);i++) {
qreplace(line[i], " ", "");
/* remove comment, if it exists */
if(strqpos(line[i], "#") != null) {
strset(line[i], strqpos(line[i], "#"), 0);
}
/* ignore blank lines */
for(int i=0;i<count(line);i++) {
if(strlen(line[i]) == 0)continue;
if(*strptr(line[i]) == '#')continue;
qsplit(part, "=", line[i]);
l = find(*part[0]);
if(l != null) {
/* if the config item name is valid... update item value */
if(item[l]->is_string == true) {
strunquote(part[1]);
*item[l]->strsource = part[1];
} else {
if(part[1] == "true" || part[1] == "yes" || part[1] == "on" || part[1] == "enabled") {
*item[l]->source = 1;
} else if(part[1] == "false" || part[1] == "no" || part[1] == "off" || part[1] == "disabled") {
*item[l]->source = 0;
} else if(item[l]->type == HEX) {
*item[l]->source = strhex(part[1]);
} else { /* fall back on DEC */
*item[l]->source = strdec(part[1]);
}
split(part, "=", line[i]);
for(int l=0;l<list_count;l++) {
if(!strcmp(list[l]->name, part[0])) {
list[l]->set(string_to_uint(list[l]->type, strptr(part[1])));
}
}
}
}
/* create a text string from config item[i] to be output via config->save() */
void config::set_newline(int i) {
char t[16];
if(item[i]->is_string == true) {
newline = item[i]->name;
newline += " = \"";
newline += *item[i]->strsource;
newline += "\"";
} else {
newline = item[i]->name;
newline += " = ";
switch(item[i]->type) {
case TRUEFALSE:
newline += (*item[i]->source)?"true":"false";
break;
case YESNO:
newline += (*item[i]->source)?"yes":"no";
break;
case ONOFF:
newline += (*item[i]->source)?"on":"off";
break;
case ENABLED:
newline += (*item[i]->source)?"enabled":"disabled";
break;
case HEX:
sprintf(t, "%x", *item[i]->source);
newline += t;
break;
case DEC:
default:
sprintf(t, "%d", *item[i]->source);
newline += t;
break;
}
}
return true;
}
bool Config::load(substring &fn) { return load(strptr(fn)); }
void config::save(char *fn) {
bool Config::save(char *fn) {
FILE *fp;
int i, fsize;
uint32 l;
char *buffer;
uint8 set[4096];
bool blank = false;
fp = fopen(fn, "rb");
if(!fp) {
blank = true;
} else {
fseek(fp, 0, SEEK_END);
fsize = ftell(fp);
fseek(fp, 0, SEEK_SET);
if(fsize == 0) {
blank = true;
} else {
buffer = (char*)malloc(fsize + 1);
fread(buffer, 1, fsize, fp);
fclose(fp);
buffer[fsize] = 0;
data = buffer;
free(buffer);
}
}
fp = fopen(fn, "wb");
/* no write access? */
if(!fp)return;
if(!fp)return false;
/* list of config items. if the item is set in the
existing config file, then don't test it to see
if it needs to be written again later on */
memset(set, 0, item_count);
if(blank == false) {
for(int i=0;i<list_count;i++) {
strcpy(data, list[i]->desc);
replace(data, "\r\n", "\n");
qreplace(data, "\t", " ");
split(line, "\n", data);
split(oldline, "\n", data);
for(i=0;i<count(line);i++) {
qreplace(line[i], " ", "");
if(strqpos(line[i], "#") != null) {
strset(line[i], strqpos(line[i], "#"), 0);
}
/* this line is empty, restore the old line and continue */
if(strlen(line[i]) == 0) {
line[i] = oldline[i];
continue;
}
qsplit(part, "=", line[i]);
l = find(*part[0]);
if(l == null) {
/* invalid item name, restore the old line and continue */
line[i] = oldline[i];
continue;
}
set[l] = 1;
set_newline(l);
/* copy the user comment from the old config file, if it exists */
if(strqpos(oldline[i], "#") != null) {
newline += " ";
newline += *oldline[i] + strqpos(oldline[i], "#");
}
line[i] = newline;
}
/* write out the old config file + changes first */
for(i=0;i<count(line);) {
fprintf(fp, "%s", *line[i]);
/* write a line feed on all lines but the last.
keeps the file from growing everytime it is saved */
if(++i < count(line))fprintf(fp, "\r\n");
split(line, "\n", data);
for(int l=0;l<count(line);l++) {
fprintf(fp, "# %s\r\n", strptr(line[l]));
}
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));
}
int lines_written;
for(i=lines_written=0;i<item_count;i++) {
/* if the item was written to the file above... */
if(set[i] == 1)continue;
/* ...or if it is still set to the default value,
then don't output it to the file here */
if(item[i]->changed() == false)continue;
set_newline(i);
/* prevent a newline from appearing at the top of the file
when the config file is created for the first time */
if(lines_written == 0 && blank == false)fprintf(fp, "\r\n");
fprintf(fp, "%s\r\n", *newline);
lines_written++;
}
fclose(fp);
return true;
}
bool Config::save(substring &fn) { return save(strptr(fn)); }
config::config() {
item_count = 0;
}
config::~config() {
for(int i=0;i<item_count;i++) {
if(item[i])delete(item[i]);
}
Config::Config() {
list_count = 0;
}

View File

@@ -1,5 +1,5 @@
/*
libconfig : version 0.01 ~byuu
libconfig : version 0.05 ~byuu (09/13/05)
*/
#ifndef __LIBCONFIG
@@ -7,45 +7,92 @@
#include "libstring.h"
class config_item {
public:
uint32 *source, def, type;
string *strsource, strdef;
bool is_string;
string name;
bool changed();
config_item();
};
class Config;
//operator= is the /only/ overloaded operator that isn't inherited by derived classes.
//similarly, base constructor/destructors with arguments are not inherited.
//the inclusion of the overloaded virtual function 'toggle' is to allow toggle to call
//the overloaded set() function, if it exists. for some reason, Setting::toggle() calls
//Setting::set() no matter what, even if the derived class defines set()...
//the below macro is a quick way to take care of all of these issues.
//usage example:
// class T : public Setting { public: SettingOperators(T); } t;
// t = 0; // -> t.set(0);
#define SettingOperators(__name) \
inline __name &operator=(const bool _data) { set((uint)_data); return *this; } \
inline __name &operator=(const uint _data) { set(_data); return *this; } \
inline __name &operator=(const uint8 _data) { set(_data); return *this; } \
inline __name &operator=(const uint16 _data) { set(_data); return *this; } \
inline __name &operator=(const uint32 _data) { set(_data); return *this; } \
inline __name &operator=(const int _data) { set(_data); return *this; } \
inline __name &operator=(const int8 _data) { set(_data); return *this; } \
inline __name &operator=(const int16 _data) { set(_data); return *this; } \
inline __name &operator=(const int32 _data) { set(_data); return *this; } \
void toggle() { data ^= 1; set(data); } \
__name(Config *_parent, char *_name, char *_desc = 0, uint _data = 0, uint _type = Setting::DEC) : \
Setting(_parent, _name, _desc, _data, _type) {}
class Setting {
friend class Config;
protected:
uint data, type, def;
class config {
private:
uint32 item_count;
config_item *item[4096];
string data, line, oldline, newline, part;
public:
enum {
TRUEFALSE = 0,
YESNO = 1,
ONOFF = 2,
ENABLED = 3,
DEC = 4,
HEX = 5,
STR = 6
TRUE_FALSE,
ENABLED_DISABLED,
ON_OFF,
YES_NO,
BOOL,
DEC,
HEX
};
void add(uint32 *variable, char *name, uint32 def, uint32 type = DEC);
void add(string *variable, char *name, char *def, uint32 type = STR);
uint32 find(char *name);
uint32 get(char *name);
string &strget(char *name);
void set(char *name, uint32 value);
void set(char *name, char *value);
char *name, *desc;
virtual void toggle();
virtual uint get();
virtual void set(uint _data);
void load(char *fn);
void save(char *fn);
void set_newline(int i);
Setting(Config *_parent, char *_name, char *_desc = 0, uint _data = 0, uint _type = DEC);
config();
~config();
inline operator bool() { return (bool)get(); }
inline operator uint() { return get(); }
inline operator uint8() { return get(); }
inline operator uint16() { return get(); }
inline operator uint32() { return get(); }
inline operator int() { return get(); }
inline operator int8() { return get(); }
inline operator int16() { return get(); }
inline operator int32() { return get(); }
inline Setting &operator=(const bool _data) { set((uint)_data); return *this; }
inline Setting &operator=(const uint _data) { set(_data); return *this; }
inline Setting &operator=(const uint8 _data) { set(_data); return *this; }
inline Setting &operator=(const uint16 _data) { set(_data); return *this; }
inline Setting &operator=(const uint32 _data) { set(_data); return *this; }
inline Setting &operator=(const int _data) { set(_data); return *this; }
inline Setting &operator=(const int8 _data) { set(_data); return *this; }
inline Setting &operator=(const int16 _data) { set(_data); return *this; }
inline Setting &operator=(const int32 _data) { set(_data); return *this; }
};
class Config {
protected:
vector<Setting*> list;
uint list_count;
string data, line, part, subpart;
uint string_to_uint(uint type, char *input);
char *uint_to_string(uint type, uint input);
public:
void add(Setting *setting);
bool load(char *fn);
bool load(substring &fn);
bool save(char *fn);
bool save(substring &fn);
Config();
};
#endif

View File

@@ -1,23 +1,26 @@
#include "libbase.h"
#include "libstring.h"
_string::_string() {
substring::substring() {
size = 16;
s = (char*)malloc(size + 1);
*s = 0;
}
_string::~_string() {
free(s);
}
void string::addto(uint32 num) {
while(listcount < (num + 1)) {
list[listcount++] = new _string();
substring::~substring() {
if(s) {
free(s);
s = 0;
}
}
_string &string::str(uint32 num) {
void string::addto(uint num) {
while(listcount < (num + 1)) {
list[listcount++] = new substring();
}
}
substring &string::str(uint num) {
if(listcount < (num + 1)) { addto(num); }
return *list[num];
}
@@ -31,60 +34,68 @@ string::string() {
string::~string() {
int i;
for(i=listcount-1;i>=0;i--) {
delete((_string*)list[i]);
delete((substring*)list[i]);
}
}
uint32 count(string &str) {
return str.count;
char chrlower(char c) {
if(c >= 'A' && c <= 'Z')return c + ('a' - 'A');
return c;
}
void strresize(_string &str, uint32 size) {
char *t;
int sl;
if(str.size == size)return;
sl = strlen(str.s);
t = (char*)malloc(size + 1);
strcpy(t, str.s);
free(str.s);
str.s = t;
char chrupper(char c) {
if(c >= 'a' && c <= 'z')return c - ('a' - 'A');
return c;
}
uint count(string &str) { return str.count; }
void strresize(substring &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(substring &str) { return str.s; }
void strcpy(_string &dest, char *src) {
uint strlen(substring &str) { return strlen(strptr(str)); }
int strcmp(substring &dest, const char *src) { return strcmp(strptr(dest), src); }
int strcmp(const char *dest, substring &src) { return strcmp(dest, strptr(src)); }
int strcmp(substring &dest, substring &src) { return strcmp(strptr(dest), strptr(src)); }
void strcpy(substring &dest, const char *src) {
int srclen = strlen(src);
if(srclen > dest.size) { strresize(dest, srclen); }
strcpy(dest.s, src);
}
void strcpy(substring &dest, substring &src) { strcpy(dest, strptr(src)); }
void strset(_string &dest, uint32 pos, uint8 c) {
void strset(substring &dest, uint pos, uint8 c) {
char *s;
if(pos > dest.size) { strresize(dest, pos); }
dest.s[pos] = c;
}
void strcat(_string &dest, char *src) {
void strcat(substring &dest, const char *src) {
int srclen, destlen;
srclen = strlen(src);
destlen = strlen(dest.s);
if(srclen + destlen > dest.size) { strresize(dest, srclen + destlen); }
strcat(dest.s, src);
}
void strcat(substring &dest, substring &src) { strcat(dest, strptr(src)); }
void strinsert(_string &dest, char *src, uint32 pos) {
_string *s = new _string();
strcpy(*s, strptr(dest) + pos);
void strinsert(substring &dest, const char *src, uint pos) {
static substring s;
strcpy(s, strptr(dest) + pos);
strset(dest, pos, 0);
strcat(dest, src);
strcat(dest, *s);
delete(s);
strcat(dest, s);
}
void strinsert(substring &dest, substring &src, uint pos) { strinsert(dest, strptr(src), pos); }
void strremove(_string &dest, uint32 start, uint32 length) {
void strremove(substring &dest, uint start, uint length) {
int destlen;
char *s;
int i, sl = strlen(dest.s);
@@ -98,36 +109,35 @@ int i, sl = strlen(dest.s);
s[i] = 0;
}
bool stricmp(char *dest, char *src) {
int i, sl = strlen(dest);
if(sl != strlen(src))return false;
for(i=0;i<sl;i++) {
if(dest[i] >= 'A' && dest[i] <= 'Z') {
if(dest[i] != src[i] && dest[i] + 0x20 != src[i])return false;
} else if(dest[i] >='a' && dest[i] <= 'z') {
if(dest[i] != src[i] && dest[i] - 0x20 != src[i])return false;
} else {
if(dest[i] != src[i])return false;
}
int __stricmp(const char *dest, const char *src) {
while(*dest && *src) {
if(chrlower(*dest) != chrlower(*src))break;
dest++;
src++;
}
return true;
return (int)chrlower(*dest) - (int)chrlower(*src);
}
int stricmp(substring &dest, const char *src) { return __stricmp(strptr(dest), src); }
int stricmp(const char *dest, substring &src) { return __stricmp(dest, strptr(src)); }
int stricmp(substring &dest, substring &src) { return __stricmp(strptr(dest), strptr(src)); }
void strlower(char *str) {
int i, sl = strlen(str);
for(i=0;i<sl;i++) {
if(str[i] >= 'A' && str[i] <= 'Z')str[i] += 0x20;
while(*str) {
*str = chrlower(*str);
str++;
}
}
void strlower(substring &str) { strlower(strptr(str)); }
void strupper(char *str) {
int i, sl = strlen(str);
for(i=0;i<sl;i++) {
if(str[i] >= 'a' && str[i] <= 'z')str[i] -= 0x20;
while(*str) {
*str = chrupper(*str);
str++;
}
}
void strupper(substring &str) { strupper(strptr(str)); }
uint32 strpos(char *str, char *key) {
uint strpos(const char *str, const char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return null;
for(i=0;i<=ssl-ksl;i++) {
@@ -135,8 +145,11 @@ int i, ssl = strlen(str), ksl = strlen(key);
}
return null;
}
uint strpos(substring &str, const char *key) { return strpos(strptr(str), key); }
uint strpos(const char *str, substring &key) { return strpos(str, strptr(key)); }
uint strpos(substring &str, substring &key) { return strpos(strptr(str), strptr(key)); }
uint32 strqpos(char *str, char *key) {
uint qstrpos(const char *str, const char *key) {
int i, z, ssl = strlen(str), ksl = strlen(key);
uint8 x;
if(ksl > ssl)return null;
@@ -155,8 +168,11 @@ uint8 x;
}
return null;
}
uint qstrpos(substring &str, const char *key) { return qstrpos(strptr(str), key); }
uint qstrpos(const char *str, substring &key) { return qstrpos(str, strptr(key)); }
uint qstrpos(substring &str, substring &key) { return qstrpos(strptr(str), strptr(key)); }
void strtr(char *dest, char *before, char *after) {
void strtr(char *dest, const char *before, const char *after) {
int i, l, sl = strlen(dest), bsl = strlen(before), asl = strlen(after);
if((bsl != asl) || bsl == 0)return;
for(i=0;i<sl;i++) {
@@ -165,15 +181,17 @@ int i, l, sl = strlen(dest), bsl = strlen(before), asl = strlen(after);
}
}
}
void strtr(substring &dest, const char *before, const char *after) { strtr(strptr(dest), before, after); }
uint32 strbegin(char *str, char *key) {
uint strbegin(const char *str, const char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return 1;
if(!memcmp(str, key, ksl))return 0;
return 1;
}
uint strbegin(substring &str, const char *key) { return strbegin(strptr(str), key); }
uint32 stribegin(char *str, char *key) {
uint stribegin(const char *str, const char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return 1;
for(i=0;i<ksl;i++) {
@@ -187,15 +205,17 @@ int i, ssl = strlen(str), ksl = strlen(key);
}
return 0;
}
uint stribegin(substring &str, const char *key) { return stribegin(strptr(str), key); }
uint32 strend(char *str, char *key) {
uint strend(const char *str, const char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return 1;
if(!memcmp(str + ssl - ksl, key, ksl))return 0;
return 1;
}
uint strend(substring &str, const char *key) { return strend(strptr(str), key); }
uint32 striend(char *str, char *key) {
uint striend(const char *str, const char *key) {
int i, z, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return 1;
for(i=ssl-ksl, z=0;i<ssl;i++, z++) {
@@ -209,8 +229,9 @@ int i, z, ssl = strlen(str), ksl = strlen(key);
}
return 0;
}
uint striend(substring &str, const char *key) { return striend(strptr(str), key); }
void strltrim(char *str, char *key) {
void strltrim(char *str, const char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return;
if(!strbegin(str, key)) {
@@ -218,8 +239,9 @@ int i, ssl = strlen(str), ksl = strlen(key);
str[i] = 0;
}
}
void strltrim(substring &str, const char *key) { strltrim(strptr(str), key); }
void striltrim(char *str, char *key) {
void striltrim(char *str, const char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return;
if(!stribegin(str, key)) {
@@ -227,43 +249,46 @@ int i, ssl = strlen(str), ksl = strlen(key);
str[i] = 0;
}
}
void striltrim(substring &str, const char *key) { striltrim(strptr(str), key); }
void strrtrim(char *str, char *key) {
void strrtrim(char *str, const char *key) {
int ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return;
if(!strend(str, key)) {
str[ssl - ksl] = 0;
}
}
void strrtrim(substring &str, const char *key) { strrtrim(strptr(str), key); }
void strirtrim(char *str, char *key) {
void strirtrim(char *str, const char *key) {
int ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return;
if(!striend(str, key)) {
str[ssl - ksl] = 0;
}
}
void strirtrim(substring &str, const char *key) { strirtrim(strptr(str), key); }
/* does not work on type char* because function increases string length */
void strquote(_string &str) {
//does not work on type char* because function increases string length
void strquote(substring &str) {
static string t;
t = "\"";
t += str;
t += "\"";
str = t;
strcpy(t, "\"");
strcat(t, str);
strcat(t, "\"");
strcpy(str, t);
}
bool strunquote(char *str) {
int i, ssl = strlen(str);
/* make sure string is long enough to have quotes */
//make sure string is long enough to have quotes
if(ssl < 2)return false;
/* make sure string actually has quotes */
//make sure string actually has quotes
if(str[0] == '\"' && str[ssl - 1] == '\"');
else if(str[0] == '\'' && str[ssl - 1] == '\'');
else return false;
/* now remove them */
//now remove them
for(i=0;i<ssl;i++) {
str[i] = str[i + 1];
}
@@ -271,9 +296,10 @@ int i, ssl = strlen(str);
return true;
}
bool strunquote(substring &str) { return strunquote(strptr(str)); }
uint32 strhex(char *str) {
uint32 r = 0, m = 0;
uint strhex(const char *str) {
uint r = 0, m = 0;
int i, ssl = strlen(str);
uint8 x;
for(i=0;i<ssl;i++) {
@@ -292,31 +318,44 @@ uint8 x;
}
return r;
}
uint strhex(substring &str) { return strhex(strptr(str)); }
int strdec(char *str) {
uint32 m = 1;
int sstrhex(const char *str) {
if(str[0] == '-') {
return -strhex(str + 1);
}
return strhex(str);
}
int sstrhex(substring &str) { return sstrhex(strptr(str)); }
uint strdec(const char *str) {
uint m = 1;
int i, r = 0, ssl = strlen(str);
uint8 x;
for(i=0;i<ssl;i++) {
if(str[i] >= '0' && str[i] <= '9');
else if(str[i] == '-' && i == 0);
else break;
}
for(--i;i>=0;i--, m*=10) {
x = str[i];
if(x >= '0' && x <= '9')x -= '0';
else if(i == 0 && str[i] == '-') {
r *= -1;
return r;
}
else return r;
r += x * m;
}
return r;
}
uint strdec(substring &str) { return strdec(strptr(str)); }
uint32 strbin(char *str) {
uint32 r = 0, m = 0;
int sstrdec(const char *str) {
if(str[0] == '-') {
return -strdec(str + 1);
}
return strdec(str);
}
int sstrdec(substring &str) { return sstrdec(strptr(str)); }
uint strbin(const char *str) {
uint r = 0, m = 0;
int i, ssl = strlen(str);
uint8 x;
for(i=0;i<ssl;i++) {
@@ -331,6 +370,15 @@ uint8 x;
}
return r;
}
uint strbin(substring &str) { return strbin(strptr(str)); }
int sstrbin(const char *str) {
if(str[0] == '-') {
return -strbin(str + 1);
}
return strbin(str);
}
int sstrbin(substring &str) { return sstrbin(strptr(str)); }
#include "libstring_math.cpp"
#include "libstring_split.cpp"

View File

@@ -1,5 +1,5 @@
/*
libstring : version 0.04 ~byuu
libstring : version 0.06a ~byuu (08/22/05)
*/
#ifndef __LIBSTRING
@@ -8,269 +8,172 @@
#include "libvector.h"
class string;
class _string;
class substring;
uint32 count(string &str);
void strresize(_string &str, uint32 size);
char* strptr(_string &str);
void strcpy(_string &dest, char *src);
void strset(_string &dest, uint32 pos, uint8 c);
void strcat(_string &dest, char *src);
void strinsert(_string &dest, char *src, uint32 pos);
void strremove(_string &dest, uint32 start, uint32 length = 0);
bool stricmp(char *dest, char *src);
void strlower(char *str);
void strupper(char *str);
uint32 strpos(char *str, char *key);
uint32 strqpos(char *str, char *key);
void strtr(char *dest, char *before, char *after);
uint32 strbegin(char *str, char *key);
uint32 stribegin(char *str, char *key);
uint32 strend(char *str, char *key);
uint32 striend(char *str, char *key);
void strltrim(char *str, char *key);
void striltrim(char *str, char *key);
void strrtrim(char *str, char *key);
void strirtrim(char *str, char *key);
void strquote(_string &str);
bool strunquote(char *str);
uint32 strhex(char *str);
int strdec(char *str);
uint32 strbin(char *str);
uint32 strmath(char *in_str);
uint32 strmathentity(char *str);
void replace (_string &str, char *key, char *token);
void qreplace(_string &str, char *key, char *token);
void split (string &dest, char *key, char *src);
void qsplit(string &dest, char *key, char *src);
void sprintf(_string &str, char *s, ...);
char chrlower(char c);
char chrupper(char c);
class _string {
uint count(string &str);
void strresize(substring &str, uint size);
char* strptr(substring &str);
uint strlen(substring &str);
int strcmp(substring &dest, const char *src);
int strcmp(const char *dest, substring &src);
int strcmp(substring &dest, substring &src);
void strcpy(substring &dest, const char *src);
void strcpy(substring &dest, substring &src);
void strset(substring &dest, uint pos, uint8 c);
void strcat(substring &dest, const char *src);
void strcat(substring &dest, substring &src);
void strinsert(substring &dest, const char *src, uint pos);
void strinsert(substring &dest, substring &src, uint pos);
void strremove(substring &dest, uint start, uint length = 0);
//vc6/win32 and gcc/dos only support stricmp, whereas
//gcc/unix only supports strcasecmp. this is an attempt
//to avoid platform-specific defines...
#define stricmp __stricmp
int __stricmp(const char *dest, const char *src);
int stricmp(substring &dest, const char *src);
int stricmp(const char *dest, substring &src);
int stricmp(substring &dest, substring &src);
void strlower(char *str);
void strlower(substring &str);
void strupper(char *str);
void strupper(substring &str);
uint strpos(const char *str, const char *key);
uint strpos(substring &str, const char *key);
uint strpos(const char *str, substring &key);
uint strpos(substring &str, substring &key);
uint qstrpos(const char *str, const char *key);
uint qstrpos(substring &str, const char *key);
uint qstrpos(const char *str, substring &key);
uint qstrpos(substring &str, substring &key);
void strtr(char *dest, const char *before, const char *after);
void strtr(substring &dest, const char *before, const char *after);
uint strbegin(const char *str, const char *key);
uint strbegin(substring &str, const char *key);
uint stribegin(const char *str, const char *key);
uint stribegin(substring &str, const char *key);
uint strend(const char *str, const char *key);
uint strend(substring &str, const char *key);
uint striend(const char *str, const char *key);
uint striend(substring &str, const char *key);
void strltrim(char *str, const char *key);
void strltrim(substring &str, const char *key);
void striltrim(char *str, const char *key);
void striltrim(substring &str, const char *key);
void strrtrim(char *str, const char *key);
void strrtrim(substring &str, const char *key);
void strirtrim(char *str, const char *key);
void strirtrim(substring &str, const char *key);
void strquote(substring &str);
bool strunquote(char *str);
bool strunquote(substring &str);
uint strhex(const char *str);
uint strhex(substring &str);
int sstrhex(const char *str);
int sstrhex(substring &str);
uint strdec(const char *str);
uint strdec(substring &str);
int sstrdec(const char *str);
int sstrdec(substring &str);
uint strbin(const char *str);
uint strbin(substring &str);
int sstrbin(const char *str);
int sstrbin(substring &str);
uint strmath(const char *in_str);
uint strmath(substring &in_str);
bool strmathentity(const char *str);
bool strmathentity(substring &str);
void replace(substring &str, const char *key, const char *token);
void replace(substring &str, const char *key, substring &token);
void qreplace(substring &str, const char *key, const char *token);
void qreplace(substring &str, const char *key, substring &token);
void split(string &dest, const char *key, char *src);
void split(string &dest, const char *key, substring &src);
void qsplit(string &dest, const char *key, char *src);
void qsplit(string &dest, const char *key, substring &src);
void sprintf(substring &str, const char *s, ...);
class substring {
public:
char *s;
uint32 size;
uint size;
//inline char* operator*() { return s; }
//inline operator char*() { return s; }
/* * */
inline char* operator*() { return s; }
/* = */
inline _string& operator=(char *cpy);
inline _string& operator=(_string &cpy);
inline _string& operator=(string &cpy);
/* += */
inline _string& operator+=(char *cat);
inline _string& operator+=(_string &cat);
inline _string& operator+=(string &cat);
/* -= */
inline _string& operator-=(char *cut);
inline _string& operator-=(_string &cut);
inline _string& operator-=(string &cut);
/* == */
inline bool operator==(char *cmp);
inline bool operator==(_string &cmp);
inline bool operator==(string &cmp);
/* != */
inline bool operator!=(char *cmp);
inline bool operator!=(_string &cmp);
inline bool operator!=(string &cmp);
inline operator char*() { return s; }
_string();
~_string();
substring();
~substring();
};
/* listcount is the actual size of list[], used for allocation
* of substrings.
* count is used by split() and count() to return the number of
* active/valid substrings. example: if string T contains 16
* substrings, and split is called, which sets three substrings,
* then count() needs to reflect that only three substrings are
* now used, but listcount still needs to reflect the true size
* of list[].
*/
class string {
public:
vector<_string*> list;
uint32 count, listcount;
void addto(uint32 num); //creates all needed strings to make list[num] valid
_string &str(uint32 num); //gets a _string reference, creating it + new strings if needed
vector<substring*> list;
uint listcount, count;
void addto(uint num); //creates all needed strings to make list[num] valid
substring &str(uint num); //gets a substring reference, creating it + new strings if needed
/* * */
inline char* operator*() { return strptr(str(0)); }
/* = */
inline string& operator=(char *cpy);
inline string& operator=(_string &cpy);
inline string& operator=(string &cpy);
/* += */
inline string& operator+=(char *cat);
inline string& operator+=(_string &cat);
inline string& operator+=(string &cat);
/* -= */
inline string& operator-=(char *cut);
inline string& operator-=(_string &cut);
inline string& operator-=(string &cut);
/* == */
inline bool operator==(char *cmp);
inline bool operator==(_string &cmp);
inline bool operator==(string &cmp);
/* != */
inline bool operator!=(char *cmp);
inline bool operator!=(_string &cmp);
inline bool operator!=(string &cmp);
inline operator char*() { return str(0).s; }
inline operator _string&() { return str(0); }
inline _string& operator[](uint32 i) { return str(i); }
inline _string& operator[](int i) { return str(i); }
//inline char* operator*() { return strptr(str(0)); }
//inline operator char*() { return str(0).s; }
inline operator substring&() { return str(0); }
inline substring& operator[](uint i) { return str(i); }
inline substring& operator[](uint8 i) { return str(i); }
inline substring& operator[](uint16 i) { return str(i); }
inline substring& operator[](uint32 i) { return str(i); }
inline substring& operator[](int i) { return str(i); }
inline substring& operator[](int8 i) { return str(i); }
inline substring& operator[](int16 i) { return str(i); }
inline substring& operator[](int32 i) { return str(i); }
string();
~string();
};
//
// =
//
inline _string& _string::operator=(char *cpy) {
strcpy(*this, cpy);
return *this;
}
inline _string& _string::operator=(_string &cpy) {
strcpy(*this, cpy);
return *this;
}
inline _string& _string::operator=(string &cpy) {
strcpy(*this, cpy.str(0));
return *this;
}
inline string& string::operator=(char *cpy) {
strcpy(str(0), cpy);
return *this;
}
inline string& string::operator=(_string &cpy) {
strcpy(str(0), cpy);
return *this;
}
inline string& string::operator=(string &cpy) {
strcpy(str(0), cpy.str(0));
return *this;
}
//
// +=
//
inline _string& _string::operator+=(char *cat) {
strcat(*this, cat);
return *this;
}
inline _string& _string::operator+=(_string &cat) {
strcat(*this, cat);
return *this;
}
inline _string& _string::operator+=(string &cat) {
strcat(*this, cat.str(0));
return *this;
}
inline string& string::operator+=(char *cat) {
strcat(str(0), cat);
return *this;
}
inline string& string::operator+=(_string &cat) {
strcat(str(0), cat);
return *this;
}
inline string& string::operator+=(string &cat) {
strcat(str(0), cat.str(0));
return *this;
}
//
// -=
//
inline _string& _string::operator-=(char *cut) {
strrtrim(*this, cut);
return *this;
}
inline _string& _string::operator-=(_string &cut) {
strrtrim(*this, cut);
return *this;
}
inline _string& _string::operator-=(string &cut) {
strrtrim(*this, cut.str(0));
return *this;
}
inline string& string::operator-=(char *cut) {
strrtrim(str(0), cut);
return *this;
}
inline string& string::operator-=(_string &cut) {
strrtrim(str(0), cut);
return *this;
}
inline string& string::operator-=(string &cut) {
strrtrim(str(0), cut.str(0));
return *this;
}
//
// ==
//
inline bool _string::operator==(char *cmp) {
if(!strcmp(*this, cmp))return true;
return false;
}
inline bool _string::operator==(_string &cmp) {
if(!strcmp(*this, cmp))return true;
return false;
}
inline bool _string::operator==(string &cmp) {
if(!strcmp(*this, cmp.str(0)))return true;
return false;
}
inline bool string::operator==(char *cmp) {
if(!strcmp(str(0), cmp))return true;
return false;
}
inline bool string::operator==(_string &cmp) {
if(!strcmp(str(0), cmp))return true;
return false;
}
inline bool string::operator==(string &cmp) {
if(!strcmp(str(0), cmp.str(0)))return true;
return false;
}
//
// !=
//
inline bool _string::operator!=(char *cmp) {
if(!strcmp(*this, cmp))return false;
return true;
}
inline bool _string::operator!=(_string &cmp) {
if(!strcmp(*this, cmp))return false;
return true;
}
inline bool _string::operator!=(string &cmp) {
if(!strcmp(*this, cmp.str(0)))return false;
return true;
}
inline bool string::operator!=(char *cmp) {
if(!strcmp(str(0), cmp))return false;
return true;
}
inline bool string::operator!=(_string &cmp) {
if(!strcmp(str(0), cmp))return false;
return true;
}
inline bool string::operator!=(string &cmp) {
if(!strcmp(str(0), cmp.str(0)))return false;
return true;
}
#endif
#endif //__LIBSTRING

View File

@@ -43,10 +43,10 @@ strmath(str)
str, and returns numerical result
example: strmath("5+5")=10
***************************************/
uint32 p_strmath(char *str) {
int i = 0, ssl = strlen(str);
uint p_strmath(const char *str) {
int i = 0, ssl = strlen(str);
uint r, array[128], array_size = 0, z = 0;
uint8 x, mode = 0;
uint32 r, array[128], array_size = 0, z = 0;
uint8 array_gate[128];
char *s1;
if(!ssl)return 0;
@@ -95,11 +95,11 @@ char *s1;
return r;
}
uint32 strmath(char *in_str) {
uint32 r = 0;
uint32 pdepth = 0, cpdepth, maxpdepth = 0;
uint32 pstart, pend, spos;
int i, sc, sl = strlen(in_str);
uint strmath(const char *in_str) {
uint r = 0;
uint pdepth = 0, cpdepth, maxpdepth = 0;
uint pstart, pend, spos;
int i, sc, sl = strlen(in_str);
char *str = (char*)malloc(sl + 1), *str0;
char *pstr;
char num[64];
@@ -165,13 +165,15 @@ char num[64];
free(str);
return r;
}
uint strmath(substring &in_str) { return strmath(strptr(in_str)); }
uint32 strmathentity(char *str) {
bool strmathentity(const char *str) {
int i, ssl = strlen(str);
for(i=0;i<ssl;i++) {
if(str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/' ||
str[i] == '%' || str[i] == '&' || str[i] == '|' || str[i] == '^' ||
(str[i] == '<' && str[i+1] == '<') || (str[i] == '>' && str[i+1] == '>'))return 1;
(str[i] == '<' && str[i+1] == '<') || (str[i] == '>' && str[i+1] == '>'))return true;
}
return 0;
return false;
}
bool strmathentity(substring &str) { return strmathentity(strptr(str)); }

View File

@@ -1,6 +1,6 @@
void replace(_string &str, char *key, char *token) {
int i, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str);
uint32 replace_count = 0, size = ssl;
void replace(substring &str, const char *key, const char *token) {
int i, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str);
uint replace_count = 0, size = ssl;
char *data;
if(ksl > ssl)return;
if(tsl > ksl) { //the new string may be longer than the old string...
@@ -27,11 +27,12 @@ char *data;
strcpy(str, data);
free(data);
}
void replace(substring &str, const char *key, substring &token) { replace(str, key, strptr(token)); }
void qreplace(_string &str, char *key, char *token) {
int i, l, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str);
void qreplace(substring &str, const char *key, const char *token) {
int i, l, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str);
uint replace_count = 0, size = ssl;
uint8 x;
uint32 replace_count = 0, size = ssl;
char *data;
if(ksl > ssl)return;
if(tsl > ksl) {
@@ -80,3 +81,4 @@ char *data;
strcpy(str, data);
free(data);
}
void qreplace(substring &str, const char *key, substring &token) { qreplace(str, key, strptr(token)); }

View File

@@ -1,7 +1,7 @@
void split(string &dest, char *key, char *src) {
int i, ssl = strlen(src), ksl = strlen(key);
void split(string &dest, const char *key, char *src) {
int i, ssl = strlen(src), ksl = strlen(key);
uint lp = 0, split_count = 0;
uint8 x;
uint32 lp = 0, split_count = 0;
for(i=0;i<=ssl-ksl;) {
if(!memcmp(src + i, key, ksl)) {
x = src[i];
@@ -15,11 +15,12 @@ uint32 lp = 0, split_count = 0;
strcpy(dest[split_count++], src + lp);
dest.count = split_count;
}
void split(string &dest, const char *key, substring &src) { split(dest, key, strptr(src)); }
void qsplit(string &dest, char *key, char *src) {
int i, z, ssl = strlen(src), ksl = strlen(key);
void qsplit(string &dest, const char *key, char *src) {
int i, z, ssl = strlen(src), ksl = strlen(key);
uint lp = 0, split_count = 0;
uint8 x;
uint32 lp = 0, split_count = 0;
for(i=0;i<=ssl-ksl;) {
x = src[i];
if(x=='\"' || x=='\'') {
@@ -39,3 +40,4 @@ uint32 lp = 0, split_count = 0;
strcpy(dest[split_count++], src + lp);
dest.count = split_count;
}
void qsplit(string &dest, const char *key, substring &src) { qsplit(dest, key, strptr(src)); }

View File

@@ -1,5 +1,5 @@
void numtobin(char *s, uint32 num) {
uint32 mask = 0x80000000, len = 0, z = 0;
void numtobin(char *s, uint num) {
uint mask = 0x80000000, len = 0, z = 0;
for(;mask;mask>>=1,len++) { if(num&mask)break; }
len = 32 - len;
do {
@@ -9,7 +9,7 @@ uint32 mask = 0x80000000, len = 0, z = 0;
s[z] = 0;
}
void sprintf(_string &str, char *s, ...) {
void sprintf(substring &str, const char *s, ...) {
va_list args;
char t[2], n[256];
int i, l, sl, z;

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