From c9c49095eea9cdbf56822586133a27595035280e Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Sun, 12 Jun 2011 01:25:22 -0500 Subject: [PATCH 01/33] Add byuu's SMP and DSP files to tree. --- apu/apu.cpp | 6 + apu/bapu/dsp/SPC_DSP.cpp | 1072 ++++++++++++++++ apu/bapu/dsp/SPC_DSP.h | 319 +++++ apu/bapu/dsp/blargg_common.h | 186 +++ apu/bapu/dsp/blargg_config.h | 24 + apu/bapu/dsp/blargg_endian.h | 185 +++ apu/bapu/dsp/blargg_source.h | 100 ++ apu/bapu/dsp/dsp.cpp | 61 + apu/bapu/dsp/dsp.hpp | 26 + apu/bapu/dsp/serialization.cpp | 31 + apu/bapu/smp/algorithms.cpp | 122 ++ apu/bapu/smp/core.cpp | 105 ++ apu/bapu/smp/core/cc.sh | 1 + apu/bapu/smp/core/generate.cpp | 154 +++ apu/bapu/smp/core/op_misc.b | 163 +++ apu/bapu/smp/core/op_misc.cpp | 346 +++++ apu/bapu/smp/core/op_mov.b | 217 ++++ apu/bapu/smp/core/op_mov.cpp | 389 ++++++ apu/bapu/smp/core/op_pc.b | 179 +++ apu/bapu/smp/core/op_pc.cpp | 603 +++++++++ apu/bapu/smp/core/op_read.b | 205 +++ apu/bapu/smp/core/op_read.cpp | 744 +++++++++++ apu/bapu/smp/core/op_rmw.b | 74 ++ apu/bapu/smp/core/op_rmw.cpp | 262 ++++ apu/bapu/smp/core/opcycle_misc.cpp | 696 +++++++++++ apu/bapu/smp/core/opcycle_mov.cpp | 806 ++++++++++++ apu/bapu/smp/core/opcycle_pc.cpp | 1347 ++++++++++++++++++++ apu/bapu/smp/core/opcycle_read.cpp | 1599 ++++++++++++++++++++++++ apu/bapu/smp/core/opcycle_rmw.cpp | 550 ++++++++ apu/bapu/smp/debugger/debugger.cpp | 75 ++ apu/bapu/smp/debugger/debugger.hpp | 27 + apu/bapu/smp/debugger/disassembler.cpp | 304 +++++ apu/bapu/smp/iplrom.cpp | 44 + apu/bapu/smp/memory.cpp | 130 ++ apu/bapu/smp/smp.cpp | 154 +++ apu/bapu/smp/smp.hpp | 124 ++ apu/bapu/smp/timing.cpp | 26 + apu/bapu/snes/snes.hpp | 45 + gtk/Makefile.am | 10 +- gtk/src/gtk_s9xwindow.cpp | 4 - 40 files changed, 11509 insertions(+), 6 deletions(-) create mode 100755 apu/bapu/dsp/SPC_DSP.cpp create mode 100755 apu/bapu/dsp/SPC_DSP.h create mode 100755 apu/bapu/dsp/blargg_common.h create mode 100755 apu/bapu/dsp/blargg_config.h create mode 100755 apu/bapu/dsp/blargg_endian.h create mode 100755 apu/bapu/dsp/blargg_source.h create mode 100755 apu/bapu/dsp/dsp.cpp create mode 100755 apu/bapu/dsp/dsp.hpp create mode 100755 apu/bapu/dsp/serialization.cpp create mode 100755 apu/bapu/smp/algorithms.cpp create mode 100755 apu/bapu/smp/core.cpp create mode 100755 apu/bapu/smp/core/cc.sh create mode 100755 apu/bapu/smp/core/generate.cpp create mode 100755 apu/bapu/smp/core/op_misc.b create mode 100755 apu/bapu/smp/core/op_misc.cpp create mode 100755 apu/bapu/smp/core/op_mov.b create mode 100755 apu/bapu/smp/core/op_mov.cpp create mode 100755 apu/bapu/smp/core/op_pc.b create mode 100755 apu/bapu/smp/core/op_pc.cpp create mode 100755 apu/bapu/smp/core/op_read.b create mode 100755 apu/bapu/smp/core/op_read.cpp create mode 100755 apu/bapu/smp/core/op_rmw.b create mode 100755 apu/bapu/smp/core/op_rmw.cpp create mode 100755 apu/bapu/smp/core/opcycle_misc.cpp create mode 100755 apu/bapu/smp/core/opcycle_mov.cpp create mode 100755 apu/bapu/smp/core/opcycle_pc.cpp create mode 100755 apu/bapu/smp/core/opcycle_read.cpp create mode 100755 apu/bapu/smp/core/opcycle_rmw.cpp create mode 100755 apu/bapu/smp/debugger/debugger.cpp create mode 100755 apu/bapu/smp/debugger/debugger.hpp create mode 100755 apu/bapu/smp/debugger/disassembler.cpp create mode 100755 apu/bapu/smp/iplrom.cpp create mode 100755 apu/bapu/smp/memory.cpp create mode 100755 apu/bapu/smp/smp.cpp create mode 100755 apu/bapu/smp/smp.hpp create mode 100755 apu/bapu/smp/timing.cpp create mode 100755 apu/bapu/snes/snes.hpp diff --git a/apu/apu.cpp b/apu/apu.cpp index f6e24456..47f03b6b 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -183,6 +183,7 @@ #include "display.h" #include "linear_resampler.h" #include "hermite_resampler.h" +#include "snes/snes.hpp" #define APU_DEFAULT_INPUT_RATE 32000 #define APU_MINIMUM_SAMPLE_COUNT 512 @@ -195,6 +196,11 @@ SNES_SPC *spc_core = NULL; +namespace SNES +{ + CPU cpu; +} + static uint8 APUROM[64] = { 0xCD, 0xEF, 0xBD, 0xE8, 0x00, 0xC6, 0x1D, 0xD0, diff --git a/apu/bapu/dsp/SPC_DSP.cpp b/apu/bapu/dsp/SPC_DSP.cpp new file mode 100755 index 00000000..e6ba49ed --- /dev/null +++ b/apu/bapu/dsp/SPC_DSP.cpp @@ -0,0 +1,1072 @@ +// snes_spc 0.9.0. http://www.slack.net/~ant/ + +#include "SPC_DSP.h" + +#include "blargg_endian.h" +#include + +/* Copyright (C) 2007 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "blargg_source.h" + +#ifdef BLARGG_ENABLE_OPTIMIZER + #include BLARGG_ENABLE_OPTIMIZER +#endif + +#if INT_MAX < 0x7FFFFFFF + #error "Requires that int type have at least 32 bits" +#endif + +// TODO: add to blargg_endian.h +#define GET_LE16SA( addr ) ((BOOST::int16_t) GET_LE16( addr )) +#define GET_LE16A( addr ) GET_LE16( addr ) +#define SET_LE16A( addr, data ) SET_LE16( addr, data ) + +static BOOST::uint8_t const initial_regs [SPC_DSP::register_count] = +{ + 0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80, + 0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF, + 0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A, + 0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF, + 0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67, + 0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x00,0x4E,0x7B,0xFF, + 0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F, + 0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF +}; + +// if ( io < -32768 ) io = -32768; +// if ( io > 32767 ) io = 32767; +#define CLAMP16( io )\ +{\ + if ( (int16_t) io != io )\ + io = (io >> 31) ^ 0x7FFF;\ +} + +// Access global DSP register +#define REG(n) m.regs [r_##n] + +// Access voice DSP register +#define VREG(r,n) r [v_##n] + +#define WRITE_SAMPLES( l, r, out ) \ +{\ + out [0] = l;\ + out [1] = r;\ + out += 2;\ + if ( out >= m.out_end )\ + {\ + check( out == m.out_end );\ + check( m.out_end != &m.extra [extra_size] || \ + (m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\ + out = m.extra;\ + m.out_end = &m.extra [extra_size];\ + }\ +}\ + +void SPC_DSP::set_output( sample_t* out, int size ) +{ + require( (size & 1) == 0 ); // must be even + if ( !out ) + { + out = m.extra; + size = extra_size; + } + m.out_begin = out; + m.out = out; + m.out_end = out + size; +} + +// Volume registers and efb are signed! Easy to forget int8_t cast. +// Prefixes are to avoid accidental use of locals with same names. + +// Gaussian interpolation + +static short const gauss [512] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, + 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, + 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, + 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, 17, + 18, 19, 19, 20, 20, 21, 21, 22, 23, 23, 24, 24, 25, 26, 27, 27, + 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 36, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 58, 59, 60, 61, 62, 64, 65, 66, 67, 69, 70, 71, 73, 74, 76, 77, + 78, 80, 81, 83, 84, 86, 87, 89, 90, 92, 94, 95, 97, 99, 100, 102, + 104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132, + 134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168, + 171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210, + 212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257, + 260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311, + 314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370, + 374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434, + 439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504, + 508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577, + 582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654, + 659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732, + 737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811, + 816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889, + 894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965, + 969, 974, 978, 983, 988, 992, 997,1001,1005,1010,1014,1019,1023,1027,1032,1036, +1040,1045,1049,1053,1057,1061,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102, +1106,1109,1113,1117,1121,1125,1128,1132,1136,1139,1143,1146,1150,1153,1157,1160, +1164,1167,1170,1174,1177,1180,1183,1186,1190,1193,1196,1199,1202,1205,1207,1210, +1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251, +1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280, +1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298, +1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305, +}; + +inline int SPC_DSP::interpolate( voice_t const* v ) +{ + // Make pointers into gaussian based on fractional position between samples + int offset = v->interp_pos >> 4 & 0xFF; + short const* fwd = gauss + 255 - offset; + short const* rev = gauss + offset; // mirror left half of gaussian + + int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; + int out; + out = (fwd [ 0] * in [0]) >> 11; + out += (fwd [256] * in [1]) >> 11; + out += (rev [256] * in [2]) >> 11; + out = (int16_t) out; + out += (rev [ 0] * in [3]) >> 11; + + CLAMP16( out ); + out &= ~1; + return out; +} + + +//// Counters + +int const simple_counter_range = 2048 * 5 * 3; // 30720 + +static unsigned const counter_rates [32] = +{ + simple_counter_range + 1, // never fires + 2048, 1536, + 1280, 1024, 768, + 640, 512, 384, + 320, 256, 192, + 160, 128, 96, + 80, 64, 48, + 40, 32, 24, + 20, 16, 12, + 10, 8, 6, + 5, 4, 3, + 2, + 1 +}; + +static unsigned const counter_offsets [32] = +{ + 1, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 0, + 0 +}; + +inline void SPC_DSP::init_counter() +{ + m.counter = 0; +} + +inline void SPC_DSP::run_counters() +{ + if ( --m.counter < 0 ) + m.counter = simple_counter_range - 1; +} + +inline unsigned SPC_DSP::read_counter( int rate ) +{ + return ((unsigned) m.counter + counter_offsets [rate]) % counter_rates [rate]; +} + + +//// Envelope + +inline void SPC_DSP::run_envelope( voice_t* const v ) +{ + int env = v->env; + if ( v->env_mode == env_release ) // 60% + { + if ( (env -= 0x8) < 0 ) + env = 0; + v->env = env; + } + else + { + int rate; + int env_data = VREG(v->regs,adsr1); + if ( m.t_adsr0 & 0x80 ) // 99% ADSR + { + if ( v->env_mode >= env_decay ) // 99% + { + env--; + env -= env >> 8; + rate = env_data & 0x1F; + if ( v->env_mode == env_decay ) // 1% + rate = (m.t_adsr0 >> 3 & 0x0E) + 0x10; + } + else // env_attack + { + rate = (m.t_adsr0 & 0x0F) * 2 + 1; + env += rate < 31 ? 0x20 : 0x400; + } + } + else // GAIN + { + int mode; + env_data = VREG(v->regs,gain); + mode = env_data >> 5; + if ( mode < 4 ) // direct + { + env = env_data * 0x10; + rate = 31; + } + else + { + rate = env_data & 0x1F; + if ( mode == 4 ) // 4: linear decrease + { + env -= 0x20; + } + else if ( mode < 6 ) // 5: exponential decrease + { + env--; + env -= env >> 8; + } + else // 6,7: linear increase + { + env += 0x20; + if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 ) + env += 0x8 - 0x20; // 7: two-slope linear increase + } + } + } + + // Sustain level + if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay ) + v->env_mode = env_sustain; + + v->hidden_env = env; + + // unsigned cast because linear decrease going negative also triggers this + if ( (unsigned) env > 0x7FF ) + { + env = (env < 0 ? 0 : 0x7FF); + if ( v->env_mode == env_attack ) + v->env_mode = env_decay; + } + + if ( !read_counter( rate ) ) + v->env = env; // nothing else is controlled by the counter + } +} + + +//// BRR Decoding + +inline void SPC_DSP::decode_brr( voice_t* v ) +{ + // Arrange the four input nybbles in 0xABCD order for easy decoding + int nybbles = m.t_brr_byte * 0x100 + m.ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF]; + + int const header = m.t_brr_header; + + // Write to next four samples in circular buffer + int* pos = &v->buf [v->buf_pos]; + int* end; + if ( (v->buf_pos += 4) >= brr_buf_size ) + v->buf_pos = 0; + + // Decode four samples + for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 ) + { + // Extract nybble and sign-extend + int s = (int16_t) nybbles >> 12; + + // Shift sample based on header + int const shift = header >> 4; + s = (s << shift) >> 1; + if ( shift >= 0xD ) // handle invalid range + s = (s >> 25) << 11; // same as: s = (s < 0 ? -0x800 : 0) + + // Apply IIR filter (8 is the most commonly used) + int const filter = header & 0x0C; + int const p1 = pos [brr_buf_size - 1]; + int const p2 = pos [brr_buf_size - 2] >> 1; + if ( filter >= 8 ) + { + s += p1; + s -= p2; + if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875 + { + s += p2 >> 4; + s += (p1 * -3) >> 6; + } + else // s += p1 * 0.8984375 - p2 * 0.40625 + { + s += (p1 * -13) >> 7; + s += (p2 * 3) >> 4; + } + } + else if ( filter ) // s += p1 * 0.46875 + { + s += p1 >> 1; + s += (-p1) >> 5; + } + + // Adjust and write sample + CLAMP16( s ); + s = (int16_t) (s * 2); + pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around + } +} + + +//// Misc + +#define MISC_CLOCK( n ) inline void SPC_DSP::misc_##n() + +MISC_CLOCK( 27 ) +{ + m.t_pmon = REG(pmon) & 0xFE; // voice 0 doesn't support PMON +} +MISC_CLOCK( 28 ) +{ + m.t_non = REG(non); + m.t_eon = REG(eon); + m.t_dir = REG(dir); +} +MISC_CLOCK( 29 ) +{ + if ( (m.every_other_sample ^= 1) != 0 ) + m.new_kon &= ~m.kon; // clears KON 63 clocks after it was last read +} +MISC_CLOCK( 30 ) +{ + if ( m.every_other_sample ) + { + m.kon = m.new_kon; + m.t_koff = REG(koff) | m.mute_mask; + } + + run_counters(); + + // Noise + if ( !read_counter( REG(flg) & 0x1F ) ) + { + int feedback = (m.noise << 13) ^ (m.noise << 14); + m.noise = (feedback & 0x4000) ^ (m.noise >> 1); + } +} + + +//// Voices + +#define VOICE_CLOCK( n ) void SPC_DSP::voice_##n( voice_t* const v ) + +inline VOICE_CLOCK( V1 ) +{ + m.t_dir_addr = m.t_dir * 0x100 + m.t_srcn * 4; + m.t_srcn = VREG(v->regs,srcn); +} +inline VOICE_CLOCK( V2 ) +{ + // Read sample pointer (ignored if not needed) + uint8_t const* entry = &m.ram [m.t_dir_addr]; + if ( !v->kon_delay ) + entry += 2; + m.t_brr_next_addr = GET_LE16A( entry ); + + m.t_adsr0 = VREG(v->regs,adsr0); + + // Read pitch, spread over two clocks + m.t_pitch = VREG(v->regs,pitchl); +} +inline VOICE_CLOCK( V3a ) +{ + m.t_pitch += (VREG(v->regs,pitchh) & 0x3F) << 8; +} +inline VOICE_CLOCK( V3b ) +{ + // Read BRR header and byte + m.t_brr_byte = m.ram [(v->brr_addr + v->brr_offset) & 0xFFFF]; + m.t_brr_header = m.ram [v->brr_addr]; // brr_addr doesn't need masking +} +VOICE_CLOCK( V3c ) +{ + // Pitch modulation using previous voice's output + if ( m.t_pmon & v->vbit ) + m.t_pitch += ((m.t_output >> 5) * m.t_pitch) >> 10; + + if ( v->kon_delay ) + { + // Get ready to start BRR decoding on next sample + if ( v->kon_delay == 5 ) + { + v->brr_addr = m.t_brr_next_addr; + v->brr_offset = 1; + v->buf_pos = 0; + m.t_brr_header = 0; // header is ignored on this sample + m.kon_check = true; + + if (take_spc_snapshot) + { + take_spc_snapshot = 0; + if (spc_snapshot_callback) + spc_snapshot_callback(); + } + } + + // Envelope is never run during KON + v->env = 0; + v->hidden_env = 0; + + // Disable BRR decoding until last three samples + v->interp_pos = 0; + if ( --v->kon_delay & 3 ) + v->interp_pos = 0x4000; + + // Pitch is never added during KON + m.t_pitch = 0; + } + + // Gaussian interpolation + { + int output = interpolate( v ); + + // Noise + if ( m.t_non & v->vbit ) + output = (int16_t) (m.noise * 2); + + // Apply envelope + m.t_output = (output * v->env) >> 11 & ~1; + v->t_envx_out = (uint8_t) (v->env >> 4); + } + + // Immediate silence due to end of sample or soft reset + if ( REG(flg) & 0x80 || (m.t_brr_header & 3) == 1 ) + { + v->env_mode = env_release; + v->env = 0; + } + + if ( m.every_other_sample ) + { + // KOFF + if ( m.t_koff & v->vbit ) + v->env_mode = env_release; + + // KON + if ( m.kon & v->vbit ) + { + v->kon_delay = 5; + v->env_mode = env_attack; + } + } + + // Run envelope for next sample + if ( !v->kon_delay ) + run_envelope( v ); +} + +inline void SPC_DSP::voice_output( voice_t const* v, int ch ) +{ + // Apply left/right volume + int amp = (m.t_output * (int8_t) VREG(v->regs,voll + ch)) >> 7; + amp *= ((stereo_switch & (1 << (v->voice_number + ch * voice_count))) ? 1 : 0); + + // Add to output total + m.t_main_out [ch] += amp; + CLAMP16( m.t_main_out [ch] ); + + // Optionally add to echo total + if ( m.t_eon & v->vbit ) + { + m.t_echo_out [ch] += amp; + CLAMP16( m.t_echo_out [ch] ); + } +} +VOICE_CLOCK( V4 ) +{ + // Decode BRR + m.t_looped = 0; + if ( v->interp_pos >= 0x4000 ) + { + decode_brr( v ); + + if ( (v->brr_offset += 2) >= brr_block_size ) + { + // Start decoding next BRR block + assert( v->brr_offset == brr_block_size ); + v->brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF; + if ( m.t_brr_header & 1 ) + { + v->brr_addr = m.t_brr_next_addr; + m.t_looped = v->vbit; + } + v->brr_offset = 1; + } + } + + // Apply pitch + v->interp_pos = (v->interp_pos & 0x3FFF) + m.t_pitch; + + // Keep from getting too far ahead (when using pitch modulation) + if ( v->interp_pos > 0x7FFF ) + v->interp_pos = 0x7FFF; + + // Output left + voice_output( v, 0 ); +} +inline VOICE_CLOCK( V5 ) +{ + // Output right + voice_output( v, 1 ); + + // ENDX, OUTX, and ENVX won't update if you wrote to them 1-2 clocks earlier + int endx_buf = REG(endx) | m.t_looped; + + // Clear bit in ENDX if KON just began + if ( v->kon_delay == 5 ) + endx_buf &= ~v->vbit; + m.endx_buf = (uint8_t) endx_buf; +} +inline VOICE_CLOCK( V6 ) +{ + (void) v; // avoid compiler warning about unused v + m.outx_buf = (uint8_t) (m.t_output >> 8); +} +inline VOICE_CLOCK( V7 ) +{ + // Update ENDX + REG(endx) = m.endx_buf; + + m.envx_buf = v->t_envx_out; +} +inline VOICE_CLOCK( V8 ) +{ + // Update OUTX + VREG(v->regs,outx) = m.outx_buf; +} +inline VOICE_CLOCK( V9 ) +{ + // Update ENVX + VREG(v->regs,envx) = m.envx_buf; +} + +// Most voices do all these in one clock, so make a handy composite +inline VOICE_CLOCK( V3 ) +{ + voice_V3a( v ); + voice_V3b( v ); + voice_V3c( v ); +} + +// Common combinations of voice steps on different voices. This greatly reduces +// code size and allows everything to be inlined in these functions. +VOICE_CLOCK(V7_V4_V1) { voice_V7(v); voice_V1(v+3); voice_V4(v+1); } +VOICE_CLOCK(V8_V5_V2) { voice_V8(v); voice_V5(v+1); voice_V2(v+2); } +VOICE_CLOCK(V9_V6_V3) { voice_V9(v); voice_V6(v+1); voice_V3(v+2); } + + +//// Echo + +// Current echo buffer pointer for left/right channel +#define ECHO_PTR( ch ) (&m.ram [m.t_echo_ptr + ch * 2]) + +// Sample in echo history buffer, where 0 is the oldest +#define ECHO_FIR( i ) (m.echo_hist_pos [i]) + +// Calculate FIR point for left/right channel +#define CALC_FIR( i, ch ) ((ECHO_FIR( i + 1 ) [ch] * (int8_t) REG(fir + i * 0x10)) >> 6) + +#define ECHO_CLOCK( n ) inline void SPC_DSP::echo_##n() + +inline void SPC_DSP::echo_read( int ch ) +{ + int s; + if ( m.t_echo_ptr >= 0xffc0 && rom_enabled ) + s = GET_LE16SA( &hi_ram [m.t_echo_ptr + ch * 2 - 0xffc0] ); + else + s = GET_LE16SA( ECHO_PTR( ch ) ); + // second copy simplifies wrap-around handling + ECHO_FIR( 0 ) [ch] = ECHO_FIR( 8 ) [ch] = s >> 1; +} + +ECHO_CLOCK( 22 ) +{ + // History + if ( ++m.echo_hist_pos >= &m.echo_hist [echo_hist_size] ) + m.echo_hist_pos = m.echo_hist; + + m.t_echo_ptr = (m.t_esa * 0x100 + m.echo_offset) & 0xFFFF; + echo_read( 0 ); + + // FIR (using l and r temporaries below helps compiler optimize) + int l = CALC_FIR( 0, 0 ); + int r = CALC_FIR( 0, 1 ); + + m.t_echo_in [0] = l; + m.t_echo_in [1] = r; +} +ECHO_CLOCK( 23 ) +{ + int l = CALC_FIR( 1, 0 ) + CALC_FIR( 2, 0 ); + int r = CALC_FIR( 1, 1 ) + CALC_FIR( 2, 1 ); + + m.t_echo_in [0] += l; + m.t_echo_in [1] += r; + + echo_read( 1 ); +} +ECHO_CLOCK( 24 ) +{ + int l = CALC_FIR( 3, 0 ) + CALC_FIR( 4, 0 ) + CALC_FIR( 5, 0 ); + int r = CALC_FIR( 3, 1 ) + CALC_FIR( 4, 1 ) + CALC_FIR( 5, 1 ); + + m.t_echo_in [0] += l; + m.t_echo_in [1] += r; +} +ECHO_CLOCK( 25 ) +{ + int l = m.t_echo_in [0] + CALC_FIR( 6, 0 ); + int r = m.t_echo_in [1] + CALC_FIR( 6, 1 ); + + l = (int16_t) l; + r = (int16_t) r; + + l += (int16_t) CALC_FIR( 7, 0 ); + r += (int16_t) CALC_FIR( 7, 1 ); + + CLAMP16( l ); + CLAMP16( r ); + + m.t_echo_in [0] = l & ~1; + m.t_echo_in [1] = r & ~1; +} +inline int SPC_DSP::echo_output( int ch ) +{ + int out = (int16_t) ((m.t_main_out [ch] * (int8_t) REG(mvoll + ch * 0x10)) >> 7) + + (int16_t) ((m.t_echo_in [ch] * (int8_t) REG(evoll + ch * 0x10)) >> 7); + CLAMP16( out ); + return out; +} +ECHO_CLOCK( 26 ) +{ + // Left output volumes + // (save sample for next clock so we can output both together) + m.t_main_out [0] = echo_output( 0 ); + + // Echo feedback + int l = m.t_echo_out [0] + (int16_t) ((m.t_echo_in [0] * (int8_t) REG(efb)) >> 7); + int r = m.t_echo_out [1] + (int16_t) ((m.t_echo_in [1] * (int8_t) REG(efb)) >> 7); + + CLAMP16( l ); + CLAMP16( r ); + + m.t_echo_out [0] = l & ~1; + m.t_echo_out [1] = r & ~1; +} +ECHO_CLOCK( 27 ) +{ + // Output + int l = m.t_main_out [0]; + int r = echo_output( 1 ); + m.t_main_out [0] = 0; + m.t_main_out [1] = 0; + + // TODO: global muting isn't this simple (turns DAC on and off + // or something, causing small ~37-sample pulse when first muted) + if ( REG(flg) & 0x40 ) + { + l = 0; + r = 0; + } + + // Output sample to DAC + #ifdef SPC_DSP_OUT_HOOK + SPC_DSP_OUT_HOOK( l, r ); + #else + sample_t* out = m.out; + WRITE_SAMPLES( l, r, out ); + m.out = out; + #endif +} +ECHO_CLOCK( 28 ) +{ + m.t_echo_enabled = REG(flg); +} +inline void SPC_DSP::echo_write( int ch ) +{ + if ( !(m.t_echo_enabled & 0x20) ) + { + if ( m.t_echo_ptr >= 0xffc0 && rom_enabled ) + SET_LE16A( &hi_ram [m.t_echo_ptr + ch * 2 - 0xffc0], m.t_echo_out [ch] ); + else + SET_LE16A( ECHO_PTR( ch ), m.t_echo_out [ch] ); + } + + m.t_echo_out [ch] = 0; +} +ECHO_CLOCK( 29 ) +{ + m.t_esa = REG(esa); + + if ( !m.echo_offset ) + m.echo_length = (REG(edl) & 0x0F) * 0x800; + + m.echo_offset += 4; + if ( m.echo_offset >= m.echo_length ) + m.echo_offset = 0; + + // Write left echo + echo_write( 0 ); + + m.t_echo_enabled = REG(flg); +} +ECHO_CLOCK( 30 ) +{ + // Write right echo + echo_write( 1 ); +} + + +//// Timing + +// Execute clock for a particular voice +#define V( clock, voice ) voice_##clock( &m.voices [voice] ); + +/* The most common sequence of clocks uses composite operations +for efficiency. For example, the following are equivalent to the +individual steps on the right: + +V(V7_V4_V1,2) -> V(V7,2) V(V4,3) V(V1,5) +V(V8_V5_V2,2) -> V(V8,2) V(V5,3) V(V2,4) +V(V9_V6_V3,2) -> V(V9,2) V(V6,3) V(V3,4) */ + +// Voice 0 1 2 3 4 5 6 7 +#define GEN_DSP_TIMING \ +PHASE( 0) V(V5,0)V(V2,1)\ +PHASE( 1) V(V6,0)V(V3,1)\ +PHASE( 2) V(V7_V4_V1,0)\ +PHASE( 3) V(V8_V5_V2,0)\ +PHASE( 4) V(V9_V6_V3,0)\ +PHASE( 5) V(V7_V4_V1,1)\ +PHASE( 6) V(V8_V5_V2,1)\ +PHASE( 7) V(V9_V6_V3,1)\ +PHASE( 8) V(V7_V4_V1,2)\ +PHASE( 9) V(V8_V5_V2,2)\ +PHASE(10) V(V9_V6_V3,2)\ +PHASE(11) V(V7_V4_V1,3)\ +PHASE(12) V(V8_V5_V2,3)\ +PHASE(13) V(V9_V6_V3,3)\ +PHASE(14) V(V7_V4_V1,4)\ +PHASE(15) V(V8_V5_V2,4)\ +PHASE(16) V(V9_V6_V3,4)\ +PHASE(17) V(V1,0) V(V7,5)V(V4,6)\ +PHASE(18) V(V8_V5_V2,5)\ +PHASE(19) V(V9_V6_V3,5)\ +PHASE(20) V(V1,1) V(V7,6)V(V4,7)\ +PHASE(21) V(V8,6)V(V5,7) V(V2,0) /* t_brr_next_addr order dependency */\ +PHASE(22) V(V3a,0) V(V9,6)V(V6,7) echo_22();\ +PHASE(23) V(V7,7) echo_23();\ +PHASE(24) V(V8,7) echo_24();\ +PHASE(25) V(V3b,0) V(V9,7) echo_25();\ +PHASE(26) echo_26();\ +PHASE(27) misc_27(); echo_27();\ +PHASE(28) misc_28(); echo_28();\ +PHASE(29) misc_29(); echo_29();\ +PHASE(30) misc_30();V(V3c,0) echo_30();\ +PHASE(31) V(V4,0) V(V1,2)\ + +#if !SPC_DSP_CUSTOM_RUN + +void SPC_DSP::run( int clocks_remain ) +{ + require( clocks_remain > 0 ); + + int const phase = m.phase; + m.phase = (phase + clocks_remain) & 31; + switch ( phase ) + { + loop: + + #define PHASE( n ) if ( n && !--clocks_remain ) break; case n: + GEN_DSP_TIMING + #undef PHASE + + if ( --clocks_remain ) + goto loop; + } +} + +#endif + + +//// Setup + +void SPC_DSP::init( void* ram_64k ) +{ + m.ram = (uint8_t*) ram_64k; + mute_voices( 0 ); + disable_surround( false ); + set_output( 0, 0 ); + reset(); + + stereo_switch = 0xffff; + take_spc_snapshot = 0; + spc_snapshot_callback = 0; + + #ifndef NDEBUG + // be sure this sign-extends + assert( (int16_t) 0x8000 == -0x8000 ); + + // be sure right shift preserves sign + assert( (-1 >> 1) == -1 ); + + // check clamp macro + int i; + i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF ); + i = -0x8001; CLAMP16( i ); assert( i == -0x8000 ); + + blargg_verify_byte_order(); + #endif +} + +void SPC_DSP::soft_reset_common() +{ + require( m.ram ); // init() must have been called already + + m.noise = 0x4000; + m.echo_hist_pos = m.echo_hist; + m.every_other_sample = 1; + m.echo_offset = 0; + m.phase = 0; + + init_counter(); + + for (int i = 0; i < voice_count; i++) + m.voices[i].voice_number = i; +} + +void SPC_DSP::soft_reset() +{ + REG(flg) = 0xE0; + soft_reset_common(); +} + +void SPC_DSP::load( uint8_t const regs [register_count] ) +{ + memcpy( m.regs, regs, sizeof m.regs ); + memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count ); + + // Internal state + for ( int i = voice_count; --i >= 0; ) + { + voice_t* v = &m.voices [i]; + v->brr_offset = 1; + v->vbit = 1 << i; + v->regs = &m.regs [i * 0x10]; + } + m.new_kon = REG(kon); + m.t_dir = REG(dir); + m.t_esa = REG(esa); + + soft_reset_common(); +} + +void SPC_DSP::reset() { load( initial_regs ); } + + +//// State save/load + +#if !SPC_NO_COPY_STATE_FUNCS + +void SPC_State_Copier::copy( void* state, size_t size ) +{ + func( buf, state, size ); +} + +int SPC_State_Copier::copy_int( int state, int size ) +{ + BOOST::uint8_t s [2]; + SET_LE16( s, state ); + func( buf, &s, size ); + return GET_LE16( s ); +} + +void SPC_State_Copier::skip( int count ) +{ + if ( count > 0 ) + { + char temp [64]; + memset( temp, 0, sizeof temp ); + do + { + int n = sizeof temp; + if ( n > count ) + n = count; + count -= n; + func( buf, temp, n ); + } + while ( count ); + } +} + +void SPC_State_Copier::extra() +{ + int n = 0; + SPC_State_Copier& copier = *this; + SPC_COPY( uint8_t, n ); + skip( n ); +} + +void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy ) +{ + SPC_State_Copier copier( io, copy ); + + // DSP registers + copier.copy( m.regs, register_count ); + + // Internal state + + // Voices + int i; + for ( i = 0; i < voice_count; i++ ) + { + voice_t* v = &m.voices [i]; + + // BRR buffer + int i; + for ( i = 0; i < brr_buf_size; i++ ) + { + int s = v->buf [i]; + SPC_COPY( int16_t, s ); + v->buf [i] = v->buf [i + brr_buf_size] = s; + } + + SPC_COPY( uint16_t, v->interp_pos ); + SPC_COPY( uint16_t, v->brr_addr ); + SPC_COPY( uint16_t, v->env ); + SPC_COPY( int16_t, v->hidden_env ); + SPC_COPY( uint8_t, v->buf_pos ); + SPC_COPY( uint8_t, v->brr_offset ); + SPC_COPY( uint8_t, v->kon_delay ); + { + int m = v->env_mode; + SPC_COPY( uint8_t, m ); + v->env_mode = (enum env_mode_t) m; + } + SPC_COPY( uint8_t, v->t_envx_out ); + + copier.extra(); + } + + // Echo history + for ( i = 0; i < echo_hist_size; i++ ) + { + int j; + for ( j = 0; j < 2; j++ ) + { + int s = m.echo_hist_pos [i] [j]; + SPC_COPY( int16_t, s ); + m.echo_hist [i] [j] = s; // write back at offset 0 + } + } + m.echo_hist_pos = m.echo_hist; + memcpy( &m.echo_hist [echo_hist_size], m.echo_hist, echo_hist_size * sizeof m.echo_hist [0] ); + + // Misc + SPC_COPY( uint8_t, m.every_other_sample ); + SPC_COPY( uint8_t, m.kon ); + + SPC_COPY( uint16_t, m.noise ); + SPC_COPY( uint16_t, m.counter ); + SPC_COPY( uint16_t, m.echo_offset ); + SPC_COPY( uint16_t, m.echo_length ); + SPC_COPY( uint8_t, m.phase ); + + SPC_COPY( uint8_t, m.new_kon ); + SPC_COPY( uint8_t, m.endx_buf ); + SPC_COPY( uint8_t, m.envx_buf ); + SPC_COPY( uint8_t, m.outx_buf ); + + SPC_COPY( uint8_t, m.t_pmon ); + SPC_COPY( uint8_t, m.t_non ); + SPC_COPY( uint8_t, m.t_eon ); + SPC_COPY( uint8_t, m.t_dir ); + SPC_COPY( uint8_t, m.t_koff ); + + SPC_COPY( uint16_t, m.t_brr_next_addr ); + SPC_COPY( uint8_t, m.t_adsr0 ); + SPC_COPY( uint8_t, m.t_brr_header ); + SPC_COPY( uint8_t, m.t_brr_byte ); + SPC_COPY( uint8_t, m.t_srcn ); + SPC_COPY( uint8_t, m.t_esa ); + SPC_COPY( uint8_t, m.t_echo_enabled ); + + SPC_COPY( int16_t, m.t_main_out [0] ); + SPC_COPY( int16_t, m.t_main_out [1] ); + SPC_COPY( int16_t, m.t_echo_out [0] ); + SPC_COPY( int16_t, m.t_echo_out [1] ); + SPC_COPY( int16_t, m.t_echo_in [0] ); + SPC_COPY( int16_t, m.t_echo_in [1] ); + + SPC_COPY( uint16_t, m.t_dir_addr ); + SPC_COPY( uint16_t, m.t_pitch ); + SPC_COPY( int16_t, m.t_output ); + SPC_COPY( uint16_t, m.t_echo_ptr ); + SPC_COPY( uint8_t, m.t_looped ); + + copier.extra(); +} +#endif + + +//// Snes9x Accessor + +void SPC_DSP::set_spc_snapshot_callback( void (*callback) (void) ) +{ + spc_snapshot_callback = callback; +} + +void SPC_DSP::dump_spc_snapshot( void ) +{ + take_spc_snapshot = 1; +} + +void SPC_DSP::set_stereo_switch( int value ) +{ + stereo_switch = value; +} + +SPC_DSP::uint8_t SPC_DSP::reg_value( int ch, int addr ) +{ + return m.voices[ch].regs[addr]; +} + +int SPC_DSP::envx_value( int ch ) +{ + return m.voices[ch].env; +} diff --git a/apu/bapu/dsp/SPC_DSP.h b/apu/bapu/dsp/SPC_DSP.h new file mode 100755 index 00000000..61d05ab5 --- /dev/null +++ b/apu/bapu/dsp/SPC_DSP.h @@ -0,0 +1,319 @@ +// Highly accurate SNES SPC-700 DSP emulator + +// snes_spc 0.9.0 +#ifndef SPC_DSP_H +#define SPC_DSP_H + +#include "blargg_common.h" + +extern "C" { typedef void (*dsp_copy_func_t)( unsigned char** io, void* state, size_t ); } + +class SPC_DSP { +public: + typedef BOOST::uint8_t uint8_t; + +// Setup + + // Initializes DSP and has it use the 64K RAM provided + void init( void* ram_64k ); + + // Sets destination for output samples. If out is NULL or out_size is 0, + // doesn't generate any. + typedef short sample_t; + void set_output( sample_t* out, int out_size ); + + // Number of samples written to output since it was last set, always + // a multiple of 2. Undefined if more samples were generated than + // output buffer could hold. + int sample_count() const; + +// Emulation + + // Resets DSP to power-on state + void reset(); + + // Emulates pressing reset switch on SNES + void soft_reset(); + + // Reads/writes DSP registers. For accuracy, you must first call run() + // to catch the DSP up to present. + int read ( int addr ) const; + void write( int addr, int data ); + + // Runs DSP for specified number of clocks (~1024000 per second). Every 32 clocks + // a pair of samples is be generated. + void run( int clock_count ); + +// Sound control + + // Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events). + // Reduces emulation accuracy. + enum { voice_count = 8 }; + void mute_voices( int mask ); + +// State + + // Resets DSP and uses supplied values to initialize registers + enum { register_count = 128 }; + void load( uint8_t const regs [register_count] ); + + // Saves/loads exact emulator state + enum { state_size = 640 }; // maximum space needed when saving + typedef dsp_copy_func_t copy_func_t; + void copy_state( unsigned char** io, copy_func_t ); + + // Returns non-zero if new key-on events occurred since last call + bool check_kon(); + +// Snes9x Accessor + + int stereo_switch; + int take_spc_snapshot; + int rom_enabled; // mirror + uint8_t *rom, *hi_ram; // mirror + void (*spc_snapshot_callback) (void); + + void set_spc_snapshot_callback( void (*callback) (void) ); + void dump_spc_snapshot( void ); + void set_stereo_switch( int ); + uint8_t reg_value( int, int ); + int envx_value( int ); + +// DSP register addresses + + // Global registers + enum { + r_mvoll = 0x0C, r_mvolr = 0x1C, + r_evoll = 0x2C, r_evolr = 0x3C, + r_kon = 0x4C, r_koff = 0x5C, + r_flg = 0x6C, r_endx = 0x7C, + r_efb = 0x0D, r_pmon = 0x2D, + r_non = 0x3D, r_eon = 0x4D, + r_dir = 0x5D, r_esa = 0x6D, + r_edl = 0x7D, + r_fir = 0x0F // 8 coefficients at 0x0F, 0x1F ... 0x7F + }; + + // Voice registers + enum { + v_voll = 0x00, v_volr = 0x01, + v_pitchl = 0x02, v_pitchh = 0x03, + v_srcn = 0x04, v_adsr0 = 0x05, + v_adsr1 = 0x06, v_gain = 0x07, + v_envx = 0x08, v_outx = 0x09 + }; + +public: + enum { extra_size = 16 }; + sample_t* extra() { return m.extra; } + sample_t const* out_pos() const { return m.out; } + void disable_surround( bool ) { } // not supported +public: + BLARGG_DISABLE_NOTHROW + + typedef BOOST::int8_t int8_t; + typedef BOOST::int16_t int16_t; + + enum { echo_hist_size = 8 }; + + enum env_mode_t { env_release, env_attack, env_decay, env_sustain }; + enum { brr_buf_size = 12 }; + struct voice_t + { + int buf [brr_buf_size*2];// decoded samples (twice the size to simplify wrap handling) + int buf_pos; // place in buffer where next samples will be decoded + int interp_pos; // relative fractional position in sample (0x1000 = 1.0) + int brr_addr; // address of current BRR block + int brr_offset; // current decoding offset in BRR block + uint8_t* regs; // pointer to voice's DSP registers + int vbit; // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc. + int kon_delay; // KON delay/current setup phase + env_mode_t env_mode; + int env; // current envelope level + int hidden_env; // used by GAIN mode 7, very obscure quirk + uint8_t t_envx_out; + int voice_number; + }; +private: + enum { brr_block_size = 9 }; + + struct state_t + { + uint8_t regs [register_count]; + + // Echo history keeps most recent 8 samples (twice the size to simplify wrap handling) + int echo_hist [echo_hist_size * 2] [2]; + int (*echo_hist_pos) [2]; // &echo_hist [0 to 7] + + int every_other_sample; // toggles every sample + int kon; // KON value when last checked + int noise; + int counter; + int echo_offset; // offset from ESA in echo buffer + int echo_length; // number of bytes that echo_offset will stop at + int phase; // next clock cycle to run (0-31) + bool kon_check; // set when a new KON occurs + + // Hidden registers also written to when main register is written to + int new_kon; + uint8_t endx_buf; + uint8_t envx_buf; + uint8_t outx_buf; + + // Temporary state between clocks + + // read once per sample + int t_pmon; + int t_non; + int t_eon; + int t_dir; + int t_koff; + + // read a few clocks ahead then used + int t_brr_next_addr; + int t_adsr0; + int t_brr_header; + int t_brr_byte; + int t_srcn; + int t_esa; + int t_echo_enabled; + + // internal state that is recalculated every sample + int t_dir_addr; + int t_pitch; + int t_output; + int t_looped; + int t_echo_ptr; + + // left/right sums + int t_main_out [2]; + int t_echo_out [2]; + int t_echo_in [2]; + + voice_t voices [voice_count]; + + // non-emulation state + uint8_t* ram; // 64K shared RAM between DSP and SMP + int mute_mask; + sample_t* out; + sample_t* out_end; + sample_t* out_begin; + sample_t extra [extra_size]; + }; + state_t m; + + void init_counter(); + void run_counters(); + unsigned read_counter( int rate ); + + int interpolate( voice_t const* v ); + void run_envelope( voice_t* const v ); + void decode_brr( voice_t* v ); + + void misc_27(); + void misc_28(); + void misc_29(); + void misc_30(); + + void voice_output( voice_t const* v, int ch ); + void voice_V1( voice_t* const ); + void voice_V2( voice_t* const ); + void voice_V3( voice_t* const ); + void voice_V3a( voice_t* const ); + void voice_V3b( voice_t* const ); + void voice_V3c( voice_t* const ); + void voice_V4( voice_t* const ); + void voice_V5( voice_t* const ); + void voice_V6( voice_t* const ); + void voice_V7( voice_t* const ); + void voice_V8( voice_t* const ); + void voice_V9( voice_t* const ); + void voice_V7_V4_V1( voice_t* const ); + void voice_V8_V5_V2( voice_t* const ); + void voice_V9_V6_V3( voice_t* const ); + + void echo_read( int ch ); + int echo_output( int ch ); + void echo_write( int ch ); + void echo_22(); + void echo_23(); + void echo_24(); + void echo_25(); + void echo_26(); + void echo_27(); + void echo_28(); + void echo_29(); + void echo_30(); + + void soft_reset_common(); +}; + +#include + +inline int SPC_DSP::sample_count() const { return m.out - m.out_begin; } + +inline int SPC_DSP::read( int addr ) const +{ + assert( (unsigned) addr < register_count ); + return m.regs [addr]; +} + +inline void SPC_DSP::write( int addr, int data ) +{ + assert( (unsigned) addr < register_count ); + + m.regs [addr] = (uint8_t) data; + switch ( addr & 0x0F ) + { + case v_envx: + m.envx_buf = (uint8_t) data; + break; + + case v_outx: + m.outx_buf = (uint8_t) data; + break; + + case 0x0C: + if ( addr == r_kon ) + m.new_kon = (uint8_t) data; + + if ( addr == r_endx ) // always cleared, regardless of data written + { + m.endx_buf = 0; + m.regs [r_endx] = 0; + } + break; + } +} + +inline void SPC_DSP::mute_voices( int mask ) { m.mute_mask = mask; } + +inline bool SPC_DSP::check_kon() +{ + bool old = m.kon_check; + m.kon_check = 0; + return old; +} + +#if !SPC_NO_COPY_STATE_FUNCS + +class SPC_State_Copier { + SPC_DSP::copy_func_t func; + unsigned char** buf; +public: + SPC_State_Copier( unsigned char** p, SPC_DSP::copy_func_t f ) { func = f; buf = p; } + void copy( void* state, size_t size ); + int copy_int( int state, int size ); + void skip( int count ); + void extra(); +}; + +#define SPC_COPY( type, state )\ +{\ + state = (BOOST::type) copier.copy_int( state, sizeof (BOOST::type) );\ + assert( (BOOST::type) state == state );\ +} + +#endif + +#endif diff --git a/apu/bapu/dsp/blargg_common.h b/apu/bapu/dsp/blargg_common.h new file mode 100755 index 00000000..75edff39 --- /dev/null +++ b/apu/bapu/dsp/blargg_common.h @@ -0,0 +1,186 @@ +// Sets up common environment for Shay Green's libraries. +// To change configuration options, modify blargg_config.h, not this file. + +// snes_spc 0.9.0 +#ifndef BLARGG_COMMON_H +#define BLARGG_COMMON_H + +#include +#include +#include +#include + +#undef BLARGG_COMMON_H +// allow blargg_config.h to #include blargg_common.h +#include "blargg_config.h" +#ifndef BLARGG_COMMON_H +#define BLARGG_COMMON_H + +// BLARGG_RESTRICT: equivalent to restrict, where supported +#if defined (__GNUC__) || _MSC_VER >= 1100 + #define BLARGG_RESTRICT __restrict +#else + #define BLARGG_RESTRICT +#endif + +// STATIC_CAST(T,expr): Used in place of static_cast (expr) +#ifndef STATIC_CAST + #define STATIC_CAST(T,expr) ((T) (expr)) +#endif + +// blargg_err_t (0 on success, otherwise error string) +#ifndef blargg_err_t + typedef const char* blargg_err_t; +#endif + +// blargg_vector - very lightweight vector of POD types (no constructor/destructor) +template +class blargg_vector { + T* begin_; + size_t size_; +public: + blargg_vector() : begin_( 0 ), size_( 0 ) { } + ~blargg_vector() { free( begin_ ); } + size_t size() const { return size_; } + T* begin() const { return begin_; } + T* end() const { return begin_ + size_; } + blargg_err_t resize( size_t n ) + { + // TODO: blargg_common.cpp to hold this as an outline function, ugh + void* p = realloc( begin_, n * sizeof (T) ); + if ( p ) + begin_ = (T*) p; + else if ( n > size_ ) // realloc failure only a problem if expanding + return "Out of memory"; + size_ = n; + return 0; + } + void clear() { void* p = begin_; begin_ = 0; size_ = 0; free( p ); } + T& operator [] ( size_t n ) const + { + assert( n <= size_ ); // <= to allow past-the-end value + return begin_ [n]; + } +}; + +#ifndef BLARGG_DISABLE_NOTHROW + // throw spec mandatory in ISO C++ if operator new can return NULL + #if __cplusplus >= 199711 || defined (__GNUC__) + #define BLARGG_THROWS( spec ) throw spec + #else + #define BLARGG_THROWS( spec ) + #endif + #define BLARGG_DISABLE_NOTHROW \ + void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\ + void operator delete ( void* p ) { free( p ); } + #define BLARGG_NEW new +#else + #include + #define BLARGG_NEW new (std::nothrow) +#endif + +// BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant) +#define BLARGG_4CHAR( a, b, c, d ) \ + ((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF)) + +// BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0. +#ifndef BOOST_STATIC_ASSERT + #ifdef _MSC_VER + // MSVC6 (_MSC_VER < 1300) fails for use of __LINE__ when /Zl is specified + #define BOOST_STATIC_ASSERT( expr ) \ + void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] ) + #else + // Some other compilers fail when declaring same function multiple times in class, + // so differentiate them by line + #define BOOST_STATIC_ASSERT( expr ) \ + void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] ) + #endif +#endif + +// BLARGG_COMPILER_HAS_BOOL: If 0, provides bool support for old compiler. If 1, +// compiler is assumed to support bool. If undefined, availability is determined. +#ifndef BLARGG_COMPILER_HAS_BOOL + #if defined (__MWERKS__) + #if !__option(bool) + #define BLARGG_COMPILER_HAS_BOOL 0 + #endif + #elif defined (_MSC_VER) + #if _MSC_VER < 1100 + #define BLARGG_COMPILER_HAS_BOOL 0 + #endif + #elif defined (__GNUC__) + // supports bool + #elif __cplusplus < 199711 + #define BLARGG_COMPILER_HAS_BOOL 0 + #endif +#endif +#if defined (BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL + // If you get errors here, modify your blargg_config.h file + typedef int bool; + const bool true = 1; + const bool false = 0; +#endif + +// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough + +#if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF + typedef long blargg_long; +#else + typedef int blargg_long; +#endif + +#if UINT_MAX < 0xFFFFFFFF || ULONG_MAX == 0xFFFFFFFF + typedef unsigned long blargg_ulong; +#else + typedef unsigned blargg_ulong; +#endif + +// BOOST::int8_t etc. + +// HAVE_STDINT_H: If defined, use for int8_t etc. +#if defined (HAVE_STDINT_H) + #include + #define BOOST + +// HAVE_INTTYPES_H: If defined, use for int8_t etc. +#elif defined (HAVE_INTTYPES_H) + #include + #define BOOST + +#else + struct BOOST + { + #if UCHAR_MAX == 0xFF && SCHAR_MAX == 0x7F + typedef signed char int8_t; + typedef unsigned char uint8_t; + #else + // No suitable 8-bit type available + typedef struct see_blargg_common_h int8_t; + typedef struct see_blargg_common_h uint8_t; + #endif + + #if USHRT_MAX == 0xFFFF + typedef short int16_t; + typedef unsigned short uint16_t; + #else + // No suitable 16-bit type available + typedef struct see_blargg_common_h int16_t; + typedef struct see_blargg_common_h uint16_t; + #endif + + #if ULONG_MAX == 0xFFFFFFFF + typedef long int32_t; + typedef unsigned long uint32_t; + #elif UINT_MAX == 0xFFFFFFFF + typedef int int32_t; + typedef unsigned int uint32_t; + #else + // No suitable 32-bit type available + typedef struct see_blargg_common_h int32_t; + typedef struct see_blargg_common_h uint32_t; + #endif + }; +#endif + +#endif +#endif diff --git a/apu/bapu/dsp/blargg_config.h b/apu/bapu/dsp/blargg_config.h new file mode 100755 index 00000000..d85d2663 --- /dev/null +++ b/apu/bapu/dsp/blargg_config.h @@ -0,0 +1,24 @@ +// snes_spc 0.9.0 user configuration file. Don't replace when updating library. + +// snes_spc 0.9.0 +#ifndef BLARGG_CONFIG_H +#define BLARGG_CONFIG_H + +// Uncomment to disable debugging checks +#define NDEBUG 1 + +// Uncomment to enable platform-specific (and possibly non-portable) optimizations +//#define BLARGG_NONPORTABLE 1 + +// Uncomment if automatic byte-order determination doesn't work +//#define BLARGG_BIG_ENDIAN 1 + +// Uncomment if you get errors in the bool section of blargg_common.h +//#define BLARGG_COMPILER_HAS_BOOL 1 + +// Use standard config.h if present +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#endif diff --git a/apu/bapu/dsp/blargg_endian.h b/apu/bapu/dsp/blargg_endian.h new file mode 100755 index 00000000..f2daca64 --- /dev/null +++ b/apu/bapu/dsp/blargg_endian.h @@ -0,0 +1,185 @@ +// CPU Byte Order Utilities + +// snes_spc 0.9.0 +#ifndef BLARGG_ENDIAN +#define BLARGG_ENDIAN + +#include "blargg_common.h" + +// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16) +#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \ + defined (__x86_64__) || defined (__ia64__) || defined (__i386__) + #define BLARGG_CPU_X86 1 + #define BLARGG_CPU_CISC 1 +#endif + +#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc) + #define BLARGG_CPU_POWERPC 1 + #define BLARGG_CPU_RISC 1 +#endif + +// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only +// one may be #defined to 1. Only needed if something actually depends on byte order. +#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN) +#ifdef __GLIBC__ + // GCC handles this for us + #include + #if __BYTE_ORDER == __LITTLE_ENDIAN + #define BLARGG_LITTLE_ENDIAN 1 + #elif __BYTE_ORDER == __BIG_ENDIAN + #define BLARGG_BIG_ENDIAN 1 + #endif +#else + +#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \ + (defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234) + #define BLARGG_LITTLE_ENDIAN 1 +#endif + +#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \ + defined (__sparc__) || BLARGG_CPU_POWERPC || \ + (defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321) + #define BLARGG_BIG_ENDIAN 1 +#elif !defined (__mips__) + // No endian specified; assume little-endian, since it's most common + #define BLARGG_LITTLE_ENDIAN 1 +#endif +#endif +#endif + +#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN + #undef BLARGG_LITTLE_ENDIAN + #undef BLARGG_BIG_ENDIAN +#endif + +inline void blargg_verify_byte_order() +{ + #ifndef NDEBUG + #if BLARGG_BIG_ENDIAN + volatile int i = 1; + assert( *(volatile char*) &i == 0 ); + #elif BLARGG_LITTLE_ENDIAN + volatile int i = 1; + assert( *(volatile char*) &i != 0 ); + #endif + #endif +} + +inline unsigned get_le16( void const* p ) +{ + return (unsigned) ((unsigned char const*) p) [1] << 8 | + (unsigned) ((unsigned char const*) p) [0]; +} + +inline unsigned get_be16( void const* p ) +{ + return (unsigned) ((unsigned char const*) p) [0] << 8 | + (unsigned) ((unsigned char const*) p) [1]; +} + +inline blargg_ulong get_le32( void const* p ) +{ + return (blargg_ulong) ((unsigned char const*) p) [3] << 24 | + (blargg_ulong) ((unsigned char const*) p) [2] << 16 | + (blargg_ulong) ((unsigned char const*) p) [1] << 8 | + (blargg_ulong) ((unsigned char const*) p) [0]; +} + +inline blargg_ulong get_be32( void const* p ) +{ + return (blargg_ulong) ((unsigned char const*) p) [0] << 24 | + (blargg_ulong) ((unsigned char const*) p) [1] << 16 | + (blargg_ulong) ((unsigned char const*) p) [2] << 8 | + (blargg_ulong) ((unsigned char const*) p) [3]; +} + +inline void set_le16( void* p, unsigned n ) +{ + ((unsigned char*) p) [1] = (unsigned char) (n >> 8); + ((unsigned char*) p) [0] = (unsigned char) n; +} + +inline void set_be16( void* p, unsigned n ) +{ + ((unsigned char*) p) [0] = (unsigned char) (n >> 8); + ((unsigned char*) p) [1] = (unsigned char) n; +} + +inline void set_le32( void* p, blargg_ulong n ) +{ + ((unsigned char*) p) [0] = (unsigned char) n; + ((unsigned char*) p) [1] = (unsigned char) (n >> 8); + ((unsigned char*) p) [2] = (unsigned char) (n >> 16); + ((unsigned char*) p) [3] = (unsigned char) (n >> 24); +} + +inline void set_be32( void* p, blargg_ulong n ) +{ + ((unsigned char*) p) [3] = (unsigned char) n; + ((unsigned char*) p) [2] = (unsigned char) (n >> 8); + ((unsigned char*) p) [1] = (unsigned char) (n >> 16); + ((unsigned char*) p) [0] = (unsigned char) (n >> 24); +} + +#if BLARGG_NONPORTABLE + // Optimized implementation if byte order is known + #if BLARGG_LITTLE_ENDIAN + #define GET_LE16( addr ) (*(BOOST::uint16_t*) (addr)) + #define GET_LE32( addr ) (*(BOOST::uint32_t*) (addr)) + #define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) + #define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) + #elif BLARGG_BIG_ENDIAN + #define GET_BE16( addr ) (*(BOOST::uint16_t*) (addr)) + #define GET_BE32( addr ) (*(BOOST::uint32_t*) (addr)) + #define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) + #define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) + + #if BLARGG_CPU_POWERPC + // PowerPC has special byte-reversed instructions + #if defined (__MWERKS__) + #define GET_LE16( addr ) (__lhbrx( addr, 0 )) + #define GET_LE32( addr ) (__lwbrx( addr, 0 )) + #define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 )) + #define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 )) + #elif defined (__GNUC__) + #define GET_LE16( addr ) ({unsigned ppc_lhbrx_; asm( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr), "0" (ppc_lhbrx_) ); ppc_lhbrx_;}) + #define GET_LE32( addr ) ({unsigned ppc_lwbrx_; asm( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr), "0" (ppc_lwbrx_) ); ppc_lwbrx_;}) + #define SET_LE16( addr, in ) ({asm( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) );}) + #define SET_LE32( addr, in ) ({asm( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) );}) + #endif + #endif + #endif +#endif + +#ifndef GET_LE16 + #define GET_LE16( addr ) get_le16( addr ) + #define SET_LE16( addr, data ) set_le16( addr, data ) +#endif + +#ifndef GET_LE32 + #define GET_LE32( addr ) get_le32( addr ) + #define SET_LE32( addr, data ) set_le32( addr, data ) +#endif + +#ifndef GET_BE16 + #define GET_BE16( addr ) get_be16( addr ) + #define SET_BE16( addr, data ) set_be16( addr, data ) +#endif + +#ifndef GET_BE32 + #define GET_BE32( addr ) get_be32( addr ) + #define SET_BE32( addr, data ) set_be32( addr, data ) +#endif + +// auto-selecting versions + +inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); } +inline void set_le( BOOST::uint32_t* p, blargg_ulong n ) { SET_LE32( p, n ); } +inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); } +inline void set_be( BOOST::uint32_t* p, blargg_ulong n ) { SET_BE32( p, n ); } +inline unsigned get_le( BOOST::uint16_t* p ) { return GET_LE16( p ); } +inline blargg_ulong get_le( BOOST::uint32_t* p ) { return GET_LE32( p ); } +inline unsigned get_be( BOOST::uint16_t* p ) { return GET_BE16( p ); } +inline blargg_ulong get_be( BOOST::uint32_t* p ) { return GET_BE32( p ); } + +#endif diff --git a/apu/bapu/dsp/blargg_source.h b/apu/bapu/dsp/blargg_source.h new file mode 100755 index 00000000..5e45c4fb --- /dev/null +++ b/apu/bapu/dsp/blargg_source.h @@ -0,0 +1,100 @@ +/* Included at the beginning of library source files, after all other #include lines. +Sets up helpful macros and services used in my source code. They don't need +module an annoying module prefix on their names since they are defined after +all other #include lines. */ + +// snes_spc 0.9.0 +#ifndef BLARGG_SOURCE_H +#define BLARGG_SOURCE_H + +// If debugging is enabled, abort program if expr is false. Meant for checking +// internal state and consistency. A failed assertion indicates a bug in the module. +// void assert( bool expr ); +#include + +// If debugging is enabled and expr is false, abort program. Meant for checking +// caller-supplied parameters and operations that are outside the control of the +// module. A failed requirement indicates a bug outside the module. +// void require( bool expr ); +#undef require +#define require( expr ) assert( expr ) + +// Like printf() except output goes to debug log file. Might be defined to do +// nothing (not even evaluate its arguments). +// void dprintf( const char* format, ... ); +static inline void blargg_dprintf_( const char*, ... ) { } +#undef dprintf +#define dprintf (1) ? (void) 0 : blargg_dprintf_ + +// If enabled, evaluate expr and if false, make debug log entry with source file +// and line. Meant for finding situations that should be examined further, but that +// don't indicate a problem. In all cases, execution continues normally. +#undef check +#define check( expr ) ((void) 0) + +// If expr yields error string, return it from current function, otherwise continue. +#undef RETURN_ERR +#define RETURN_ERR( expr ) do { \ + blargg_err_t blargg_return_err_ = (expr); \ + if ( blargg_return_err_ ) return blargg_return_err_; \ + } while ( 0 ) + +// If ptr is 0, return out of memory error string. +#undef CHECK_ALLOC +#define CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 ) + +// Avoid any macros which evaluate their arguments multiple times +#undef min +#undef max + +#define DEF_MIN_MAX( type ) \ + static inline type min( type x, type y ) { if ( x < y ) return x; return y; }\ + static inline type max( type x, type y ) { if ( y < x ) return x; return y; } + +DEF_MIN_MAX( int ) +DEF_MIN_MAX( unsigned ) +DEF_MIN_MAX( long ) +DEF_MIN_MAX( unsigned long ) +DEF_MIN_MAX( float ) +DEF_MIN_MAX( double ) + +#undef DEF_MIN_MAX + +/* +// using const references generates crappy code, and I am currenly only using these +// for built-in types, so they take arguments by value + +// TODO: remove +inline int min( int x, int y ) +template +inline T min( T x, T y ) +{ + if ( x < y ) + return x; + return y; +} + +template +inline T max( T x, T y ) +{ + if ( x < y ) + return y; + return x; +} +*/ + +// TODO: good idea? bad idea? +#undef byte +#define byte byte_ +typedef unsigned char byte; + +// deprecated +#define BLARGG_CHECK_ALLOC CHECK_ALLOC +#define BLARGG_RETURN_ERR RETURN_ERR + +// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf and check +#ifdef BLARGG_SOURCE_BEGIN + #include BLARGG_SOURCE_BEGIN +#endif + +#endif diff --git a/apu/bapu/dsp/dsp.cpp b/apu/bapu/dsp/dsp.cpp new file mode 100755 index 00000000..f82bd824 --- /dev/null +++ b/apu/bapu/dsp/dsp.cpp @@ -0,0 +1,61 @@ +#include + +#define DSP_CPP +namespace SNES { + +DSP dsp; + +#include "SPC_DSP.cpp" + +void DSP::step(unsigned clocks) { + clock += clocks; +} + +void DSP::synchronize_smp() { + while(clock >= 0) smp.enter(); +} + +void DSP::enter() { + spc_dsp.run(1); + step(24); + +/* signed count = spc_dsp.sample_count(); + if(count > 0) { + for(unsigned n = 0; n < count; n += 2) audio.sample(samplebuffer[n + 0], samplebuffer[n + 1]); + spc_dsp.set_output(samplebuffer, 8192); + } */ +} + +uint8 DSP::read(uint8 addr) { + return spc_dsp.read(addr); +} + +void DSP::write(uint8 addr, uint8 data) { + spc_dsp.write(addr, data); +} + +void DSP::power() { + spc_dsp.init(smp.apuram); + spc_dsp.reset(); + spc_dsp.set_output(samplebuffer, 8192); +} + +void DSP::reset() { + spc_dsp.soft_reset(); + spc_dsp.set_output(samplebuffer, 8192); +} + +void DSP::channel_enable(unsigned channel, bool enable) { + channel_enabled[channel & 7] = enable; + unsigned mask = 0; + for(unsigned i = 0; i < 8; i++) { + if(channel_enabled[i] == false) mask |= 1 << i; + } + spc_dsp.mute_voices(mask); +} + +DSP::DSP() { + for(unsigned i = 0; i < 8; i++) channel_enabled[i] = true; +} + +} diff --git a/apu/bapu/dsp/dsp.hpp b/apu/bapu/dsp/dsp.hpp new file mode 100755 index 00000000..634c6da4 --- /dev/null +++ b/apu/bapu/dsp/dsp.hpp @@ -0,0 +1,26 @@ +#include "SPC_DSP.h" + +class DSP : public Processor { +public: + enum { Threaded = false }; + alwaysinline void step(unsigned clocks); + alwaysinline void synchronize_smp(); + + uint8 read(uint8 addr); + void write(uint8 addr, uint8 data); + + void enter(); + void power(); + void reset(); + + void channel_enable(unsigned channel, bool enable); + + DSP(); + +private: + SPC_DSP spc_dsp; + int16 samplebuffer[8192]; + bool channel_enabled[8]; +}; + +extern DSP dsp; diff --git a/apu/bapu/dsp/serialization.cpp b/apu/bapu/dsp/serialization.cpp new file mode 100755 index 00000000..0565a1b5 --- /dev/null +++ b/apu/bapu/dsp/serialization.cpp @@ -0,0 +1,31 @@ +#ifdef DSP_CPP + +static void dsp_state_save(unsigned char **out, void *in, size_t size) { + memcpy(*out, in, size); + *out += size; +} + +static void dsp_state_load(unsigned char **in, void *out, size_t size) { + memcpy(out, *in, size); + *in += size; +} + +void DSP::serialize(serializer &s) { + Processor::serialize(s); + s.array(samplebuffer); + + unsigned char state[SPC_DSP::state_size]; + unsigned char *p = state; + memset(&state, 0, SPC_DSP::state_size); + if(s.mode() == serializer::Save) { + spc_dsp.copy_state(&p, dsp_state_save); + s.array(state); + } else if(s.mode() == serializer::Load) { + s.array(state); + spc_dsp.copy_state(&p, dsp_state_load); + } else { + s.array(state); + } +} + +#endif diff --git a/apu/bapu/smp/algorithms.cpp b/apu/bapu/smp/algorithms.cpp new file mode 100755 index 00000000..a55369fb --- /dev/null +++ b/apu/bapu/smp/algorithms.cpp @@ -0,0 +1,122 @@ +uint8 SMP::op_adc(uint8 x, uint8 y) { + int r = x + y + regs.p.c; + regs.p.n = r & 0x80; + regs.p.v = ~(x ^ y) & (x ^ r) & 0x80; + regs.p.h = (x ^ y ^ r) & 0x10; + regs.p.z = (uint8)r == 0; + regs.p.c = r > 0xff; + return r; +} + +uint16 SMP::op_addw(uint16 x, uint16 y) { + uint16 r; + regs.p.c = 0; + r = op_adc(x, y); + r |= op_adc(x >> 8, y >> 8) << 8; + regs.p.z = r == 0; + return r; +} + +uint8 SMP::op_and(uint8 x, uint8 y) { + x &= y; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMP::op_cmp(uint8 x, uint8 y) { + int r = x - y; + regs.p.n = r & 0x80; + regs.p.z = (uint8)r == 0; + regs.p.c = r >= 0; + return x; +} + +uint16 SMP::op_cmpw(uint16 x, uint16 y) { + int r = x - y; + regs.p.n = r & 0x8000; + regs.p.z = (uint16)r == 0; + regs.p.c = r >= 0; + return x; +} + +uint8 SMP::op_eor(uint8 x, uint8 y) { + x ^= y; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMP::op_or(uint8 x, uint8 y) { + x |= y; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMP::op_sbc(uint8 x, uint8 y) { + int r = x - y - !regs.p.c; + regs.p.n = r & 0x80; + regs.p.v = (x ^ y) & (x ^ r) & 0x80; + regs.p.h = !((x ^ y ^ r) & 0x10); + regs.p.z = (uint8)r == 0; + regs.p.c = r >= 0; + return r; +} + +uint16 SMP::op_subw(uint16 x, uint16 y) { + uint16 r; + regs.p.c = 1; + r = op_sbc(x, y); + r |= op_sbc(x >> 8, y >> 8) << 8; + regs.p.z = r == 0; + return r; +} + +uint8 SMP::op_inc(uint8 x) { + x++; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMP::op_dec(uint8 x) { + x--; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMP::op_asl(uint8 x) { + regs.p.c = x & 0x80; + x <<= 1; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMP::op_lsr(uint8 x) { + regs.p.c = x & 0x01; + x >>= 1; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMP::op_rol(uint8 x) { + unsigned carry = (unsigned)regs.p.c; + regs.p.c = x & 0x80; + x = (x << 1) | carry; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMP::op_ror(uint8 x) { + unsigned carry = (unsigned)regs.p.c << 7; + regs.p.c = x & 0x01; + x = carry | (x >> 1); + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp new file mode 100755 index 00000000..6e0a29b2 --- /dev/null +++ b/apu/bapu/smp/core.cpp @@ -0,0 +1,105 @@ +void SMP::tick() { + timer0.tick(); + timer1.tick(); + timer2.tick(); + + clock += cycle_step_cpu; + dsp.clock -= 24; + synchronize_dsp(); +} + +void SMP::op_io() { + #if defined(CYCLE_ACCURATE) + tick(); + #endif +} + +uint8 SMP::op_read(uint16 addr) { + #if defined(CYCLE_ACCURATE) + tick(); + #endif + if((addr & 0xfff0) == 0x00f0) return mmio_read(addr); + if(addr >= 0xffc0 && status.iplrom_enable) return iplrom[addr & 0x3f]; + return apuram[addr]; +} + +void SMP::op_write(uint16 addr, uint8 data) { + #if defined(CYCLE_ACCURATE) + tick(); + #endif + if((addr & 0xfff0) == 0x00f0) mmio_write(addr, data); + apuram[addr] = data; //all writes go to RAM, even MMIO writes +} + +void SMP::op_step() { + #define op_readpc() op_read(regs.pc++) + #define op_readdp(addr) op_read((regs.p.p << 8) + addr) + #define op_writedp(addr, data) op_write((regs.p.p << 8) + addr, data) + #define op_readaddr(addr) op_read(addr) + #define op_writeaddr(addr, data) op_write(addr, data) + #define op_readstack() op_read(0x0100 | ++regs.sp) + #define op_writestack(data) op_write(0x0100 | regs.sp--, data) + static unsigned rd, wr, dp, sp, ya, bit; + + #if defined(CYCLE_ACCURATE) + + if(opcode_cycle == 0) { + opcode_number = op_readpc(); + opcode_cycle++; + } else switch(opcode_number) { + #include "core/opcycle_misc.cpp" + #include "core/opcycle_mov.cpp" + #include "core/opcycle_pc.cpp" + #include "core/opcycle_read.cpp" + #include "core/opcycle_rmw.cpp" + } + + #else + + unsigned opcode = op_readpc(); + switch(opcode) { + #include "core/op_misc.cpp" + #include "core/op_mov.cpp" + #include "core/op_pc.cpp" + #include "core/op_read.cpp" + #include "core/op_rmw.cpp" + } + + //TODO: untaken branches should consume less cycles + + timer0.tick(cycle_count_table[opcode]); + timer1.tick(cycle_count_table[opcode]); + timer2.tick(cycle_count_table[opcode]); + + clock += cycle_table_cpu[opcode]; + dsp.clock -= cycle_table_dsp[opcode]; + synchronize_dsp(); + + #endif +} + +const unsigned SMP::cycle_count_table[256] = { + #define c 12 +//0 1 2 3 4 5 6 7 8 9 A B C D E F + 2,8,4,7, 3,4,3,6, 2,6,5,4, 5,4,6,8, //0 + 4,8,4,7, 4,5,5,6, 5,5,6,5, 2,2,4,6, //1 + 2,8,4,7, 3,4,3,6, 2,6,5,4, 5,4,7,4, //2 + 4,8,4,7, 4,5,5,6, 5,5,6,5, 2,2,3,8, //3 + + 2,8,4,7, 3,4,3,6, 2,6,4,4, 5,4,6,6, //4 + 4,8,4,7, 4,5,5,6, 5,5,4,5, 2,2,4,3, //5 + 2,8,4,7, 3,4,3,6, 2,6,4,4, 5,4,7,5, //6 + 4,8,4,7, 4,5,5,6, 5,5,5,5, 2,2,3,6, //7 + + 2,8,4,7, 3,4,3,6, 2,6,5,4, 5,2,4,5, //8 + 4,8,4,7, 4,5,5,6, 5,5,5,5, 2,2,c,5, //9 + 3,8,4,7, 3,4,3,6, 2,6,4,4, 5,2,4,4, //A + 4,8,4,7, 4,5,5,6, 5,5,5,5, 2,2,3,4, //B + + 3,8,4,7, 4,5,4,7, 2,5,6,4, 5,2,4,9, //C + 4,8,4,7, 5,6,6,7, 4,5,5,5, 2,2,8,3, //D + 2,8,4,7, 3,4,3,6, 2,4,5,3, 4,3,4,1, //E + 4,8,4,7, 4,5,5,6, 3,4,5,4, 2,2,6,1, //F + + #undef c +}; diff --git a/apu/bapu/smp/core/cc.sh b/apu/bapu/smp/core/cc.sh new file mode 100755 index 00000000..937b7139 --- /dev/null +++ b/apu/bapu/smp/core/cc.sh @@ -0,0 +1 @@ +g++-4.5 -std=gnu++0x -I../../../.. -o generate generate.cpp diff --git a/apu/bapu/smp/core/generate.cpp b/apu/bapu/smp/core/generate.cpp new file mode 100755 index 00000000..77ab3ed2 --- /dev/null +++ b/apu/bapu/smp/core/generate.cpp @@ -0,0 +1,154 @@ +#include +#include +#include +using namespace nall; + +static bool cycle_accurate; + +struct opcode_t { + string name; + lstring args; + unsigned opcode; +}; + +void generate(const char *sourceFilename, const char *targetFilename) { + file fp; + fp.open(targetFilename, file::mode::write); + + string filedata; + filedata.readfile(sourceFilename); + filedata.replace("\r", ""); + + lstring block; + block.split("\n\n", filedata); + + foreach(data, block) { + lstring lines; + lines.split("\n", data); + + linear_vector array; + + unsigned sourceStart = 0; + foreach(line, lines, currentLine) { + line.transform("()", "``"); + lstring part; + part.split("`", line); + lstring arguments; + arguments.split(", ", part[1]); + + opcode_t opcode; + opcode.name = part[0]; + opcode.args = arguments; + opcode.opcode = hex(arguments[0]); + array.append(opcode); + + line.rtrim<1>(","); + if(line.endswith(" {")) { + line.rtrim<1>("{ "); + sourceStart = currentLine + 1; + break; + } + } + + if(cycle_accurate == false) { + foreach(opcode, array) { + fp.print("case 0x", hex<2>(opcode.opcode), ": {\n"); + + for(unsigned n = sourceStart; n < lines.size(); n++) { + if(lines[n] == "}") break; + + string output; + + if(lines[n].beginswith(" ")) { + output = lines[n]; + } else { + lstring part; + part.split<1>(":", lines[n]); + output = { " ", part[1] }; + } + + output.replace("$1", opcode.args[1]); + output.replace("$2", opcode.args[2]); + output.replace("$3", opcode.args[3]); + output.replace("$4", opcode.args[4]); + output.replace("$5", opcode.args[5]); + output.replace("$6", opcode.args[6]); + output.replace("$7", opcode.args[7]); + output.replace("$8", opcode.args[8]); + output.replace("end;", "break;"); + + fp.print(output, "\n"); + } + + fp.print(" break;\n"); + fp.print("}\n\n"); + } + } else { + foreach(opcode, array) { + fp.print("case 0x", hex<2>(opcode.opcode), ": {\n"); + fp.print(" switch(opcode_cycle++) {\n"); + + for(unsigned n = sourceStart; n < lines.size(); n++) { + if(lines[n] == "}") break; + + bool nextLineEndsCycle = false; + if(lines[n + 1] == "}") nextLineEndsCycle = true; + if(lines[n + 1].beginswith(" ") == false) nextLineEndsCycle = true; + + string output; + + if(lines[n].beginswith(" ")) { + output = { " ", lines[n] }; + } else { + lstring part; + part.split<1>(":", lines[n]); + fp.print(" case ", (unsigned)decimal(part[0]), ":\n"); + output = { " ", part[1] }; + } + + output.replace("$1", opcode.args[1]); + output.replace("$2", opcode.args[2]); + output.replace("$3", opcode.args[3]); + output.replace("$4", opcode.args[4]); + output.replace("$5", opcode.args[5]); + output.replace("$6", opcode.args[6]); + output.replace("$7", opcode.args[7]); + output.replace("$8", opcode.args[8]); + output.replace("end;", "{ opcode_cycle = 0; break; }"); + + fp.print(output, "\n"); + if(nextLineEndsCycle) { + if(lines[n + 1].beginswith("}")) { + fp.print(" opcode_cycle = 0;\n"); + } + fp.print(" break;\n"); + } + } + + fp.print(" }\n"); + fp.print(" break;\n"); + fp.print("}\n\n"); + } + } + } + + fp.close(); +} + +int main() { + cycle_accurate = false; + generate("op_misc.b", "op_misc.cpp"); + generate("op_mov.b", "op_mov.cpp" ); + generate("op_pc.b", "op_pc.cpp" ); + generate("op_read.b", "op_read.cpp"); + generate("op_rmw.b", "op_rmw.cpp" ); + + cycle_accurate = true; + generate("op_misc.b", "opcycle_misc.cpp"); + generate("op_mov.b", "opcycle_mov.cpp" ); + generate("op_pc.b", "opcycle_pc.cpp" ); + generate("op_read.b", "opcycle_read.cpp"); + generate("op_rmw.b", "opcycle_rmw.cpp" ); + + return 0; +} diff --git a/apu/bapu/smp/core/op_misc.b b/apu/bapu/smp/core/op_misc.b new file mode 100755 index 00000000..fb258650 --- /dev/null +++ b/apu/bapu/smp/core/op_misc.b @@ -0,0 +1,163 @@ +nop(0x00) { +1:op_io(); +} + +sleep(0xef), +stop(0xff) { +1:op_io(); +2:op_io(); + regs.pc--; +} + +xcn(0x9f) { +1:op_io(); +2:op_io(); +3:op_io(); +4:op_io(); + regs.a = (regs.a >> 4) | (regs.a << 4); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +daa(0xdf) { +1:op_io(); +2:op_io(); + if(regs.p.c || (regs.a) > 0x99) { + regs.a += 0x60; + regs.p.c = 1; + } + if(regs.p.h || (regs.a & 15) > 0x09) { + regs.a += 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +das(0xbe) { +1:op_io(); +2:op_io(); + if(!regs.p.c || (regs.a) > 0x99) { + regs.a -= 0x60; + regs.p.c = 0; + } + if(!regs.p.h || (regs.a & 15) > 0x09) { + regs.a -= 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +clrc(0x60, regs.p.c = 0), +clrp(0x20, regs.p.p = 0), +setc(0x80, regs.p.c = 1), +setp(0x40, regs.p.p = 1) { +1:op_io(); + $1; +} + +clrv(0xe0) { +1:op_io(); + regs.p.v = 0; + regs.p.h = 0; +} + +notc(0xed) { +1:op_io(); +2:op_io(); + regs.p.c = !regs.p.c; +} + +ei(0xa0, 1), +di(0xc0, 0) { +1:op_io(); +2:op_io(); + regs.p.i = $1; +} + +set0_dp(0x02, rd |= 0x01), +clr0_dp(0x12, rd &= ~0x01), +set1_dp(0x22, rd |= 0x02), +clr1_dp(0x32, rd &= ~0x02), +set2_dp(0x42, rd |= 0x04), +clr2_dp(0x52, rd &= ~0x04), +set3_dp(0x62, rd |= 0x08), +clr3_dp(0x72, rd &= ~0x08), +set4_dp(0x82, rd |= 0x10), +clr4_dp(0x92, rd &= ~0x10), +set5_dp(0xa2, rd |= 0x20), +clr5_dp(0xb2, rd &= ~0x20), +set6_dp(0xc2, rd |= 0x40), +clr6_dp(0xd2, rd &= ~0x40), +set7_dp(0xe2, rd |= 0x80), +clr7_dp(0xf2, rd &= ~0x80) { +1:dp = op_readpc(); +2:rd = op_readdp(dp); +3:$1; + op_writedp(dp, rd); +} + +push_a(0x2d, a), +push_x(0x4d, x), +push_y(0x6d, y), +push_p(0x0d, p) { +1:op_io(); +2:op_io(); +3:op_writestack(regs.$1); +} + +pop_a(0xae, a), +pop_x(0xce, x), +pop_y(0xee, y), +pop_p(0x8e, p) { +1:op_io(); +2:op_io(); +3:regs.$1 = op_readstack(); +} + +mul_ya(0xcf) { +1:op_io(); +2:op_io(); +3:op_io(); +4:op_io(); +5:op_io(); +6:op_io(); +7:op_io(); +8:op_io(); + ya = regs.y * regs.a; + regs.a = ya; + regs.y = ya >> 8; + //result is set based on y (high-byte) only + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); +} + +div_ya_x(0x9e) { +1:op_io(); +2:op_io(); +3:op_io(); +4:op_io(); +5:op_io(); +6:op_io(); +7:op_io(); +8:op_io(); +9:op_io(); +10:op_io(); +11:op_io(); + ya = regs.ya; + //overflow set if quotient >= 256 + regs.p.v = !!(regs.y >= regs.x); + regs.p.h = !!((regs.y & 15) >= (regs.x & 15)); + if(regs.y < (regs.x << 1)) { + //if quotient is <= 511 (will fit into 9-bit result) + regs.a = ya / regs.x; + regs.y = ya % regs.x; + } else { + //otherwise, the quotient won't fit into regs.p.v + regs.a + //this emulates the odd behavior of the S-SMP 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); +} diff --git a/apu/bapu/smp/core/op_misc.cpp b/apu/bapu/smp/core/op_misc.cpp new file mode 100755 index 00000000..9a6a062d --- /dev/null +++ b/apu/bapu/smp/core/op_misc.cpp @@ -0,0 +1,346 @@ +case 0x00: { + op_io(); + break; +} + +case 0xef: { + op_io(); + op_io(); + regs.pc--; + break; +} + +case 0xff: { + op_io(); + op_io(); + regs.pc--; + break; +} + +case 0x9f: { + op_io(); + op_io(); + op_io(); + op_io(); + regs.a = (regs.a >> 4) | (regs.a << 4); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xdf: { + op_io(); + op_io(); + if(regs.p.c || (regs.a) > 0x99) { + regs.a += 0x60; + regs.p.c = 1; + } + if(regs.p.h || (regs.a & 15) > 0x09) { + regs.a += 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xbe: { + op_io(); + op_io(); + if(!regs.p.c || (regs.a) > 0x99) { + regs.a -= 0x60; + regs.p.c = 0; + } + if(!regs.p.h || (regs.a & 15) > 0x09) { + regs.a -= 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0x60: { + op_io(); + regs.p.c = 0; + break; +} + +case 0x20: { + op_io(); + regs.p.p = 0; + break; +} + +case 0x80: { + op_io(); + regs.p.c = 1; + break; +} + +case 0x40: { + op_io(); + regs.p.p = 1; + break; +} + +case 0xe0: { + op_io(); + regs.p.v = 0; + regs.p.h = 0; + break; +} + +case 0xed: { + op_io(); + op_io(); + regs.p.c = !regs.p.c; + break; +} + +case 0xa0: { + op_io(); + op_io(); + regs.p.i = 1; + break; +} + +case 0xc0: { + op_io(); + op_io(); + regs.p.i = 0; + break; +} + +case 0x02: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x01; + op_writedp(dp, rd); + break; +} + +case 0x12: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x01; + op_writedp(dp, rd); + break; +} + +case 0x22: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x02; + op_writedp(dp, rd); + break; +} + +case 0x32: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x02; + op_writedp(dp, rd); + break; +} + +case 0x42: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x04; + op_writedp(dp, rd); + break; +} + +case 0x52: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x04; + op_writedp(dp, rd); + break; +} + +case 0x62: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x08; + op_writedp(dp, rd); + break; +} + +case 0x72: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x08; + op_writedp(dp, rd); + break; +} + +case 0x82: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x10; + op_writedp(dp, rd); + break; +} + +case 0x92: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x10; + op_writedp(dp, rd); + break; +} + +case 0xa2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x20; + op_writedp(dp, rd); + break; +} + +case 0xb2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x20; + op_writedp(dp, rd); + break; +} + +case 0xc2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x40; + op_writedp(dp, rd); + break; +} + +case 0xd2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x40; + op_writedp(dp, rd); + break; +} + +case 0xe2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x80; + op_writedp(dp, rd); + break; +} + +case 0xf2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x80; + op_writedp(dp, rd); + break; +} + +case 0x2d: { + op_io(); + op_io(); + op_writestack(regs.a); + break; +} + +case 0x4d: { + op_io(); + op_io(); + op_writestack(regs.x); + break; +} + +case 0x6d: { + op_io(); + op_io(); + op_writestack(regs.y); + break; +} + +case 0x0d: { + op_io(); + op_io(); + op_writestack(regs.p); + break; +} + +case 0xae: { + op_io(); + op_io(); + regs.a = op_readstack(); + break; +} + +case 0xce: { + op_io(); + op_io(); + regs.x = op_readstack(); + break; +} + +case 0xee: { + op_io(); + op_io(); + regs.y = op_readstack(); + break; +} + +case 0x8e: { + op_io(); + op_io(); + regs.p = op_readstack(); + break; +} + +case 0xcf: { + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + ya = regs.y * regs.a; + regs.a = ya; + regs.y = ya >> 8; + //result is set based on y (high-byte) only + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + break; +} + +case 0x9e: { + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + ya = regs.ya; + //overflow set if quotient >= 256 + regs.p.v = !!(regs.y >= regs.x); + regs.p.h = !!((regs.y & 15) >= (regs.x & 15)); + if(regs.y < (regs.x << 1)) { + //if quotient is <= 511 (will fit into 9-bit result) + regs.a = ya / regs.x; + regs.y = ya % regs.x; + } else { + //otherwise, the quotient won't fit into regs.p.v + regs.a + //this emulates the odd behavior of the S-SMP in this case + regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); + regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); + } + //result is set based on a (quotient) only + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + diff --git a/apu/bapu/smp/core/op_mov.b b/apu/bapu/smp/core/op_mov.b new file mode 100755 index 00000000..dee821af --- /dev/null +++ b/apu/bapu/smp/core/op_mov.b @@ -0,0 +1,217 @@ +mov_a_x(0x7d, a, x), +mov_a_y(0xdd, a, y), +mov_x_a(0x5d, x, a), +mov_y_a(0xfd, y, a), +mov_x_sp(0x9d, x, sp) { +1:op_io(); + regs.$1 = regs.$2; + regs.p.n = !!(regs.$1 & 0x80); + regs.p.z = (regs.$1 == 0); +} + +mov_sp_x(0xbd, sp, x) { +1:op_io(); + regs.$1 = regs.$2; +} + +mov_a_const(0xe8, a), +mov_x_const(0xcd, x), +mov_y_const(0x8d, y) { +1:regs.$1 = op_readpc(); + regs.p.n = !!(regs.$1 & 0x80); + regs.p.z = (regs.$1 == 0); +} + +mov_a_ix(0xe6) { +1:op_io(); +2:regs.a = op_readdp(regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_a_ixinc(0xbf) { +1:op_io(); +2:regs.a = op_readdp(regs.x++); +3:op_io(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_a_dp(0xe4, a), +mov_x_dp(0xf8, x), +mov_y_dp(0xeb, y) { +1:sp = op_readpc(); +2:regs.$1 = op_readdp(sp); + regs.p.n = !!(regs.$1 & 0x80); + regs.p.z = (regs.$1 == 0); +} + +mov_a_dpx(0xf4, a, x), +mov_x_dpy(0xf9, x, y), +mov_y_dpx(0xfb, y, x) { +1:sp = op_readpc(); +2:op_io(); +3:regs.$1 = op_readdp(sp + regs.$2); + regs.p.n = !!(regs.$1 & 0x80); + regs.p.z = (regs.$1 == 0); +} + +mov_a_addr(0xe5, a), +mov_x_addr(0xe9, x), +mov_y_addr(0xec, y) { +1:sp = op_readpc(); +2:sp |= op_readpc() << 8; +3:regs.$1 = op_readaddr(sp); + regs.p.n = !!(regs.$1 & 0x80); + regs.p.z = (regs.$1 == 0); +} + +mov_a_addrx(0xf5, x), +mov_a_addry(0xf6, y) { +1:sp = op_readpc(); +2:sp |= op_readpc() << 8; +3:op_io(); +4:regs.a = op_readaddr(sp + regs.$1); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_a_idpx(0xe7) { +1:dp = op_readpc() + regs.x; +2:op_io(); +3:sp = op_readdp(dp); +4:sp |= op_readdp(dp + 1) << 8; +5:regs.a = op_readaddr(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_a_idpy(0xf7) { +1:dp = op_readpc(); +2:op_io(); +3:sp = op_readdp(dp); +4:sp |= op_readdp(dp + 1) << 8; +5:regs.a = op_readaddr(sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_dp_dp(0xfa) { +1:sp = op_readpc(); +2:rd = op_readdp(sp); +3:dp = op_readpc(); +4:op_writedp(dp, rd); +} + +mov_dp_const(0x8f) { +1:rd = op_readpc(); +2:dp = op_readpc(); +3:op_readdp(dp); +4:op_writedp(dp, rd); +} + +mov_ix_a(0xc6) { +1:op_io(); +2:op_readdp(regs.x); +3:op_writedp(regs.x, regs.a); +} + +mov_ixinc_a(0xaf) { +1:op_io(); +2:op_io(); +3:op_writedp(regs.x++, regs.a); +} + +mov_dp_a(0xc4, a), +mov_dp_x(0xd8, x), +mov_dp_y(0xcb, y) { +1:dp = op_readpc(); +2:op_readdp(dp); +3:op_writedp(dp, regs.$1); +} + +mov_dpx_a(0xd4, x, a), +mov_dpy_x(0xd9, y, x), +mov_dpx_y(0xdb, x, y) { +1:dp = op_readpc(); +2:op_io(); + dp += regs.$1; +3:op_readdp(dp); +4:op_writedp(dp, regs.$2); +} + +mov_addr_a(0xc5, a), +mov_addr_x(0xc9, x), +mov_addr_y(0xcc, y) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:op_readaddr(dp); +4:op_writeaddr(dp, regs.$1); +} + +mov_addrx_a(0xd5, x), +mov_addry_a(0xd6, y) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:op_io(); + dp += regs.$1; +4:op_readaddr(dp); +5:op_writeaddr(dp, regs.a); +} + +mov_idpx_a(0xc7) { +1:sp = op_readpc(); +2:op_io(); + sp += regs.x; +3:dp = op_readdp(sp); +4:dp |= op_readdp(sp + 1) << 8; +5:op_readaddr(dp); +6:op_writeaddr(dp, regs.a); +} + +mov_idpy_a(0xd7) { +1:sp = op_readpc(); +2:dp = op_readdp(sp); +3:dp |= op_readdp(sp + 1) << 8; +4:op_io(); + dp += regs.y; +5:op_readaddr(dp); +6:op_writeaddr(dp, regs.a); +} + +movw_ya_dp(0xba) { +1:sp = op_readpc(); +2:regs.a = op_readdp(sp); +3:op_io(); +4:regs.y = op_readdp(sp + 1); + regs.p.n = !!(regs.ya & 0x8000); + regs.p.z = (regs.ya == 0); +} + +movw_dp_ya(0xda) { +1:dp = op_readpc(); +2:op_readdp(dp); +3:op_writedp(dp, regs.a); +4:op_writedp(dp + 1, regs.y); +} + +mov1_c_bit(0xaa) { +1:sp = op_readpc(); +2:sp |= op_readpc() << 8; +3:bit = sp >> 13; + sp &= 0x1fff; + rd = op_readaddr(sp); + regs.p.c = !!(rd & (1 << bit)); +} + +mov1_bit_c(0xca) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + if(regs.p.c)rd |= (1 << bit); + else rd &= ~(1 << bit); +4:op_io(); +5:op_writeaddr(dp, rd); +} diff --git a/apu/bapu/smp/core/op_mov.cpp b/apu/bapu/smp/core/op_mov.cpp new file mode 100755 index 00000000..f3079423 --- /dev/null +++ b/apu/bapu/smp/core/op_mov.cpp @@ -0,0 +1,389 @@ +case 0x7d: { + op_io(); + regs.a = regs.x; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xdd: { + op_io(); + regs.a = regs.y; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0x5d: { + op_io(); + regs.x = regs.a; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + break; +} + +case 0xfd: { + op_io(); + regs.y = regs.a; + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + break; +} + +case 0x9d: { + op_io(); + regs.x = regs.sp; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + break; +} + +case 0xbd: { + op_io(); + regs.sp = regs.x; + break; +} + +case 0xe8: { + regs.a = op_readpc(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xcd: { + regs.x = op_readpc(); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + break; +} + +case 0x8d: { + regs.y = op_readpc(); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + break; +} + +case 0xe6: { + op_io(); + regs.a = op_readdp(regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xbf: { + op_io(); + regs.a = op_readdp(regs.x++); + op_io(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xe4: { + sp = op_readpc(); + regs.a = op_readdp(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xf8: { + sp = op_readpc(); + regs.x = op_readdp(sp); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + break; +} + +case 0xeb: { + sp = op_readpc(); + regs.y = op_readdp(sp); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + break; +} + +case 0xf4: { + sp = op_readpc(); + op_io(); + regs.a = op_readdp(sp + regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xf9: { + sp = op_readpc(); + op_io(); + regs.x = op_readdp(sp + regs.y); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + break; +} + +case 0xfb: { + sp = op_readpc(); + op_io(); + regs.y = op_readdp(sp + regs.x); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + break; +} + +case 0xe5: { + sp = op_readpc(); + sp |= op_readpc() << 8; + regs.a = op_readaddr(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xe9: { + sp = op_readpc(); + sp |= op_readpc() << 8; + regs.x = op_readaddr(sp); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + break; +} + +case 0xec: { + sp = op_readpc(); + sp |= op_readpc() << 8; + regs.y = op_readaddr(sp); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + break; +} + +case 0xf5: { + sp = op_readpc(); + sp |= op_readpc() << 8; + op_io(); + regs.a = op_readaddr(sp + regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xf6: { + sp = op_readpc(); + sp |= op_readpc() << 8; + op_io(); + regs.a = op_readaddr(sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xe7: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + regs.a = op_readaddr(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xf7: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + regs.a = op_readaddr(sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xfa: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + op_writedp(dp, rd); + break; +} + +case 0x8f: { + rd = op_readpc(); + dp = op_readpc(); + op_readdp(dp); + op_writedp(dp, rd); + break; +} + +case 0xc6: { + op_io(); + op_readdp(regs.x); + op_writedp(regs.x, regs.a); + break; +} + +case 0xaf: { + op_io(); + op_io(); + op_writedp(regs.x++, regs.a); + break; +} + +case 0xc4: { + dp = op_readpc(); + op_readdp(dp); + op_writedp(dp, regs.a); + break; +} + +case 0xd8: { + dp = op_readpc(); + op_readdp(dp); + op_writedp(dp, regs.x); + break; +} + +case 0xcb: { + dp = op_readpc(); + op_readdp(dp); + op_writedp(dp, regs.y); + break; +} + +case 0xd4: { + dp = op_readpc(); + op_io(); + dp += regs.x; + op_readdp(dp); + op_writedp(dp, regs.a); + break; +} + +case 0xd9: { + dp = op_readpc(); + op_io(); + dp += regs.y; + op_readdp(dp); + op_writedp(dp, regs.x); + break; +} + +case 0xdb: { + dp = op_readpc(); + op_io(); + dp += regs.x; + op_readdp(dp); + op_writedp(dp, regs.y); + break; +} + +case 0xc5: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_readaddr(dp); + op_writeaddr(dp, regs.a); + break; +} + +case 0xc9: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_readaddr(dp); + op_writeaddr(dp, regs.x); + break; +} + +case 0xcc: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_readaddr(dp); + op_writeaddr(dp, regs.y); + break; +} + +case 0xd5: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + dp += regs.x; + op_readaddr(dp); + op_writeaddr(dp, regs.a); + break; +} + +case 0xd6: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + dp += regs.y; + op_readaddr(dp); + op_writeaddr(dp, regs.a); + break; +} + +case 0xc7: { + sp = op_readpc(); + op_io(); + sp += regs.x; + dp = op_readdp(sp); + dp |= op_readdp(sp + 1) << 8; + op_readaddr(dp); + op_writeaddr(dp, regs.a); + break; +} + +case 0xd7: { + sp = op_readpc(); + dp = op_readdp(sp); + dp |= op_readdp(sp + 1) << 8; + op_io(); + dp += regs.y; + op_readaddr(dp); + op_writeaddr(dp, regs.a); + break; +} + +case 0xba: { + sp = op_readpc(); + regs.a = op_readdp(sp); + op_io(); + regs.y = op_readdp(sp + 1); + regs.p.n = !!(regs.ya & 0x8000); + regs.p.z = (regs.ya == 0); + break; +} + +case 0xda: { + dp = op_readpc(); + op_readdp(dp); + op_writedp(dp, regs.a); + op_writedp(dp + 1, regs.y); + break; +} + +case 0xaa: { + sp = op_readpc(); + sp |= op_readpc() << 8; + bit = sp >> 13; + sp &= 0x1fff; + rd = op_readaddr(sp); + regs.p.c = !!(rd & (1 << bit)); + break; +} + +case 0xca: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + if(regs.p.c)rd |= (1 << bit); + else rd &= ~(1 << bit); + op_io(); + op_writeaddr(dp, rd); + break; +} + diff --git a/apu/bapu/smp/core/op_pc.b b/apu/bapu/smp/core/op_pc.b new file mode 100755 index 00000000..affaf844 --- /dev/null +++ b/apu/bapu/smp/core/op_pc.b @@ -0,0 +1,179 @@ +bra(0x2f, 0), +beq(0xf0, !regs.p.z), +bne(0xd0, regs.p.z), +bcs(0xb0, !regs.p.c), +bcc(0x90, regs.p.c), +bvs(0x70, !regs.p.v), +bvc(0x50, regs.p.v), +bmi(0x30, !regs.p.n), +bpl(0x10, regs.p.n) { +1:rd = op_readpc(); + if($1)end; +2:op_io(); +3:op_io(); + regs.pc += (int8)rd; +} + +bbs0(0x03, 0x01, !=), +bbc0(0x13, 0x01, ==), +bbs1(0x23, 0x02, !=), +bbc1(0x33, 0x02, ==), +bbs2(0x43, 0x04, !=), +bbc2(0x53, 0x04, ==), +bbs3(0x63, 0x08, !=), +bbc3(0x73, 0x08, ==), +bbs4(0x83, 0x10, !=), +bbc4(0x93, 0x10, ==), +bbs5(0xa3, 0x20, !=), +bbc5(0xb3, 0x20, ==), +bbs6(0xc3, 0x40, !=), +bbc6(0xd3, 0x40, ==), +bbs7(0xe3, 0x80, !=), +bbc7(0xf3, 0x80, ==) { +1:dp = op_readpc(); +2:sp = op_readdp(dp); +3:rd = op_readpc(); +4:op_io(); + if((sp & $1) $2 $1)end; +5:op_io(); +6:op_io(); + regs.pc += (int8)rd; +} + +cbne_dp(0x2e) { +1:dp = op_readpc(); +2:sp = op_readdp(dp); +3:rd = op_readpc(); +4:op_io(); + if(regs.a == sp)end; +5:op_io(); +6:op_io(); + regs.pc += (int8)rd; +} + +cbne_dpx(0xde) { +1:dp = op_readpc(); +2:op_io(); +3:sp = op_readdp(dp + regs.x); +4:rd = op_readpc(); +5:op_io(); + if(regs.a == sp)end; +6:op_io(); +7:op_io(); + regs.pc += (int8)rd; +} + +dbnz_dp(0x6e) { +1:dp = op_readpc(); +2:wr = op_readdp(dp); +3:op_writedp(dp, --wr); +4:rd = op_readpc(); + if(wr == 0x00)end; +5:op_io(); +6:op_io(); + regs.pc += (int8)rd; +} + +dbnz_y(0xfe) { +1:rd = op_readpc(); +2:op_io(); + regs.y--; +3:op_io(); + if(regs.y == 0x00)end; +4:op_io(); +5:op_io(); + regs.pc += (int8)rd; +} + +jmp_addr(0x5f) { +1:rd = op_readpc(); +2:rd |= op_readpc() << 8; + regs.pc = rd; +} + +jmp_iaddrx(0x1f) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:op_io(); + dp += regs.x; +4:rd = op_readaddr(dp); +5:rd |= op_readaddr(dp + 1) << 8; + regs.pc = rd; +} + +call(0x3f) { +1:rd = op_readpc(); +2:rd |= op_readpc() << 8; +3:op_io(); +4:op_io(); +5:op_io(); +6:op_writestack(regs.pc >> 8); +7:op_writestack(regs.pc); + regs.pc = rd; +} + +pcall(0x4f) { +1:rd = op_readpc(); +2:op_io(); +3:op_io(); +4:op_writestack(regs.pc >> 8); +5:op_writestack(regs.pc); + regs.pc = 0xff00 | rd; +} + +tcall_0(0x01, 0), +tcall_1(0x11, 1), +tcall_2(0x21, 2), +tcall_3(0x31, 3), +tcall_4(0x41, 4), +tcall_5(0x51, 5), +tcall_6(0x61, 6), +tcall_7(0x71, 7), +tcall_8(0x81, 8), +tcall_9(0x91, 9), +tcall_10(0xa1, 10), +tcall_11(0xb1, 11), +tcall_12(0xc1, 12), +tcall_13(0xd1, 13), +tcall_14(0xe1, 14), +tcall_15(0xf1, 15) { +1:dp = 0xffde - ($1 << 1); + rd = op_readaddr(dp); +2:rd |= op_readaddr(dp + 1) << 8; +3:op_io(); +4:op_io(); +5:op_io(); +6:op_writestack(regs.pc >> 8); +7:op_writestack(regs.pc); + regs.pc = rd; +} + +brk(0x0f) { +1:rd = op_readaddr(0xffde); +2:rd |= op_readaddr(0xffdf) << 8; +3:op_io(); +4:op_io(); +5:op_writestack(regs.pc >> 8); +6:op_writestack(regs.pc); +7:op_writestack(regs.p); + regs.pc = rd; + regs.p.b = 1; + regs.p.i = 0; +} + +ret(0x6f) { +1:rd = op_readstack(); +2:rd |= op_readstack() << 8; +3:op_io(); +4:op_io(); + regs.pc = rd; +} + +reti(0x7f) { +1:regs.p = op_readstack(); +2:rd = op_readstack(); +3:rd |= op_readstack() << 8; +4:op_io(); +5:op_io(); + regs.pc = rd; +} diff --git a/apu/bapu/smp/core/op_pc.cpp b/apu/bapu/smp/core/op_pc.cpp new file mode 100755 index 00000000..763a033e --- /dev/null +++ b/apu/bapu/smp/core/op_pc.cpp @@ -0,0 +1,603 @@ +case 0x2f: { + rd = op_readpc(); + if(0)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xf0: { + rd = op_readpc(); + if(!regs.p.z)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xd0: { + rd = op_readpc(); + if(regs.p.z)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xb0: { + rd = op_readpc(); + if(!regs.p.c)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x90: { + rd = op_readpc(); + if(regs.p.c)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x70: { + rd = op_readpc(); + if(!regs.p.v)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x50: { + rd = op_readpc(); + if(regs.p.v)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x30: { + rd = op_readpc(); + if(!regs.p.n)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x10: { + rd = op_readpc(); + if(regs.p.n)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x03: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x01) != 0x01)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x13: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x01) == 0x01)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x23: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x02) != 0x02)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x33: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x02) == 0x02)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x43: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x04) != 0x04)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x53: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x04) == 0x04)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x63: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x08) != 0x08)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x73: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x08) == 0x08)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x83: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x10) != 0x10)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x93: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x10) == 0x10)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xa3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x20) != 0x20)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xb3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x20) == 0x20)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xc3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x40) != 0x40)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xd3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x40) == 0x40)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xe3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x80) != 0x80)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xf3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x80) == 0x80)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x2e: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if(regs.a == sp)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xde: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp + regs.x); + rd = op_readpc(); + op_io(); + if(regs.a == sp)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x6e: { + dp = op_readpc(); + wr = op_readdp(dp); + op_writedp(dp, --wr); + rd = op_readpc(); + if(wr == 0x00)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xfe: { + rd = op_readpc(); + op_io(); + regs.y--; + op_io(); + if(regs.y == 0x00)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x5f: { + rd = op_readpc(); + rd |= op_readpc() << 8; + regs.pc = rd; + break; +} + +case 0x1f: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + dp += regs.x; + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + regs.pc = rd; + break; +} + +case 0x3f: { + rd = op_readpc(); + rd |= op_readpc() << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x4f: { + rd = op_readpc(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = 0xff00 | rd; + break; +} + +case 0x01: { + dp = 0xffde - (0 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x11: { + dp = 0xffde - (1 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x21: { + dp = 0xffde - (2 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x31: { + dp = 0xffde - (3 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x41: { + dp = 0xffde - (4 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x51: { + dp = 0xffde - (5 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x61: { + dp = 0xffde - (6 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x71: { + dp = 0xffde - (7 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x81: { + dp = 0xffde - (8 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x91: { + dp = 0xffde - (9 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xa1: { + dp = 0xffde - (10 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xb1: { + dp = 0xffde - (11 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xc1: { + dp = 0xffde - (12 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xd1: { + dp = 0xffde - (13 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xe1: { + dp = 0xffde - (14 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xf1: { + dp = 0xffde - (15 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x0f: { + rd = op_readaddr(0xffde); + rd |= op_readaddr(0xffdf) << 8; + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + op_writestack(regs.p); + regs.pc = rd; + regs.p.b = 1; + regs.p.i = 0; + break; +} + +case 0x6f: { + rd = op_readstack(); + rd |= op_readstack() << 8; + op_io(); + op_io(); + regs.pc = rd; + break; +} + +case 0x7f: { + regs.p = op_readstack(); + rd = op_readstack(); + rd |= op_readstack() << 8; + op_io(); + op_io(); + regs.pc = rd; + break; +} + diff --git a/apu/bapu/smp/core/op_read.b b/apu/bapu/smp/core/op_read.b new file mode 100755 index 00000000..fd2f9d82 --- /dev/null +++ b/apu/bapu/smp/core/op_read.b @@ -0,0 +1,205 @@ +adc_a_const(0x88, adc, a), +and_a_const(0x28, and, a), +cmp_a_const(0x68, cmp, a), +cmp_x_const(0xc8, cmp, x), +cmp_y_const(0xad, cmp, y), +eor_a_const(0x48, eor, a), +or_a_const(0x08, or, a), +sbc_a_const(0xa8, sbc, a) { +1:rd = op_readpc(); + regs.$2 = op_$1(regs.$2, rd); +} + +adc_a_ix(0x86, adc), +and_a_ix(0x26, and), +cmp_a_ix(0x66, cmp), +eor_a_ix(0x46, eor), +or_a_ix(0x06, or), +sbc_a_ix(0xa6, sbc) { +1:op_io(); +2:rd = op_readdp(regs.x); + regs.a = op_$1(regs.a, rd); +} + +adc_a_dp(0x84, adc, a), +and_a_dp(0x24, and, a), +cmp_a_dp(0x64, cmp, a), +cmp_x_dp(0x3e, cmp, x), +cmp_y_dp(0x7e, cmp, y), +eor_a_dp(0x44, eor, a), +or_a_dp(0x04, or, a), +sbc_a_dp(0xa4, sbc, a) { +1:dp = op_readpc(); +2:rd = op_readdp(dp); + regs.$2 = op_$1(regs.$2, rd); +} + +adc_a_dpx(0x94, adc), +and_a_dpx(0x34, and), +cmp_a_dpx(0x74, cmp), +eor_a_dpx(0x54, eor), +or_a_dpx(0x14, or), +sbc_a_dpx(0xb4, sbc) { +1:dp = op_readpc(); +2:op_io(); +3:rd = op_readdp(dp + regs.x); + regs.a = op_$1(regs.a, rd); +} + +adc_a_addr(0x85, adc, a), +and_a_addr(0x25, and, a), +cmp_a_addr(0x65, cmp, a), +cmp_x_addr(0x1e, cmp, x), +cmp_y_addr(0x5e, cmp, y), +eor_a_addr(0x45, eor, a), +or_a_addr(0x05, or, a), +sbc_a_addr(0xa5, sbc, a) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:rd = op_readaddr(dp); + regs.$2 = op_$1(regs.$2, rd); +} + +adc_a_addrx(0x95, adc, x), +adc_a_addry(0x96, adc, y), +and_a_addrx(0x35, and, x), +and_a_addry(0x36, and, y), +cmp_a_addrx(0x75, cmp, x), +cmp_a_addry(0x76, cmp, y), +eor_a_addrx(0x55, eor, x), +eor_a_addry(0x56, eor, y), +or_a_addrx(0x15, or, x), +or_a_addry(0x16, or, y), +sbc_a_addrx(0xb5, sbc, x), +sbc_a_addry(0xb6, sbc, y) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:op_io(); +4:rd = op_readaddr(dp + regs.$2); + regs.a = op_$1(regs.a, rd); +} + +adc_a_idpx(0x87, adc), +and_a_idpx(0x27, and), +cmp_a_idpx(0x67, cmp), +eor_a_idpx(0x47, eor), +or_a_idpx(0x07, or), +sbc_a_idpx(0xa7, sbc) { +1:dp = op_readpc() + regs.x; +2:op_io(); +3:sp = op_readdp(dp); +4:sp |= op_readdp(dp + 1) << 8; +5:rd = op_readaddr(sp); + regs.a = op_$1(regs.a, rd); +} + +adc_a_idpy(0x97, adc), +and_a_idpy(0x37, and), +cmp_a_idpy(0x77, cmp), +eor_a_idpy(0x57, eor), +or_a_idpy(0x17, or), +sbc_a_idpy(0xb7, sbc) { +1:dp = op_readpc(); +2:op_io(); +3:sp = op_readdp(dp); +4:sp |= op_readdp(dp + 1) << 8; +5:rd = op_readaddr(sp + regs.y); + regs.a = op_$1(regs.a, rd); +} + +adc_ix_iy(0x99, adc, 1), +and_ix_iy(0x39, and, 1), +cmp_ix_iy(0x79, cmp, 0), +eor_ix_iy(0x59, eor, 1), +or_ix_iy(0x19, or, 1), +sbc_ix_iy(0xb9, sbc, 1) { +1:op_io(); +2:rd = op_readdp(regs.y); +3:wr = op_readdp(regs.x); + wr = op_$1(wr, rd); +4:($2) ? op_writedp(regs.x, wr) : op_io(); +} + +adc_dp_dp(0x89, adc, 1), +and_dp_dp(0x29, and, 1), +cmp_dp_dp(0x69, cmp, 0), +eor_dp_dp(0x49, eor, 1), +or_dp_dp(0x09, or, 1), +sbc_dp_dp(0xa9, sbc, 1) { +1:sp = op_readpc(); +2:rd = op_readdp(sp); +3:dp = op_readpc(); +4:wr = op_readdp(dp); +5:wr = op_$1(wr, rd); + ($2) ? op_writedp(dp, wr) : op_io(); +} + +adc_dp_const(0x98, adc, 1), +and_dp_const(0x38, and, 1), +cmp_dp_const(0x78, cmp, 0), +eor_dp_const(0x58, eor, 1), +or_dp_const(0x18, or, 1), +sbc_dp_const(0xb8, sbc, 1) { +1:rd = op_readpc(); +2:dp = op_readpc(); +3:wr = op_readdp(dp); +4:wr = op_$1(wr, rd); + ($2) ? op_writedp(dp, wr) : op_io(); +} + +addw_ya_dp(0x7a, addw), +subw_ya_dp(0x9a, subw) { +1:dp = op_readpc(); +2:rd = op_readdp(dp); +3:op_io(); +4:rd |= op_readdp(dp + 1) << 8; + regs.ya = op_$1(regs.ya, rd); +} + +cmpw_ya_dp(0x5a) { +1:dp = op_readpc(); +2:rd = op_readdp(dp); +3:rd |= op_readdp(dp + 1) << 8; + op_cmpw(regs.ya, rd); +} + +and1_bit(0x4a, !!), +and1_notbit(0x6a, !) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & $1(rd & (1 << bit)); +} + +eor1_bit(0x8a) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); +4:op_io(); + regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); +} + +not1_bit(0xea) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + rd ^= (1 << bit); +4:op_writeaddr(dp, rd); +} + +or1_bit(0x0a, !!), +or1_notbit(0x2a, !) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); +4:op_io(); + regs.p.c = regs.p.c | $1(rd & (1 << bit)); +} diff --git a/apu/bapu/smp/core/op_read.cpp b/apu/bapu/smp/core/op_read.cpp new file mode 100755 index 00000000..2a16a3c8 --- /dev/null +++ b/apu/bapu/smp/core/op_read.cpp @@ -0,0 +1,744 @@ +case 0x88: { + rd = op_readpc(); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x28: { + rd = op_readpc(); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x68: { + rd = op_readpc(); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0xc8: { + rd = op_readpc(); + regs.x = op_cmp(regs.x, rd); + break; +} + +case 0xad: { + rd = op_readpc(); + regs.y = op_cmp(regs.y, rd); + break; +} + +case 0x48: { + rd = op_readpc(); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x08: { + rd = op_readpc(); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa8: { + rd = op_readpc(); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x86: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x26: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x66: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x46: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x06: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa6: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x84: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x24: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x64: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x3e: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.x = op_cmp(regs.x, rd); + break; +} + +case 0x7e: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.y = op_cmp(regs.y, rd); + break; +} + +case 0x44: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x04: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa4: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x94: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x34: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x74: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x54: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x14: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xb4: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x85: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x25: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x65: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x1e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.x = op_cmp(regs.x, rd); + break; +} + +case 0x5e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.y = op_cmp(regs.y, rd); + break; +} + +case 0x45: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x05: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa5: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x95: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x96: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x35: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x36: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x75: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x76: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x55: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x56: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x15: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_or(regs.a, rd); + break; +} + +case 0x16: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xb5: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0xb6: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x87: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x27: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x67: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x47: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x07: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa7: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x97: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x37: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x77: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x57: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x17: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xb7: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x99: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_adc(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x39: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_and(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x79: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_cmp(wr, rd); + (0) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x59: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_eor(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x19: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_or(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0xb9: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_sbc(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x89: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x29: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x69: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x49: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x09: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0xa9: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x98: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x38: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x78: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x58: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x18: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0xb8: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x7a: { + dp = op_readpc(); + rd = op_readdp(dp); + op_io(); + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_addw(regs.ya, rd); + break; +} + +case 0x9a: { + dp = op_readpc(); + rd = op_readdp(dp); + op_io(); + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_subw(regs.ya, rd); + break; +} + +case 0x5a: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= op_readdp(dp + 1) << 8; + op_cmpw(regs.ya, rd); + break; +} + +case 0x4a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !!(rd & (1 << bit)); + break; +} + +case 0x6a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !(rd & (1 << bit)); + break; +} + +case 0x8a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); + break; +} + +case 0xea: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + rd ^= (1 << bit); + op_writeaddr(dp, rd); + break; +} + +case 0x0a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c | !!(rd & (1 << bit)); + break; +} + +case 0x2a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c | !(rd & (1 << bit)); + break; +} + diff --git a/apu/bapu/smp/core/op_rmw.b b/apu/bapu/smp/core/op_rmw.b new file mode 100755 index 00000000..425574e8 --- /dev/null +++ b/apu/bapu/smp/core/op_rmw.b @@ -0,0 +1,74 @@ +inc_a(0xbc, inc, a), +inc_x(0x3d, inc, x), +inc_y(0xfc, inc, y), +dec_a(0x9c, dec, a), +dec_x(0x1d, dec, x), +dec_y(0xdc, dec, y), +asl_a(0x1c, asl, a), +lsr_a(0x5c, lsr, a), +rol_a(0x3c, rol, a), +ror_a(0x7c, ror, a) { +1:op_io(); + regs.$2 = op_$1(regs.$2); +} + +inc_dp(0xab, inc), +dec_dp(0x8b, dec), +asl_dp(0x0b, asl), +lsr_dp(0x4b, lsr), +rol_dp(0x2b, rol), +ror_dp(0x6b, ror) { +1:dp = op_readpc(); +2:rd = op_readdp(dp); +3:rd = op_$1(rd); + op_writedp(dp, rd); +} + +inc_dpx(0xbb, inc), +dec_dpx(0x9b, dec), +asl_dpx(0x1b, asl), +lsr_dpx(0x5b, lsr), +rol_dpx(0x3b, rol), +ror_dpx(0x7b, ror) { +1:dp = op_readpc(); +2:op_io(); +3:rd = op_readdp(dp + regs.x); +4:rd = op_$1(rd); + op_writedp(dp + regs.x, rd); +} + +inc_addr(0xac, inc), +dec_addr(0x8c, dec), +asl_addr(0x0c, asl), +lsr_addr(0x4c, lsr), +rol_addr(0x2c, rol), +ror_addr(0x6c, ror) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:rd = op_readaddr(dp); +4:rd = op_$1(rd); + op_writeaddr(dp, rd); +} + +tset_addr_a(0x0e, |), +tclr_addr_a(0x4e, &~) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); +4:op_readaddr(dp); +5:op_writeaddr(dp, rd $1 regs.a); +} + +incw_dp(0x3a, ++), +decw_dp(0x1a, --) { +1:dp = op_readpc(); +2:rd = op_readdp(dp); + rd$1; +3:op_writedp(dp++, rd); +4:rd += op_readdp(dp) << 8; +5:op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); +} diff --git a/apu/bapu/smp/core/op_rmw.cpp b/apu/bapu/smp/core/op_rmw.cpp new file mode 100755 index 00000000..f89ecacf --- /dev/null +++ b/apu/bapu/smp/core/op_rmw.cpp @@ -0,0 +1,262 @@ +case 0xbc: { + op_io(); + regs.a = op_inc(regs.a); + break; +} + +case 0x3d: { + op_io(); + regs.x = op_inc(regs.x); + break; +} + +case 0xfc: { + op_io(); + regs.y = op_inc(regs.y); + break; +} + +case 0x9c: { + op_io(); + regs.a = op_dec(regs.a); + break; +} + +case 0x1d: { + op_io(); + regs.x = op_dec(regs.x); + break; +} + +case 0xdc: { + op_io(); + regs.y = op_dec(regs.y); + break; +} + +case 0x1c: { + op_io(); + regs.a = op_asl(regs.a); + break; +} + +case 0x5c: { + op_io(); + regs.a = op_lsr(regs.a); + break; +} + +case 0x3c: { + op_io(); + regs.a = op_rol(regs.a); + break; +} + +case 0x7c: { + op_io(); + regs.a = op_ror(regs.a); + break; +} + +case 0xab: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_inc(rd); + op_writedp(dp, rd); + break; +} + +case 0x8b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_dec(rd); + op_writedp(dp, rd); + break; +} + +case 0x0b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_asl(rd); + op_writedp(dp, rd); + break; +} + +case 0x4b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_lsr(rd); + op_writedp(dp, rd); + break; +} + +case 0x2b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_rol(rd); + op_writedp(dp, rd); + break; +} + +case 0x6b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_ror(rd); + op_writedp(dp, rd); + break; +} + +case 0xbb: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_inc(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x9b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_dec(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x1b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_asl(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x5b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_lsr(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x3b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_rol(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x7b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_ror(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0xac: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_inc(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x8c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_dec(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x0c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_asl(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x4c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_lsr(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x2c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_rol(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x6c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_ror(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x0e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + op_readaddr(dp); + op_writeaddr(dp, rd | regs.a); + break; +} + +case 0x4e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + op_readaddr(dp); + op_writeaddr(dp, rd &~ regs.a); + break; +} + +case 0x3a: { + dp = op_readpc(); + rd = op_readdp(dp); + rd++; + op_writedp(dp++, rd); + rd += op_readdp(dp) << 8; + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + break; +} + +case 0x1a: { + dp = op_readpc(); + rd = op_readdp(dp); + rd--; + op_writedp(dp++, rd); + rd += op_readdp(dp) << 8; + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + break; +} + diff --git a/apu/bapu/smp/core/opcycle_misc.cpp b/apu/bapu/smp/core/opcycle_misc.cpp new file mode 100755 index 00000000..963f9fc2 --- /dev/null +++ b/apu/bapu/smp/core/opcycle_misc.cpp @@ -0,0 +1,696 @@ +case 0x00: { + switch(opcode_cycle++) { + case 1: + op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0xef: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.pc--; + opcode_cycle = 0; + break; + } + break; +} + +case 0xff: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.pc--; + opcode_cycle = 0; + break; + } + break; +} + +case 0x9f: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_io(); + break; + case 4: + op_io(); + regs.a = (regs.a >> 4) | (regs.a << 4); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xdf: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + if(regs.p.c || (regs.a) > 0x99) { + regs.a += 0x60; + regs.p.c = 1; + } + if(regs.p.h || (regs.a & 15) > 0x09) { + regs.a += 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xbe: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + if(!regs.p.c || (regs.a) > 0x99) { + regs.a -= 0x60; + regs.p.c = 0; + } + if(!regs.p.h || (regs.a & 15) > 0x09) { + regs.a -= 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0x60: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.c = 0; + opcode_cycle = 0; + break; + } + break; +} + +case 0x20: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.p = 0; + opcode_cycle = 0; + break; + } + break; +} + +case 0x80: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.c = 1; + opcode_cycle = 0; + break; + } + break; +} + +case 0x40: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.p = 1; + opcode_cycle = 0; + break; + } + break; +} + +case 0xe0: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.v = 0; + regs.p.h = 0; + opcode_cycle = 0; + break; + } + break; +} + +case 0xed: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.p.c = !regs.p.c; + opcode_cycle = 0; + break; + } + break; +} + +case 0xa0: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.p.i = 1; + opcode_cycle = 0; + break; + } + break; +} + +case 0xc0: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.p.i = 0; + opcode_cycle = 0; + break; + } + break; +} + +case 0x02: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x01; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x12: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x01; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x22: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x02; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x32: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x02; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x42: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x04; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x52: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x04; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x62: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x08; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x72: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x08; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x82: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x10; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x92: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x10; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xa2: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x20; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xb2: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x20; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc2: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x40; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd2: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x40; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe2: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x80; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf2: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x80; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x2d: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_writestack(regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0x4d: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_writestack(regs.x); + opcode_cycle = 0; + break; + } + break; +} + +case 0x6d: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_writestack(regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0x0d: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_writestack(regs.p); + opcode_cycle = 0; + break; + } + break; +} + +case 0xae: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + regs.a = op_readstack(); + opcode_cycle = 0; + break; + } + break; +} + +case 0xce: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + regs.x = op_readstack(); + opcode_cycle = 0; + break; + } + break; +} + +case 0xee: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + regs.y = op_readstack(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x8e: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + regs.p = op_readstack(); + opcode_cycle = 0; + break; + } + break; +} + +case 0xcf: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_io(); + break; + case 7: + op_io(); + break; + case 8: + op_io(); + ya = regs.y * regs.a; + regs.a = ya; + regs.y = ya >> 8; + //result is set based on y (high-byte) only + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0x9e: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_io(); + break; + case 7: + op_io(); + break; + case 8: + op_io(); + break; + case 9: + op_io(); + break; + case 10: + op_io(); + break; + case 11: + op_io(); + ya = regs.ya; + //overflow set if quotient >= 256 + regs.p.v = !!(regs.y >= regs.x); + regs.p.h = !!((regs.y & 15) >= (regs.x & 15)); + if(regs.y < (regs.x << 1)) { + //if quotient is <= 511 (will fit into 9-bit result) + regs.a = ya / regs.x; + regs.y = ya % regs.x; + } else { + //otherwise, the quotient won't fit into regs.p.v + regs.a + //this emulates the odd behavior of the S-SMP 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); + opcode_cycle = 0; + break; + } + break; +} + diff --git a/apu/bapu/smp/core/opcycle_mov.cpp b/apu/bapu/smp/core/opcycle_mov.cpp new file mode 100755 index 00000000..635c7ca5 --- /dev/null +++ b/apu/bapu/smp/core/opcycle_mov.cpp @@ -0,0 +1,806 @@ +case 0x7d: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = regs.x; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xdd: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = regs.y; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0x5d: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.x = regs.a; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xfd: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.y = regs.a; + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0x9d: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.x = regs.sp; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xbd: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.sp = regs.x; + opcode_cycle = 0; + break; + } + break; +} + +case 0xe8: { + switch(opcode_cycle++) { + case 1: + regs.a = op_readpc(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xcd: { + switch(opcode_cycle++) { + case 1: + regs.x = op_readpc(); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0x8d: { + switch(opcode_cycle++) { + case 1: + regs.y = op_readpc(); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe6: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + regs.a = op_readdp(regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xbf: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + regs.a = op_readdp(regs.x++); + break; + case 3: + op_io(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe4: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + regs.a = op_readdp(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf8: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + regs.x = op_readdp(sp); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xeb: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + regs.y = op_readdp(sp); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf4: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + regs.a = op_readdp(sp + regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf9: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + regs.x = op_readdp(sp + regs.y); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xfb: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + regs.y = op_readdp(sp + regs.x); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe5: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + sp |= op_readpc() << 8; + break; + case 3: + regs.a = op_readaddr(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe9: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + sp |= op_readpc() << 8; + break; + case 3: + regs.x = op_readaddr(sp); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xec: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + sp |= op_readpc() << 8; + break; + case 3: + regs.y = op_readaddr(sp); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf5: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + sp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + regs.a = op_readaddr(sp + regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf6: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + sp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + regs.a = op_readaddr(sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe7: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + regs.a = op_readaddr(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf7: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + regs.a = op_readaddr(sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xfa: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x8f: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + op_readdp(dp); + break; + case 4: + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc6: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_readdp(regs.x); + break; + case 3: + op_writedp(regs.x, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xaf: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_writedp(regs.x++, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc4: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd8: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.x); + opcode_cycle = 0; + break; + } + break; +} + +case 0xcb: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd4: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + dp += regs.x; + break; + case 3: + op_readdp(dp); + break; + case 4: + op_writedp(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd9: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + dp += regs.y; + break; + case 3: + op_readdp(dp); + break; + case 4: + op_writedp(dp, regs.x); + opcode_cycle = 0; + break; + } + break; +} + +case 0xdb: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + dp += regs.x; + break; + case 3: + op_readdp(dp); + break; + case 4: + op_writedp(dp, regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc5: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_readaddr(dp); + break; + case 4: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc9: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_readaddr(dp); + break; + case 4: + op_writeaddr(dp, regs.x); + opcode_cycle = 0; + break; + } + break; +} + +case 0xcc: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_readaddr(dp); + break; + case 4: + op_writeaddr(dp, regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd5: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + dp += regs.x; + break; + case 4: + op_readaddr(dp); + break; + case 5: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd6: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + dp += regs.y; + break; + case 4: + op_readaddr(dp); + break; + case 5: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc7: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + op_io(); + sp += regs.x; + break; + case 3: + dp = op_readdp(sp); + break; + case 4: + dp |= op_readdp(sp + 1) << 8; + break; + case 5: + op_readaddr(dp); + break; + case 6: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd7: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + dp = op_readdp(sp); + break; + case 3: + dp |= op_readdp(sp + 1) << 8; + break; + case 4: + op_io(); + dp += regs.y; + break; + case 5: + op_readaddr(dp); + break; + case 6: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xba: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + regs.a = op_readdp(sp); + break; + case 3: + op_io(); + break; + case 4: + regs.y = op_readdp(sp + 1); + regs.p.n = !!(regs.ya & 0x8000); + regs.p.z = (regs.ya == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xda: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.a); + break; + case 4: + op_writedp(dp + 1, regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0xaa: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + sp |= op_readpc() << 8; + break; + case 3: + bit = sp >> 13; + sp &= 0x1fff; + rd = op_readaddr(sp); + regs.p.c = !!(rd & (1 << bit)); + opcode_cycle = 0; + break; + } + break; +} + +case 0xca: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + if(regs.p.c)rd |= (1 << bit); + else rd &= ~(1 << bit); + break; + case 4: + op_io(); + break; + case 5: + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + diff --git a/apu/bapu/smp/core/opcycle_pc.cpp b/apu/bapu/smp/core/opcycle_pc.cpp new file mode 100755 index 00000000..1cdda647 --- /dev/null +++ b/apu/bapu/smp/core/opcycle_pc.cpp @@ -0,0 +1,1347 @@ +case 0x2f: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(0){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xf0: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(!regs.p.z){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xd0: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(regs.p.z){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xb0: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(!regs.p.c){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x90: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(regs.p.c){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x70: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(!regs.p.v){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x50: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(regs.p.v){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x30: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(!regs.p.n){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x10: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(regs.p.n){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x03: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x01) != 0x01){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x13: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x01) == 0x01){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x23: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x02) != 0x02){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x33: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x02) == 0x02){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x43: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x04) != 0x04){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x53: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x04) == 0x04){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x63: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x08) != 0x08){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x73: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x08) == 0x08){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x83: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x10) != 0x10){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x93: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x10) == 0x10){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xa3: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x20) != 0x20){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xb3: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x20) == 0x20){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xc3: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x40) != 0x40){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xd3: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x40) == 0x40){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xe3: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x80) != 0x80){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xf3: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x80) == 0x80){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x2e: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if(regs.a == sp){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xde: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp + regs.x); + break; + case 4: + rd = op_readpc(); + break; + case 5: + op_io(); + if(regs.a == sp){ opcode_cycle = 0; break; } + break; + case 6: + op_io(); + break; + case 7: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x6e: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + wr = op_readdp(dp); + break; + case 3: + op_writedp(dp, --wr); + break; + case 4: + rd = op_readpc(); + if(wr == 0x00){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xfe: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + op_io(); + regs.y--; + break; + case 3: + op_io(); + if(regs.y == 0x00){ opcode_cycle = 0; break; } + break; + case 4: + op_io(); + break; + case 5: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x5f: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + rd |= op_readpc() << 8; + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x1f: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + dp += regs.x; + break; + case 4: + rd = op_readaddr(dp); + break; + case 5: + rd |= op_readaddr(dp + 1) << 8; + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x3f: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + rd |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x4f: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + op_io(); + break; + case 4: + op_writestack(regs.pc >> 8); + break; + case 5: + op_writestack(regs.pc); + regs.pc = 0xff00 | rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x01: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (0 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x11: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (1 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x21: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (2 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x31: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (3 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x41: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (4 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x51: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (5 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x61: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (6 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x71: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (7 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x81: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (8 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x91: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (9 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xa1: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (10 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xb1: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (11 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xc1: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (12 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xd1: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (13 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xe1: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (14 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xf1: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (15 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x0f: { + switch(opcode_cycle++) { + case 1: + rd = op_readaddr(0xffde); + break; + case 2: + rd |= op_readaddr(0xffdf) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_writestack(regs.pc >> 8); + break; + case 6: + op_writestack(regs.pc); + break; + case 7: + op_writestack(regs.p); + regs.pc = rd; + regs.p.b = 1; + regs.p.i = 0; + opcode_cycle = 0; + break; + } + break; +} + +case 0x6f: { + switch(opcode_cycle++) { + case 1: + rd = op_readstack(); + break; + case 2: + rd |= op_readstack() << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x7f: { + switch(opcode_cycle++) { + case 1: + regs.p = op_readstack(); + break; + case 2: + rd = op_readstack(); + break; + case 3: + rd |= op_readstack() << 8; + break; + case 4: + op_io(); + break; + case 5: + op_io(); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + diff --git a/apu/bapu/smp/core/opcycle_read.cpp b/apu/bapu/smp/core/opcycle_read.cpp new file mode 100755 index 00000000..6c19f3a9 --- /dev/null +++ b/apu/bapu/smp/core/opcycle_read.cpp @@ -0,0 +1,1599 @@ +case 0x88: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x28: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x68: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc8: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.x = op_cmp(regs.x, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xad: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.y = op_cmp(regs.y, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x48: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x08: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xa8: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x86: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x26: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x66: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x46: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x06: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xa6: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x84: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x24: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x64: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x3e: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.x = op_cmp(regs.x, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x7e: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.y = op_cmp(regs.y, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x44: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x04: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xa4: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x94: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x34: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x74: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x54: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x14: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xb4: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x85: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x25: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x65: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x1e: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.x = op_cmp(regs.x, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x5e: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.y = op_cmp(regs.y, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x45: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x05: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xa5: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x95: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x96: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x35: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x36: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x75: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x76: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x55: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x56: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x15: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x16: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xb5: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xb6: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x87: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x27: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x67: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x47: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x07: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xa7: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x97: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x37: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x77: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x57: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x17: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xb7: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x99: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_adc(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x39: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_and(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x79: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_cmp(wr, rd); + break; + case 4: + (0) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x59: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_eor(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x19: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_or(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0xb9: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_sbc(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x89: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x29: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x69: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x49: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x09: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0xa9: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x98: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x38: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x78: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x58: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x18: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0xb8: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x7a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + op_io(); + break; + case 4: + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_addw(regs.ya, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x9a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + op_io(); + break; + case 4: + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_subw(regs.ya, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x5a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= op_readdp(dp + 1) << 8; + op_cmpw(regs.ya, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x4a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !!(rd & (1 << bit)); + opcode_cycle = 0; + break; + } + break; +} + +case 0x6a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !(rd & (1 << bit)); + opcode_cycle = 0; + break; + } + break; +} + +case 0x8a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + break; + case 4: + op_io(); + regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); + opcode_cycle = 0; + break; + } + break; +} + +case 0xea: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + rd ^= (1 << bit); + break; + case 4: + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x0a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + break; + case 4: + op_io(); + regs.p.c = regs.p.c | !!(rd & (1 << bit)); + opcode_cycle = 0; + break; + } + break; +} + +case 0x2a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + break; + case 4: + op_io(); + regs.p.c = regs.p.c | !(rd & (1 << bit)); + opcode_cycle = 0; + break; + } + break; +} + diff --git a/apu/bapu/smp/core/opcycle_rmw.cpp b/apu/bapu/smp/core/opcycle_rmw.cpp new file mode 100755 index 00000000..eca62f02 --- /dev/null +++ b/apu/bapu/smp/core/opcycle_rmw.cpp @@ -0,0 +1,550 @@ +case 0xbc: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_inc(regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0x3d: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.x = op_inc(regs.x); + opcode_cycle = 0; + break; + } + break; +} + +case 0xfc: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.y = op_inc(regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0x9c: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_dec(regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0x1d: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.x = op_dec(regs.x); + opcode_cycle = 0; + break; + } + break; +} + +case 0xdc: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.y = op_dec(regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0x1c: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_asl(regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0x5c: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_lsr(regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0x3c: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_rol(regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0x7c: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_ror(regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xab: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_inc(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x8b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_dec(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x0b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_asl(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x4b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_lsr(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x2b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_rol(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x6b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_ror(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xbb: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_inc(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x9b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_dec(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x1b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_asl(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x5b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_lsr(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x3b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_rol(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x7b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_ror(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xac: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_inc(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x8c: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_dec(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x0c: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_asl(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x4c: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_lsr(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x2c: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_rol(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x6c: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_ror(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x0e: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + break; + case 4: + op_readaddr(dp); + break; + case 5: + op_writeaddr(dp, rd | regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0x4e: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + break; + case 4: + op_readaddr(dp); + break; + case 5: + op_writeaddr(dp, rd &~ regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0x3a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + rd++; + break; + case 3: + op_writedp(dp++, rd); + break; + case 4: + rd += op_readdp(dp) << 8; + break; + case 5: + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0x1a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + rd--; + break; + case 3: + op_writedp(dp++, rd); + break; + case 4: + rd += op_readdp(dp) << 8; + break; + case 5: + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + opcode_cycle = 0; + break; + } + break; +} + diff --git a/apu/bapu/smp/debugger/debugger.cpp b/apu/bapu/smp/debugger/debugger.cpp new file mode 100755 index 00000000..9546c118 --- /dev/null +++ b/apu/bapu/smp/debugger/debugger.cpp @@ -0,0 +1,75 @@ +#ifdef SMP_CPP + +void SMPDebugger::op_step() { + bool break_event = false; + + usage[regs.pc] |= UsageExec; + opcode_pc = regs.pc; + + opcode_edge = true; + debugger.breakpoint_test(Debugger::Breakpoint::Source::APURAM, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00); + if(step_event && step_event() == true) { + debugger.break_event = Debugger::BreakEvent::SMPStep; + scheduler.exit(Scheduler::ExitReason::DebuggerEvent); + } + opcode_edge = false; + + SMP::op_step(); + synchronize_cpu(); +} + +uint8 SMPDebugger::op_read(uint16 addr) { + uint8 data = SMP::op_read(addr); + usage[addr] |= UsageRead; + debugger.breakpoint_test(Debugger::Breakpoint::Source::APURAM, Debugger::Breakpoint::Mode::Read, addr, data); + return data; +} + +void SMPDebugger::op_write(uint16 addr, uint8 data) { + SMP::op_write(addr, data); + usage[addr] |= UsageWrite; + usage[addr] &= ~UsageExec; + debugger.breakpoint_test(Debugger::Breakpoint::Source::APURAM, Debugger::Breakpoint::Mode::Write, addr, data); +} + +SMPDebugger::SMPDebugger() { + usage = new uint8[1 << 16](); + opcode_pc = 0xffc0; + opcode_edge = false; +} + +SMPDebugger::~SMPDebugger() { + delete[] usage; +} + +bool SMPDebugger::property(unsigned id, string &name, string &value) { + unsigned n = 0; + + #define item(name_, value_) \ + if(id == n++) { \ + name = name_; \ + value = value_; \ + return true; \ + } + + //$00f0 + item("$00f0", ""); + item("Clock Speed", (unsigned)status.clock_speed); + item("Timers Enable", status.timers_enable); + item("RAM Disable", status.ram_disable); + item("RAM Writable", status.ram_writable); + item("Timers Disable", status.timers_disable); + + //$00f1 + item("$00f1", ""); + item("IPLROM Enable", status.iplrom_enable); + + //$00f2 + item("$00f2", ""); + item("DSP Address", string("0x", hex<2>(status.dsp_addr))); + + #undef item + return false; +} + +#endif diff --git a/apu/bapu/smp/debugger/debugger.hpp b/apu/bapu/smp/debugger/debugger.hpp new file mode 100755 index 00000000..811aa4c6 --- /dev/null +++ b/apu/bapu/smp/debugger/debugger.hpp @@ -0,0 +1,27 @@ +class SMPDebugger : public SMP, public ChipDebugger { +public: + bool property(unsigned id, string &name, string &value); + + function step_event; + + enum Usage { + UsageRead = 0x80, + UsageWrite = 0x40, + UsageExec = 0x20, + }; + uint8 *usage; + uint16 opcode_pc; + bool opcode_edge; + + void op_step(); + uint8 op_read(uint16 addr); + void op_write(uint16 addr, uint8 data); + + SMPDebugger(); + ~SMPDebugger(); + + //disassembler + void disassemble_opcode(char *output, uint16 addr); + inline uint8 disassemble_read(uint16 addr); + inline uint16 relb(int8 offset, int op_len); +}; diff --git a/apu/bapu/smp/debugger/disassembler.cpp b/apu/bapu/smp/debugger/disassembler.cpp new file mode 100755 index 00000000..fb76ae92 --- /dev/null +++ b/apu/bapu/smp/debugger/disassembler.cpp @@ -0,0 +1,304 @@ +uint8 SMP::disassemble_read(uint16 addr) { + if(addr >= 0xffc0) return smp.iplrom[addr & 0x3f]; + return smp.apuram[addr]; +} + +uint16 SMP::relb(int8 offset, int op_len) { + uint16 pc = regs.pc + op_len; + return pc + offset; +} + +void SMP::disassemble_opcode(char *output, uint16 addr) { + char *s, t[512]; + uint8 op, op0, op1; + uint16 opw, opdp0, opdp1; + s = output; + + sprintf(s, "..%.4x ", addr); + + op = disassemble_read(addr + 0); + op0 = disassemble_read(addr + 1); + op1 = disassemble_read(addr + 2); + opw = (op0) | (op1 << 8); + opdp0 = ((unsigned)regs.p.p << 8) + op0; + opdp1 = ((unsigned)regs.p.p << 8) + op1; + + strcpy(t, " "); + + switch(op) { + case 0x00: sprintf(t, "nop"); break; + case 0x01: sprintf(t, "tcall 0"); break; + case 0x02: sprintf(t, "set0 $%.3x", opdp0); break; + case 0x03: sprintf(t, "bbs0 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x04: sprintf(t, "or a,$%.3x", opdp0); break; + case 0x05: sprintf(t, "or a,$%.4x", opw); break; + case 0x06: sprintf(t, "or a,(x)"); break; + case 0x07: sprintf(t, "or a,($%.3x+x)", opdp0); break; + case 0x08: sprintf(t, "or a,#$%.2x", op0); break; + case 0x09: sprintf(t, "or $%.3x,$%.3x", opdp1, opdp0); break; + case 0x0a: sprintf(t, "or1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0x0b: sprintf(t, "asl $%.3x", opdp0); break; + case 0x0c: sprintf(t, "asl $%.4x", opw); break; + case 0x0d: sprintf(t, "push p"); break; + case 0x0e: sprintf(t, "tset $%.4x,a", opw); break; + case 0x0f: sprintf(t, "brk"); break; + case 0x10: sprintf(t, "bpl $%.4x", relb(op0, 2)); break; + case 0x11: sprintf(t, "tcall 1"); break; + case 0x12: sprintf(t, "clr0 $%.3x", opdp0); break; + case 0x13: sprintf(t, "bbc0 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x14: sprintf(t, "or a,$%.3x+x", opdp0); break; + case 0x15: sprintf(t, "or a,$%.4x+x", opw); break; + case 0x16: sprintf(t, "or a,$%.4x+y", opw); break; + case 0x17: sprintf(t, "or a,($%.3x)+y", opdp0); break; + case 0x18: sprintf(t, "or $%.3x,#$%.2x", opdp1, op0); break; + case 0x19: sprintf(t, "or (x),(y)"); break; + case 0x1a: sprintf(t, "decw $%.3x", opdp0); break; + case 0x1b: sprintf(t, "asl $%.3x+x", opdp0); break; + case 0x1c: sprintf(t, "asl a"); break; + case 0x1d: sprintf(t, "dec x"); break; + case 0x1e: sprintf(t, "cmp x,$%.4x", opw); break; + case 0x1f: sprintf(t, "jmp ($%.4x+x)", opw); break; + case 0x20: sprintf(t, "clrp"); break; + case 0x21: sprintf(t, "tcall 2"); break; + case 0x22: sprintf(t, "set1 $%.3x", opdp0); break; + case 0x23: sprintf(t, "bbs1 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x24: sprintf(t, "and a,$%.3x", opdp0); break; + case 0x25: sprintf(t, "and a,$%.4x", opw); break; + case 0x26: sprintf(t, "and a,(x)"); break; + case 0x27: sprintf(t, "and a,($%.3x+x)", opdp0); break; + case 0x28: sprintf(t, "and a,#$%.2x", op0); break; + case 0x29: sprintf(t, "and $%.3x,$%.3x", opdp1, opdp0); break; + case 0x2a: sprintf(t, "or1 c,!$%.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0x2b: sprintf(t, "rol $%.3x", opdp0); break; + case 0x2c: sprintf(t, "rol $%.4x", opw); break; + case 0x2d: sprintf(t, "push a"); break; + case 0x2e: sprintf(t, "cbne $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x2f: sprintf(t, "bra $%.4x", relb(op0, 2)); break; + case 0x30: sprintf(t, "bmi $%.4x", relb(op0, 2)); break; + case 0x31: sprintf(t, "tcall 3"); break; + case 0x32: sprintf(t, "clr1 $%.3x", opdp0); break; + case 0x33: sprintf(t, "bbc1 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x34: sprintf(t, "and a,$%.3x+x", opdp0); break; + case 0x35: sprintf(t, "and a,$%.4x+x", opw); break; + case 0x36: sprintf(t, "and a,$%.4x+y", opw); break; + case 0x37: sprintf(t, "and a,($%.3x)+y", opdp0); break; + case 0x38: sprintf(t, "and $%.3x,#$%.2x", opdp1, op0); break; + case 0x39: sprintf(t, "and (x),(y)"); break; + case 0x3a: sprintf(t, "incw $%.3x", opdp0); break; + case 0x3b: sprintf(t, "rol $%.3x+x", opdp0); break; + case 0x3c: sprintf(t, "rol a"); break; + case 0x3d: sprintf(t, "inc x"); break; + case 0x3e: sprintf(t, "cmp x,$%.3x", opdp0); break; + case 0x3f: sprintf(t, "call $%.4x", opw); break; + case 0x40: sprintf(t, "setp"); break; + case 0x41: sprintf(t, "tcall 4"); break; + case 0x42: sprintf(t, "set2 $%.3x", opdp0); break; + case 0x43: sprintf(t, "bbs2 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x44: sprintf(t, "eor a,$%.3x", opdp0); break; + case 0x45: sprintf(t, "eor a,$%.4x", opw); break; + case 0x46: sprintf(t, "eor a,(x)"); break; + case 0x47: sprintf(t, "eor a,($%.3x+x)", opdp0); break; + case 0x48: sprintf(t, "eor a,#$%.2x", op0); break; + case 0x49: sprintf(t, "eor $%.3x,$%.3x", opdp1, opdp0); break; + case 0x4a: sprintf(t, "and1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0x4b: sprintf(t, "lsr $%.3x", opdp0); break; + case 0x4c: sprintf(t, "lsr $%.4x", opw); break; + case 0x4d: sprintf(t, "push x"); break; + case 0x4e: sprintf(t, "tclr $%.4x,a", opw); break; + case 0x4f: sprintf(t, "pcall $ff%.2x", op0); break; + case 0x50: sprintf(t, "bvc $%.4x", relb(op0, 2)); break; + case 0x51: sprintf(t, "tcall 5"); break; + case 0x52: sprintf(t, "clr2 $%.3x", opdp0); break; + case 0x53: sprintf(t, "bbc2 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x54: sprintf(t, "eor a,$%.3x+x", opdp0); break; + case 0x55: sprintf(t, "eor a,$%.4x+x", opw); break; + case 0x56: sprintf(t, "eor a,$%.4x+y", opw); break; + case 0x57: sprintf(t, "eor a,($%.3x)+y", opdp0); break; + case 0x58: sprintf(t, "eor $%.3x,#$%.2x", opdp1, op0); break; + case 0x59: sprintf(t, "eor (x),(y)"); break; + case 0x5a: sprintf(t, "cmpw ya,$%.3x", opdp0); break; + case 0x5b: sprintf(t, "lsr $%.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,$%.4x", opw); break; + case 0x5f: sprintf(t, "jmp $%.4x", opw); break; + case 0x60: sprintf(t, "clrc"); break; + case 0x61: sprintf(t, "tcall 6"); break; + case 0x62: sprintf(t, "set3 $%.3x", opdp0); break; + case 0x63: sprintf(t, "bbs3 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x64: sprintf(t, "cmp a,$%.3x", opdp0); break; + case 0x65: sprintf(t, "cmp a,$%.4x", opw); break; + case 0x66: sprintf(t, "cmp a,(x)"); break; + case 0x67: sprintf(t, "cmp a,($%.3x+x)", opdp0); break; + case 0x68: sprintf(t, "cmp a,#$%.2x", op0); break; + case 0x69: sprintf(t, "cmp $%.3x,$%.3x", opdp1, opdp0); break; + case 0x6a: sprintf(t, "and1 c,!$%.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0x6b: sprintf(t, "ror $%.3x", opdp0); break; + case 0x6c: sprintf(t, "ror $%.4x", opw); break; + case 0x6d: sprintf(t, "push y"); break; + case 0x6e: sprintf(t, "dbnz $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x6f: sprintf(t, "ret"); break; + case 0x70: sprintf(t, "bvs $%.4x", relb(op0, 2)); break; + case 0x71: sprintf(t, "tcall 7"); break; + case 0x72: sprintf(t, "clr3 $%.3x", opdp0); break; + case 0x73: sprintf(t, "bbc3 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x74: sprintf(t, "cmp a,$%.3x+x", opdp0); break; + case 0x75: sprintf(t, "cmp a,$%.4x+x", opw); break; + case 0x76: sprintf(t, "cmp a,$%.4x+y", opw); break; + case 0x77: sprintf(t, "cmp a,($%.3x)+y", opdp0); break; + case 0x78: sprintf(t, "cmp $%.3x,#$%.2x", opdp1, op0); break; + case 0x79: sprintf(t, "cmp (x),(y)"); break; + case 0x7a: sprintf(t, "addw ya,$%.3x", opdp0); break; + case 0x7b: sprintf(t, "ror $%.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,$%.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 $%.3x", opdp0); break; + case 0x83: sprintf(t, "bbs4 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x84: sprintf(t, "adc a,$%.3x", opdp0); break; + case 0x85: sprintf(t, "adc a,$%.4x", opw); break; + case 0x86: sprintf(t, "adc a,(x)"); break; + case 0x87: sprintf(t, "adc a,($%.3x+x)", opdp0); break; + case 0x88: sprintf(t, "adc a,#$%.2x", op0); break; + case 0x89: sprintf(t, "adc $%.3x,$%.3x", opdp1, opdp0); break; + case 0x8a: sprintf(t, "eor1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0x8b: sprintf(t, "dec $%.3x", opdp0); break; + case 0x8c: sprintf(t, "dec $%.4x", opw); break; + case 0x8d: sprintf(t, "mov y,#$%.2x", op0); break; + case 0x8e: sprintf(t, "pop p"); break; + case 0x8f: sprintf(t, "mov $%.3x,#$%.2x", opdp1, op0); break; + case 0x90: sprintf(t, "bcc $%.4x", relb(op0, 2)); break; + case 0x91: sprintf(t, "tcall 9"); break; + case 0x92: sprintf(t, "clr4 $%.3x", opdp0); break; + case 0x93: sprintf(t, "bbc4 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x94: sprintf(t, "adc a,$%.3x+x", opdp0); break; + case 0x95: sprintf(t, "adc a,$%.4x+x", opw); break; + case 0x96: sprintf(t, "adc a,$%.4x+y", opw); break; + case 0x97: sprintf(t, "adc a,($%.3x)+y", opdp0); break; + case 0x98: sprintf(t, "adc $%.3x,#$%.2x", opdp1, op0); break; + case 0x99: sprintf(t, "adc (x),(y)"); break; + case 0x9a: sprintf(t, "subw ya,$%.3x", opdp0); break; + case 0x9b: sprintf(t, "dec $%.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 $%.3x", opdp0); break; + case 0xa3: sprintf(t, "bbs5 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0xa4: sprintf(t, "sbc a,$%.3x", opdp0); break; + case 0xa5: sprintf(t, "sbc a,$%.4x", opw); break; + case 0xa6: sprintf(t, "sbc a,(x)"); break; + case 0xa7: sprintf(t, "sbc a,($%.3x+x)", opdp0); break; + case 0xa8: sprintf(t, "sbc a,#$%.2x", op0); break; + case 0xa9: sprintf(t, "sbc $%.3x,$%.3x", opdp1, opdp0); break; + case 0xaa: sprintf(t, "mov1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0xab: sprintf(t, "inc $%.3x", opdp0); break; + case 0xac: sprintf(t, "inc $%.4x", opw); break; + case 0xad: sprintf(t, "cmp y,#$%.2x", op0); break; + case 0xae: sprintf(t, "pop a"); break; + case 0xaf: sprintf(t, "mov (x)+,a"); break; + case 0xb0: sprintf(t, "bcs $%.4x", relb(op0, 2)); break; + case 0xb1: sprintf(t, "tcall 11"); break; + case 0xb2: sprintf(t, "clr5 $%.3x", opdp0); break; + case 0xb3: sprintf(t, "bbc5 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0xb4: sprintf(t, "sbc a,$%.3x+x", opdp0); break; + case 0xb5: sprintf(t, "sbc a,$%.4x+x", opw); break; + case 0xb6: sprintf(t, "sbc a,$%.4x+y", opw); break; + case 0xb7: sprintf(t, "sbc a,($%.3x)+y", opdp0); break; + case 0xb8: sprintf(t, "sbc $%.3x,#$%.2x", opdp1, op0); break; + case 0xb9: sprintf(t, "sbc (x),(y)"); break; + case 0xba: sprintf(t, "movw ya,$%.3x", opdp0); break; + case 0xbb: sprintf(t, "inc $%.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 $%.3x", opdp0); break; + case 0xc3: sprintf(t, "bbs6 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0xc4: sprintf(t, "mov $%.3x,a", opdp0); break; + case 0xc5: sprintf(t, "mov $%.4x,a", opw); break; + case 0xc6: sprintf(t, "mov (x),a"); break; + case 0xc7: sprintf(t, "mov ($%.3x+x),a", opdp0); break; + case 0xc8: sprintf(t, "cmp x,#$%.2x", op0); break; + case 0xc9: sprintf(t, "mov $%.4x,x", opw); break; + case 0xca: sprintf(t, "mov1 $%.4x:%d,c", opw & 0x1fff, opw >> 13); break; + case 0xcb: sprintf(t, "mov $%.3x,y", opdp0); break; + case 0xcc: sprintf(t, "mov $%.4x,y", opw); break; + case 0xcd: sprintf(t, "mov x,#$%.2x", op0); break; + case 0xce: sprintf(t, "pop x"); break; + case 0xcf: sprintf(t, "mul ya"); break; + case 0xd0: sprintf(t, "bne $%.4x", relb(op0, 2)); break; + case 0xd1: sprintf(t, "tcall 13"); break; + case 0xd2: sprintf(t, "clr6 $%.3x", opdp0); break; + case 0xd3: sprintf(t, "bbc6 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0xd4: sprintf(t, "mov $%.3x+x,a", opdp0); break; + case 0xd5: sprintf(t, "mov $%.4x+x,a", opw); break; + case 0xd6: sprintf(t, "mov $%.4x+y,a", opw); break; + case 0xd7: sprintf(t, "mov ($%.3x)+y,a", opdp0); break; + case 0xd8: sprintf(t, "mov $%.3x,x", opdp0); break; + case 0xd9: sprintf(t, "mov $%.3x+y,x", opdp0); break; + case 0xda: sprintf(t, "movw $%.3x,ya", opdp0); break; + case 0xdb: sprintf(t, "mov $%.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 $%.3x+x,$%.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 $%.3x", opdp0); break; + case 0xe3: sprintf(t, "bbs7 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0xe4: sprintf(t, "mov a,$%.3x", opdp0); break; + case 0xe5: sprintf(t, "mov a,$%.4x", opw); break; + case 0xe6: sprintf(t, "mov a,(x)"); break; + case 0xe7: sprintf(t, "mov a,($%.3x+x)", opdp0); break; + case 0xe8: sprintf(t, "mov a,#$%.2x", op0); break; + case 0xe9: sprintf(t, "mov x,$%.4x", opw); break; + case 0xea: sprintf(t, "not1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0xeb: sprintf(t, "mov y,$%.3x", opdp0); break; + case 0xec: sprintf(t, "mov y,$%.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 $%.4x", relb(op0, 2)); break; + case 0xf1: sprintf(t, "tcall 15"); break; + case 0xf2: sprintf(t, "clr7 $%.3x", opdp0); break; + case 0xf3: sprintf(t, "bbc7 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0xf4: sprintf(t, "mov a,$%.3x+x", opdp0); break; + case 0xf5: sprintf(t, "mov a,$%.4x+x", opw); break; + case 0xf6: sprintf(t, "mov a,$%.4x+y", opw); break; + case 0xf7: sprintf(t, "mov a,($%.3x)+y", opdp0); break; + case 0xf8: sprintf(t, "mov x,$%.3x", opdp0); break; + case 0xf9: sprintf(t, "mov x,$%.3x+y", opdp0); break; + case 0xfa: sprintf(t, "mov $%.3x,$%.3x", opdp1, opdp0); break; + case 0xfb: sprintf(t, "mov y,$%.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,$%.4x", relb(op0, 2)); break; + case 0xff: sprintf(t, "stop"); break; + } + + t[strlen(t)] = ' '; + strcat(s, t); + + sprintf(t, "A:%.2x X:%.2x Y:%.2x SP:01%.2x YA:%.4x ", + regs.a, regs.x, regs.y, regs.sp, (uint16)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); +} diff --git a/apu/bapu/smp/iplrom.cpp b/apu/bapu/smp/iplrom.cpp new file mode 100755 index 00000000..a2ade89d --- /dev/null +++ b/apu/bapu/smp/iplrom.cpp @@ -0,0 +1,44 @@ +#ifdef SMP_CPP + +//this is the IPLROM for the S-SMP coprocessor. +//the S-SMP does not allow writing to the IPLROM. +//all writes are instead mapped to the extended +//RAM region, accessible when $f1.d7 is clear. + +const uint8 SMP::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) +}; + +#endif diff --git a/apu/bapu/smp/memory.cpp b/apu/bapu/smp/memory.cpp new file mode 100755 index 00000000..aecba720 --- /dev/null +++ b/apu/bapu/smp/memory.cpp @@ -0,0 +1,130 @@ +unsigned SMP::port_read(unsigned addr) { + return apuram[0xf4 + (addr & 3)]; +} + +void SMP::port_write(unsigned addr, unsigned data) { + apuram[0xf4 + (addr & 3)] = data; +} + +unsigned SMP::mmio_read(unsigned addr) { + switch(addr) { + + case 0xf2: + return status.dsp_addr; + + case 0xf3: + return dsp.read(status.dsp_addr & 0x7f); + + case 0xf4: + case 0xf5: + case 0xf6: + case 0xf7: + synchronize_cpu(); + return cpu.port_read(addr); + + case 0xf8: + return status.ram00f8; + + case 0xf9: + return status.ram00f9; + + case 0xfd: { + unsigned result = timer0.stage3_ticks & 15; + timer0.stage3_ticks = 0; + return result; + } + + case 0xfe: { + unsigned result = timer1.stage3_ticks & 15; + timer1.stage3_ticks = 0; + return result; + } + + case 0xff: { + unsigned result = timer2.stage3_ticks & 15; + timer2.stage3_ticks = 0; + return result; + } + + } + + return 0x00; +} + +void SMP::mmio_write(unsigned addr, unsigned data) { + switch(addr) { + + case 0xf1: + status.iplrom_enable = data & 0x80; + + if(data & 0x30) { + synchronize_cpu(); + if(data & 0x20) { + cpu.port_write(3, 0x00); + cpu.port_write(2, 0x00); + } + if(data & 0x10) { + cpu.port_write(1, 0x00); + cpu.port_write(0, 0x00); + } + } + + if(timer2.enable == false && (data & 0x04)) { + timer2.stage2_ticks = 0; + timer2.stage3_ticks = 0; + } + timer2.enable = data & 0x04; + + if(timer1.enable == false && (data & 0x02)) { + timer1.stage2_ticks = 0; + timer1.stage3_ticks = 0; + } + timer1.enable = data & 0x02; + + if(timer0.enable == false && (data & 0x01)) { + timer0.stage2_ticks = 0; + timer0.stage3_ticks = 0; + } + timer0.enable = data & 0x01; + + break; + + case 0xf2: + status.dsp_addr = data; + break; + + case 0xf3: + if(status.dsp_addr & 0x80) break; + dsp.write(status.dsp_addr, data); + break; + + case 0xf4: + case 0xf5: + case 0xf6: + case 0xf7: + synchronize_cpu(); + port_write(addr, data); + break; + + case 0xf8: + status.ram00f8 = data; + break; + + case 0xf9: + status.ram00f9 = data; + break; + + case 0xfa: + timer0.target = data; + break; + + case 0xfb: + timer1.target = data; + break; + + case 0xfc: + timer2.target = data; + break; + + } +} diff --git a/apu/bapu/smp/smp.cpp b/apu/bapu/smp/smp.cpp new file mode 100755 index 00000000..ba26d0b4 --- /dev/null +++ b/apu/bapu/smp/smp.cpp @@ -0,0 +1,154 @@ +#define CYCLE_ACCURATE + +#include + +#define SMP_CPP +namespace SNES { + +#if defined(DEBUGGER) + #include "debugger/debugger.cpp" + #include "debugger/disassembler.cpp" + SMPDebugger smp; +#else + SMP smp; +#endif + +#include "algorithms.cpp" +#include "core.cpp" +#include "iplrom.cpp" +#include "memory.cpp" +#include "timing.cpp" + +void SMP::synchronize_cpu() { + if(CPU::Threaded == true) { + //if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); + } else { + while(clock >= 0) cpu.enter(); + } +} + +void SMP::synchronize_dsp() { + if(DSP::Threaded == true) { + //if(dsp.clock < 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(dsp.thread); + } else { + while(dsp.clock < 0) dsp.enter(); + } +} + +void SMP::enter() { + while(clock < 0) op_step(); +} + +void SMP::power() { +#ifdef BSNES + Processor::frequency = system.apu_frequency(); +#else + Processor::frequency = 1025600; +#endif + + Processor::clock = 0; + + timer0.target = 0; + timer1.target = 0; + timer2.target = 0; + + for(unsigned n = 0; n < 256; n++) { + cycle_table_dsp[n] = (cycle_count_table[n] * 24); + cycle_table_cpu[n] = (cycle_count_table[n] * 24) * cpu.frequency; + } + + cycle_step_cpu = 24 * cpu.frequency; + + reset(); +} + +void SMP::reset() { + for(unsigned n = 0x0000; n <= 0xffff; n++) apuram[n] = 0x00; + + opcode_number = 0; + opcode_cycle = 0; + + regs.pc = 0xffc0; + regs.sp = 0xef; + regs.a = 0x00; + regs.x = 0x00; + regs.y = 0x00; + regs.p = 0x02; + + //$00f1 + status.iplrom_enable = true; + + //$00f2 + status.dsp_addr = 0x00; + + //$00f8,$00f9 + status.ram00f8 = 0x00; + status.ram00f9 = 0x00; + + //timers + timer0.enable = timer1.enable = timer2.enable = false; + timer0.stage1_ticks = timer1.stage1_ticks = timer2.stage1_ticks = 0; + timer0.stage2_ticks = timer1.stage2_ticks = timer2.stage2_ticks = 0; + timer0.stage3_ticks = timer1.stage3_ticks = timer2.stage3_ticks = 0; +} + +#ifdef BSNES +void SMP::serialize(serializer &s) { + Processor::serialize(s); + + s.array(apuram, 64 * 1024); + + s.integer(opcode_number); + s.integer(opcode_cycle); + + s.integer(regs.pc); + s.integer(regs.sp); + s.integer(regs.a); + s.integer(regs.x); + s.integer(regs.y); + + s.integer(regs.p.n); + s.integer(regs.p.v); + s.integer(regs.p.p); + s.integer(regs.p.b); + s.integer(regs.p.h); + s.integer(regs.p.i); + s.integer(regs.p.z); + s.integer(regs.p.c); + + s.integer(status.iplrom_enable); + + s.integer(status.dsp_addr); + + s.integer(status.ram00f8); + s.integer(status.ram00f9); + + s.integer(timer0.enable); + s.integer(timer0.target); + s.integer(timer0.stage1_ticks); + s.integer(timer0.stage2_ticks); + s.integer(timer0.stage3_ticks); + + s.integer(timer1.enable); + s.integer(timer1.target); + s.integer(timer1.stage1_ticks); + s.integer(timer1.stage2_ticks); + s.integer(timer1.stage3_ticks); + + s.integer(timer2.enable); + s.integer(timer2.target); + + s.integer(timer2.stage1_ticks); + s.integer(timer2.stage2_ticks); + s.integer(timer2.stage3_ticks); +} +#endif + +SMP::SMP() { + apuram = new uint8[64 * 1024]; +} + +SMP::~SMP() { +} + +} diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp new file mode 100755 index 00000000..be52f77a --- /dev/null +++ b/apu/bapu/smp/smp.hpp @@ -0,0 +1,124 @@ +class SMP : public Processor { +public: + static const uint8 iplrom[64]; + uint8 *apuram; + + enum { Threaded = false }; + alwaysinline void synchronize_cpu(); + alwaysinline void synchronize_dsp(); + + unsigned port_read(unsigned port); + void port_write(unsigned port, unsigned data); + + unsigned mmio_read(unsigned addr); + void mmio_write(unsigned addr, unsigned data); + + void enter(); + void power(); + void reset(); + +#ifdef BSNES + void serialize(serializer&); +#endif + SMP(); + ~SMP(); + +//private: + struct Flags { + bool n, v, p, b, h, i, z, c; + + alwaysinline operator unsigned() const { + return (n << 7) | (v << 6) | (p << 5) | (b << 4) + | (h << 3) | (i << 2) | (z << 1) | (c << 0); + }; + + alwaysinline unsigned operator=(unsigned data) { + n = data & 0x80; v = data & 0x40; p = data & 0x20; b = data & 0x10; + h = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01; + return *this; + } + + alwaysinline unsigned operator|=(unsigned data) { return operator=(operator unsigned() | data); } + alwaysinline unsigned operator^=(unsigned data) { return operator=(operator unsigned() ^ data); } + alwaysinline unsigned operator&=(unsigned data) { return operator=(operator unsigned() & data); } + }; + + unsigned opcode_number; + unsigned opcode_cycle; + + struct Regs { + uint16 pc; + uint8 sp; + union { + uint16 ya; +#ifndef __BIG_ENDIAN__ + struct { uint8 a, y; }; +#else + struct { uint8 y, a; }; +#endif + }; + uint8 x; + Flags p; + } regs; + + struct Status { + //$00f1 + bool iplrom_enable; + + //$00f2 + unsigned dsp_addr; + + //$00f8,$00f9 + unsigned ram00f8; + unsigned ram00f9; + } status; + + template + struct Timer { + bool enable; + uint8 target; + uint8 stage1_ticks; + uint8 stage2_ticks; + uint8 stage3_ticks; + + void tick(); + void tick(unsigned clocks); + }; + + Timer<128> timer0; + Timer<128> timer1; + Timer< 16> timer2; + + void tick(); + alwaysinline void op_io(); + debugvirtual alwaysinline uint8 op_read(uint16 addr); + debugvirtual alwaysinline void op_write(uint16 addr, uint8 data); + debugvirtual alwaysinline void op_step(); + static const unsigned cycle_count_table[256]; + uint64 cycle_table_cpu[256]; + unsigned cycle_table_dsp[256]; + uint64 cycle_step_cpu; + + uint8 op_adc (uint8 x, uint8 y); + uint16 op_addw(uint16 x, uint16 y); + uint8 op_and (uint8 x, uint8 y); + uint8 op_cmp (uint8 x, uint8 y); + uint16 op_cmpw(uint16 x, uint16 y); + uint8 op_eor (uint8 x, uint8 y); + uint8 op_inc (uint8 x); + uint8 op_dec (uint8 x); + uint8 op_or (uint8 x, uint8 y); + uint8 op_sbc (uint8 x, uint8 y); + uint16 op_subw(uint16 x, uint16 y); + uint8 op_asl (uint8 x); + uint8 op_lsr (uint8 x); + uint8 op_rol (uint8 x); + uint8 op_ror (uint8 x); +}; + +#if defined(DEBUGGER) + #include "debugger/debugger.hpp" + extern SMPDebugger smp; +#else + extern SMP smp; +#endif diff --git a/apu/bapu/smp/timing.cpp b/apu/bapu/smp/timing.cpp new file mode 100755 index 00000000..d278f6f4 --- /dev/null +++ b/apu/bapu/smp/timing.cpp @@ -0,0 +1,26 @@ +template +void SMP::Timer::tick() { + if(++stage1_ticks < cycle_frequency) return; + + stage1_ticks = 0; + if(enable == false) return; + + if(++stage2_ticks != target) return; + + stage2_ticks = 0; + stage3_ticks = (stage3_ticks + 1) & 15; +} + +template +void SMP::Timer::tick(unsigned clocks) { + stage1_ticks += clocks; + if(stage1_ticks < cycle_frequency) return; + + stage1_ticks -= cycle_frequency; + if(enable == false) return; + + if(++stage2_ticks != target) return; + + stage2_ticks = 0; + stage3_ticks = (stage3_ticks + 1) & 15; +} diff --git a/apu/bapu/snes/snes.hpp b/apu/bapu/snes/snes.hpp new file mode 100755 index 00000000..47b687ff --- /dev/null +++ b/apu/bapu/snes/snes.hpp @@ -0,0 +1,45 @@ +#ifndef __SNES_HPP +#define __SNES_HPP + +#include "snes9x.h" + +#define alwaysinline inline +#define debugvirtual + +namespace SNES +{ + +struct Processor +{ + unsigned frequency; + int64 clock; +}; + +class CPU +{ +public: + enum { Threaded = false }; + int frequency; + + void enter () + { + } + + void port_write (uint8 port, uint8 data) + { + } + + uint8 port_read (uint8 port) + { + return 0; + } +}; + +extern CPU cpu; + +#include "smp/smp.hpp" +#include "dsp/dsp.hpp" + +} /* namespace SNES */ + +#endif diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 14d99899..4ec45d06 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -8,7 +8,7 @@ snes9x_gtk_CXXFLAGS = -fno-exceptions -fno-rtti endif noinst_LIBRARIES = -INCLUDES = -I$(top_srcdir) -I.. -DSNES9XLOCALEDIR=\""$(snes9xlocaledir)"\" +INCLUDES = -I../apu/bapu -I$(top_srcdir) -I.. -DSNES9XLOCALEDIR=\""$(snes9xlocaledir)"\" CLEANFILES = \ src/gtk_snes9x_ui.cpp \ @@ -123,8 +123,14 @@ snes9x_gtk_SOURCES += \ ../apu/SNES_SPC.cpp \ ../apu/SNES_SPC_misc.cpp \ ../apu/SNES_SPC_state.cpp \ - ../apu/SPC_DSP.cpp \ ../apu/SPC_Filter.cpp + +# Byuu's APU +snes9x_gtk_SOURCES += \ + ../apu/bapu/dsp/dsp.cpp \ + ../apu/bapu/dsp/serialization.cpp \ + ../apu/bapu/dsp/SPC_DSP.cpp \ + ../apu/bapu/smp/smp.cpp # DSP snes9x_gtk_SOURCES += \ diff --git a/gtk/src/gtk_s9xwindow.cpp b/gtk/src/gtk_s9xwindow.cpp index f7713978..f58d934f 100644 --- a/gtk/src/gtk_s9xwindow.cpp +++ b/gtk/src/gtk_s9xwindow.cpp @@ -221,7 +221,6 @@ event_motion_notify (GtkWidget *widget, gpointer user_data) { Snes9xWindow *window = (Snes9xWindow *) user_data; - int c_width, c_height; if (!window->config->rom_loaded || window->last_width <= 0 || @@ -230,9 +229,6 @@ event_motion_notify (GtkWidget *widget, return FALSE; } - c_width = window->get_width (); - c_height = window->get_height (); - window->mouse_loc_x = (uint16) ((int) (event->x) - window->mouse_region_x) * 256 / (window->mouse_region_width <= 0 ? 1 : window->mouse_region_width); From 10a521e39c64ed51580e0421f49e5079c173d536 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Sat, 18 Jun 2011 05:31:44 -0500 Subject: [PATCH 02/33] byuu APU now being used. Nothing works yet. Sync is broken, but the new SMP will handle ratios now. Save states need to be redone without serializer. No SPC dumping. --- apu/SNES_SPC.cpp | 564 ------------------ apu/SNES_SPC.h | 316 ----------- apu/SNES_SPC_misc.cpp | 855 ---------------------------- apu/SNES_SPC_state.cpp | 142 ----- apu/SPC_CPU.h | 1228 ---------------------------------------- apu/SPC_DSP.cpp | 1072 ----------------------------------- apu/SPC_DSP.h | 319 ----------- apu/SPC_Filter.cpp | 68 --- apu/SPC_Filter.h | 47 -- apu/apu.cpp | 101 ++-- apu/apu.h | 3 - apu/bapu/dsp/dsp.cpp | 8 - apu/bapu/dsp/dsp.hpp | 4 +- apu/bapu/smp/smp.cpp | 2 - apu/bapu/snes/snes.hpp | 2 + apu/blargg_common.h | 186 ------ apu/blargg_config.h | 24 - apu/blargg_endian.h | 185 ------ apu/blargg_source.h | 100 ---- apu/license.txt | 504 ----------------- apu/linear_resampler.h | 115 ---- gtk/Makefile.am | 6 +- snapshot.cpp | 14 +- 23 files changed, 46 insertions(+), 5819 deletions(-) delete mode 100644 apu/SNES_SPC.cpp delete mode 100644 apu/SNES_SPC.h delete mode 100644 apu/SNES_SPC_misc.cpp delete mode 100644 apu/SNES_SPC_state.cpp delete mode 100644 apu/SPC_CPU.h delete mode 100644 apu/SPC_DSP.cpp delete mode 100644 apu/SPC_DSP.h delete mode 100644 apu/SPC_Filter.cpp delete mode 100644 apu/SPC_Filter.h delete mode 100644 apu/blargg_common.h delete mode 100644 apu/blargg_config.h delete mode 100644 apu/blargg_endian.h delete mode 100644 apu/blargg_source.h delete mode 100644 apu/license.txt delete mode 100644 apu/linear_resampler.h diff --git a/apu/SNES_SPC.cpp b/apu/SNES_SPC.cpp deleted file mode 100644 index 567b7ddc..00000000 --- a/apu/SNES_SPC.cpp +++ /dev/null @@ -1,564 +0,0 @@ -// Core SPC emulation: CPU, timers, SMP registers, memory - -// snes_spc 0.9.0. http://www.slack.net/~ant/ - -#include "SNES_SPC.h" - -#include - -/* Copyright (C) 2004-2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -#define RAM (m.ram.ram) -#define REGS (m.smp_regs [0]) -#define REGS_IN (m.smp_regs [1]) - -// (n ? n : 256) -#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1) - -// Note: SPC_MORE_ACCURACY exists mainly so I can run my validation tests, which -// do crazy echo buffer accesses. -#ifndef SPC_MORE_ACCURACY - #define SPC_MORE_ACCURACY 0 -#endif - -#ifdef BLARGG_ENABLE_OPTIMIZER - #include BLARGG_ENABLE_OPTIMIZER -#endif - - -//// Timers - -#if SPC_DISABLE_TEMPO - #define TIMER_DIV( t, n ) ((n) >> t->prescaler) - #define TIMER_MUL( t, n ) ((n) << t->prescaler) -#else - #define TIMER_DIV( t, n ) ((n) / t->prescaler) - #define TIMER_MUL( t, n ) ((n) * t->prescaler) -#endif - -SNES_SPC::Timer* SNES_SPC::run_timer_( Timer* t, rel_time_t time ) -{ - int elapsed = TIMER_DIV( t, time - t->next_time ) + 1; - t->next_time += TIMER_MUL( t, elapsed ); - - if ( t->enabled ) - { - int remain = IF_0_THEN_256( t->period - t->divider ); - int divider = t->divider + elapsed; - int over = elapsed - remain; - if ( over >= 0 ) - { - int n = over / t->period; - t->counter = (t->counter + 1 + n) & 0x0F; - divider = over - n * t->period; - } - t->divider = (uint8_t) divider; - } - return t; -} - -inline SNES_SPC::Timer* SNES_SPC::run_timer( Timer* t, rel_time_t time ) -{ - if ( time >= t->next_time ) - t = run_timer_( t, time ); - return t; -} - - -//// ROM - -void SNES_SPC::enable_rom( int enable ) -{ - if ( m.rom_enabled != enable ) - { - m.rom_enabled = dsp.rom_enabled = enable; - if ( enable ) - memcpy( m.hi_ram, &RAM [rom_addr], sizeof m.hi_ram ); - memcpy( &RAM [rom_addr], (enable ? m.rom : m.hi_ram), rom_size ); - // TODO: ROM can still get overwritten when DSP writes to echo buffer - } -} - - -//// DSP - -#if SPC_LESS_ACCURATE - int const max_reg_time = 29; - - signed char const SNES_SPC::reg_times_ [256] = - { - -1, 0,-11,-10,-15,-11, -2, -2, 4, 3, 14, 14, 26, 26, 14, 22, - 2, 3, 0, 1,-12, 0, 1, 1, 7, 6, 14, 14, 27, 14, 14, 23, - 5, 6, 3, 4, -1, 3, 4, 4, 10, 9, 14, 14, 26, -5, 14, 23, - 8, 9, 6, 7, 2, 6, 7, 7, 13, 12, 14, 14, 27, -4, 14, 24, - 11, 12, 9, 10, 5, 9, 10, 10, 16, 15, 14, 14, -2, -4, 14, 24, - 14, 15, 12, 13, 8, 12, 13, 13, 19, 18, 14, 14, -2,-36, 14, 24, - 17, 18, 15, 16, 11, 15, 16, 16, 22, 21, 14, 14, 28, -3, 14, 25, - 20, 21, 18, 19, 14, 18, 19, 19, 25, 24, 14, 14, 14, 29, 14, 25, - - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - }; - - #define RUN_DSP( time, offset ) \ - int count = (time) - (offset) - m.dsp_time;\ - if ( count >= 0 )\ - {\ - int clock_count = (count & ~(clocks_per_sample - 1)) + clocks_per_sample;\ - m.dsp_time += clock_count;\ - dsp.run( clock_count );\ - } -#else - #define RUN_DSP( time, offset ) \ - {\ - int count = (time) - m.dsp_time;\ - if ( !SPC_MORE_ACCURACY || count )\ - {\ - assert( count > 0 );\ - m.dsp_time = (time);\ - dsp.run( count );\ - }\ - } -#endif - -int SNES_SPC::dsp_read( rel_time_t time ) -{ - RUN_DSP( time, reg_times [REGS [r_dspaddr] & 0x7F] ); - - int result = dsp.read( REGS [r_dspaddr] & 0x7F ); - - #ifdef SPC_DSP_READ_HOOK - SPC_DSP_READ_HOOK( spc_time + time, (REGS [r_dspaddr] & 0x7F), result ); - #endif - - return result; -} - -inline void SNES_SPC::dsp_write( int data, rel_time_t time ) -{ - RUN_DSP( time, reg_times [REGS [r_dspaddr]] ) - #if SPC_LESS_ACCURATE - else if ( m.dsp_time == skipping_time ) - { - int r = REGS [r_dspaddr]; - if ( r == SPC_DSP::r_kon ) - m.skipped_kon |= data & ~dsp.read( SPC_DSP::r_koff ); - - if ( r == SPC_DSP::r_koff ) - { - m.skipped_koff |= data; - m.skipped_kon &= ~data; - } - } - #endif - - #ifdef SPC_DSP_WRITE_HOOK - SPC_DSP_WRITE_HOOK( m.spc_time + time, REGS [r_dspaddr], (uint8_t) data ); - #endif - - if ( REGS [r_dspaddr] <= 0x7F ) - dsp.write( REGS [r_dspaddr], data ); - else if ( !SPC_MORE_ACCURACY ) - dprintf( "SPC wrote to DSP register > $7F\n" ); -} - - -//// Memory access extras - -#if SPC_MORE_ACCURACY - #define MEM_ACCESS( time, addr ) \ - {\ - if ( time >= m.dsp_time )\ - {\ - RUN_DSP( time, max_reg_time );\ - }\ - } -#elif !defined (NDEBUG) - // Debug-only check for read/write within echo buffer, since this might result in - // inaccurate emulation due to the DSP not being caught up to the present. - - bool SNES_SPC::check_echo_access( int addr ) - { - if ( !(dsp.read( SPC_DSP::r_flg ) & 0x20) ) - { - int start = 0x100 * dsp.read( SPC_DSP::r_esa ); - int size = 0x800 * (dsp.read( SPC_DSP::r_edl ) & 0x0F); - int end = start + (size ? size : 4); - if ( start <= addr && addr < end ) - { - if ( !m.echo_accessed ) - { - m.echo_accessed = 1; - return true; - } - } - } - return false; - } - - #define MEM_ACCESS( time, addr ) check( !check_echo_access( (uint16_t) addr ) ); -#else - #define MEM_ACCESS( time, addr ) -#endif - - -//// CPU write - -#if SPC_MORE_ACCURACY -static unsigned char const glitch_probs [3] [256] = -{ - 0xC3,0x92,0x5B,0x1C,0xD1,0x92,0x5B,0x1C,0xDB,0x9C,0x72,0x18,0xCD,0x5C,0x38,0x0B, - 0xE1,0x9C,0x74,0x17,0xCF,0x75,0x45,0x0C,0xCF,0x6E,0x4A,0x0D,0xA3,0x3A,0x1D,0x08, - 0xDB,0xA0,0x82,0x19,0xD9,0x73,0x3C,0x0E,0xCB,0x76,0x52,0x0B,0xA5,0x46,0x1D,0x09, - 0xDA,0x74,0x55,0x0F,0xA2,0x3F,0x21,0x05,0x9A,0x40,0x20,0x07,0x63,0x1E,0x10,0x01, - 0xDF,0xA9,0x85,0x1D,0xD3,0x84,0x4B,0x0E,0xCF,0x6F,0x49,0x0F,0xB3,0x48,0x1E,0x05, - 0xD8,0x77,0x52,0x12,0xB7,0x49,0x23,0x06,0xAA,0x45,0x28,0x07,0x7D,0x28,0x0F,0x07, - 0xCC,0x7B,0x4A,0x0E,0xB2,0x4F,0x24,0x07,0xAD,0x43,0x2C,0x06,0x86,0x29,0x11,0x07, - 0xAE,0x48,0x1F,0x0A,0x76,0x21,0x19,0x05,0x76,0x21,0x14,0x05,0x44,0x11,0x0B,0x01, - 0xE7,0xAD,0x96,0x23,0xDC,0x86,0x59,0x0E,0xDC,0x7C,0x5F,0x15,0xBB,0x53,0x2E,0x09, - 0xD6,0x7C,0x4A,0x16,0xBB,0x4A,0x25,0x08,0xB3,0x4F,0x28,0x0B,0x8E,0x23,0x15,0x08, - 0xCF,0x7F,0x57,0x11,0xB5,0x4A,0x23,0x0A,0xAA,0x42,0x28,0x05,0x7D,0x22,0x12,0x03, - 0xA6,0x49,0x28,0x09,0x82,0x2B,0x0D,0x04,0x7A,0x20,0x0F,0x04,0x3D,0x0F,0x09,0x03, - 0xD1,0x7C,0x4C,0x0F,0xAF,0x4E,0x21,0x09,0xA8,0x46,0x2A,0x07,0x85,0x1F,0x0E,0x07, - 0xA6,0x3F,0x26,0x07,0x7C,0x24,0x14,0x07,0x78,0x22,0x16,0x04,0x46,0x12,0x0A,0x02, - 0xA6,0x41,0x2C,0x0A,0x7E,0x28,0x11,0x05,0x73,0x1B,0x14,0x05,0x3D,0x11,0x0A,0x02, - 0x70,0x22,0x17,0x05,0x48,0x13,0x08,0x03,0x3C,0x07,0x0D,0x07,0x26,0x07,0x06,0x01, - - 0xE0,0x9F,0xDA,0x7C,0x4F,0x18,0x28,0x0D,0xE9,0x9F,0xDA,0x7C,0x4F,0x18,0x1F,0x07, - 0xE6,0x97,0xD8,0x72,0x64,0x13,0x26,0x09,0xDC,0x67,0xA9,0x38,0x21,0x07,0x15,0x06, - 0xE9,0x91,0xD2,0x6B,0x63,0x14,0x2B,0x0E,0xD6,0x61,0xB7,0x41,0x2B,0x0E,0x10,0x09, - 0xCF,0x59,0xB0,0x2F,0x35,0x08,0x0F,0x07,0xB6,0x30,0x7A,0x21,0x17,0x07,0x09,0x03, - 0xE7,0xA3,0xE5,0x6B,0x65,0x1F,0x34,0x09,0xD8,0x6B,0xBE,0x45,0x27,0x07,0x10,0x07, - 0xDA,0x54,0xB1,0x39,0x2E,0x0E,0x17,0x08,0xA9,0x3C,0x86,0x22,0x16,0x06,0x07,0x03, - 0xD4,0x51,0xBC,0x3D,0x38,0x0A,0x13,0x06,0xB2,0x37,0x79,0x1C,0x17,0x05,0x0E,0x06, - 0xA7,0x31,0x74,0x1C,0x11,0x06,0x0C,0x02,0x6D,0x1A,0x38,0x10,0x0B,0x05,0x06,0x03, - 0xEB,0x9A,0xE1,0x7A,0x6F,0x13,0x34,0x0E,0xE6,0x75,0xC5,0x45,0x3E,0x0B,0x1A,0x05, - 0xD8,0x63,0xC1,0x40,0x3C,0x1B,0x19,0x06,0xB3,0x42,0x83,0x29,0x18,0x0A,0x08,0x04, - 0xD4,0x58,0xBA,0x43,0x3F,0x0A,0x1F,0x09,0xB1,0x33,0x8A,0x1F,0x1F,0x06,0x0D,0x05, - 0xAF,0x3C,0x7A,0x1F,0x16,0x08,0x0A,0x01,0x72,0x1B,0x52,0x0D,0x0B,0x09,0x06,0x01, - 0xCF,0x63,0xB7,0x47,0x40,0x10,0x14,0x06,0xC0,0x41,0x96,0x20,0x1C,0x09,0x10,0x05, - 0xA6,0x35,0x82,0x1A,0x20,0x0C,0x0E,0x04,0x80,0x1F,0x53,0x0F,0x0B,0x02,0x06,0x01, - 0xA6,0x31,0x81,0x1B,0x1D,0x01,0x08,0x08,0x7B,0x20,0x4D,0x19,0x0E,0x05,0x07,0x03, - 0x6B,0x17,0x49,0x07,0x0E,0x03,0x0A,0x05,0x37,0x0B,0x1F,0x06,0x04,0x02,0x07,0x01, - - 0xF0,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x47,0x1E,0x6E,0x1B,0x32,0x0A, - 0xF0,0xD6,0xEA,0xA4,0xED,0xC4,0xDE,0x82,0x98,0x1F,0x50,0x13,0x52,0x15,0x2A,0x0A, - 0xF1,0xD1,0xEB,0xA2,0xEB,0xB7,0xD8,0x69,0xA2,0x1F,0x5B,0x18,0x55,0x18,0x2C,0x0A, - 0xED,0xB5,0xDE,0x7E,0xE6,0x85,0xD3,0x59,0x59,0x0F,0x2C,0x09,0x24,0x07,0x15,0x09, - 0xF1,0xD6,0xEA,0xA0,0xEC,0xBB,0xDA,0x77,0xA9,0x23,0x58,0x14,0x5D,0x12,0x2F,0x09, - 0xF1,0xC1,0xE3,0x86,0xE4,0x87,0xD2,0x4E,0x68,0x15,0x26,0x0B,0x27,0x09,0x15,0x02, - 0xEE,0xA6,0xE0,0x5C,0xE0,0x77,0xC3,0x41,0x67,0x1B,0x3C,0x07,0x2A,0x06,0x19,0x07, - 0xE4,0x75,0xC6,0x43,0xCC,0x50,0x95,0x23,0x35,0x09,0x14,0x04,0x15,0x05,0x0B,0x04, - 0xEE,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x56,0x14,0x5A,0x12,0x26,0x0A, - 0xEE,0xBB,0xE7,0x7E,0xE9,0x8D,0xCB,0x49,0x67,0x11,0x34,0x07,0x2B,0x0B,0x14,0x07, - 0xED,0xA7,0xE5,0x76,0xE3,0x7E,0xC4,0x4B,0x77,0x14,0x34,0x08,0x27,0x07,0x14,0x04, - 0xE7,0x8B,0xD2,0x4C,0xCA,0x56,0x9E,0x31,0x36,0x0C,0x11,0x07,0x14,0x04,0x0A,0x02, - 0xF0,0x9B,0xEA,0x6F,0xE5,0x81,0xC4,0x43,0x74,0x10,0x30,0x0B,0x2D,0x08,0x1B,0x06, - 0xE6,0x83,0xCA,0x48,0xD9,0x56,0xA7,0x23,0x3B,0x09,0x12,0x09,0x15,0x07,0x0A,0x03, - 0xE5,0x5F,0xCB,0x3C,0xCF,0x48,0x91,0x22,0x31,0x0A,0x17,0x08,0x15,0x04,0x0D,0x02, - 0xD1,0x43,0x91,0x20,0xA9,0x2D,0x54,0x12,0x17,0x07,0x09,0x02,0x0C,0x04,0x05,0x03, -}; -#endif - -// divided into multiple functions to keep rarely-used functionality separate -// so often-used functionality can be optimized better by compiler - -// If write isn't preceded by read, data has this added to it -int const no_read_before_write = 0x2000; - -void SNES_SPC::cpu_write_smp_reg_( int data, rel_time_t time, int addr ) -{ - switch ( addr ) - { - case r_t0target: - case r_t1target: - case r_t2target: { - Timer* t = &m.timers [addr - r_t0target]; - int period = IF_0_THEN_256( data ); - if ( t->period != period ) - { - t = run_timer( t, time ); - #if SPC_MORE_ACCURACY - // Insane behavior when target is written just after counter is - // clocked and counter matches new period and new period isn't 1, 2, 4, or 8 - if ( t->divider == (period & 0xFF) && - t->next_time == time + TIMER_MUL( t, 1 ) && - ((period - 1) | ~0x0F) & period ) - { - //dprintf( "SPC pathological timer target write\n" ); - - // If the period is 3, 5, or 9, there's a probability this behavior won't occur, - // based on the previous period - int prob = 0xFF; - int old_period = t->period & 0xFF; - if ( period == 3 ) prob = glitch_probs [0] [old_period]; - if ( period == 5 ) prob = glitch_probs [1] [old_period]; - if ( period == 9 ) prob = glitch_probs [2] [old_period]; - - // The glitch suppresses incrementing of one of the counter bits, based on - // the lowest set bit in the new period - int b = 1; - while ( !(period & b) ) - b <<= 1; - - if ( (rand() >> 4 & 0xFF) <= prob ) - t->divider = (t->divider - b) & 0xFF; - } - #endif - t->period = period; - } - break; - } - - case r_t0out: - case r_t1out: - case r_t2out: - if ( !SPC_MORE_ACCURACY ) - dprintf( "SPC wrote to counter %d\n", (int) addr - r_t0out ); - - if ( data < no_read_before_write / 2 ) - run_timer( &m.timers [addr - r_t0out], time - 1 )->counter = 0; - break; - - // Registers that act like RAM - case 0x8: - case 0x9: - REGS_IN [addr] = (uint8_t) data; - break; - - case r_test: - if ( (uint8_t) data != 0x0A ) - dprintf( "SPC wrote to test register\n" ); - break; - - case r_control: - // port clears - if ( data & 0x10 ) - { - REGS_IN [r_cpuio0] = 0; - REGS_IN [r_cpuio1] = 0; - } - if ( data & 0x20 ) - { - REGS_IN [r_cpuio2] = 0; - REGS_IN [r_cpuio3] = 0; - } - - // timers - { - for ( int i = 0; i < timer_count; i++ ) - { - Timer* t = &m.timers [i]; - int enabled = data >> i & 1; - if ( t->enabled != enabled ) - { - t = run_timer( t, time ); - t->enabled = enabled; - if ( enabled ) - { - t->divider = 0; - t->counter = 0; - } - } - } - } - enable_rom( data & 0x80 ); - break; - } -} - -void SNES_SPC::cpu_write_smp_reg( int data, rel_time_t time, int addr ) -{ - if ( addr == r_dspdata ) // 99% - dsp_write( data, time ); - else - cpu_write_smp_reg_( data, time, addr ); -} - -void SNES_SPC::cpu_write_high( int data, int i, rel_time_t time ) -{ - if ( i < rom_size ) - { - m.hi_ram [i] = (uint8_t) data; - if ( m.rom_enabled ) - RAM [i + rom_addr] = m.rom [i]; // restore overwritten ROM - } - else - { - assert( *(&(RAM [0]) + i + rom_addr) == (uint8_t) data ); - *(&(RAM [0]) + i + rom_addr) = cpu_pad_fill; // restore overwritten padding - cpu_write( data, i + rom_addr - 0x10000, time ); - } -} - -int const bits_in_int = CHAR_BIT * sizeof (int); - -void SNES_SPC::cpu_write( int data, int addr, rel_time_t time ) -{ - MEM_ACCESS( time, addr ) - - // RAM - RAM [addr] = (uint8_t) data; - int reg = addr - 0xF0; - if ( reg >= 0 ) // 64% - { - // $F0-$FF - if ( reg < reg_count ) // 87% - { - REGS [reg] = (uint8_t) data; - - // Ports - #ifdef SPC_PORT_WRITE_HOOK - if ( (unsigned) (reg - r_cpuio0) < port_count ) - SPC_PORT_WRITE_HOOK( m.spc_time + time, (reg - r_cpuio0), - (uint8_t) data, ®S [r_cpuio0] ); - #endif - - // Registers other than $F2 and $F4-$F7 - //if ( reg != 2 && reg != 4 && reg != 5 && reg != 6 && reg != 7 ) - // TODO: this is a bit on the fragile side - if ( ((~0x2F00 << (bits_in_int - 16)) << reg) < 0 ) // 36% - cpu_write_smp_reg( data, time, reg ); - } - // High mem/address wrap-around - else - { - reg -= rom_addr - 0xF0; - if ( reg >= 0 ) // 1% in IPL ROM area or address wrapped around - cpu_write_high( data, reg, time ); - } - } -} - - -//// CPU read - -inline int SNES_SPC::cpu_read_smp_reg( int reg, rel_time_t time ) -{ - int result = REGS_IN [reg]; - reg -= r_dspaddr; - // DSP addr and data - if ( (unsigned) reg <= 1 ) // 4% 0xF2 and 0xF3 - { - result = REGS [r_dspaddr]; - if ( (unsigned) reg == 1 ) - result = dsp_read( time ); // 0xF3 - } - return result; -} - -int SNES_SPC::cpu_read( int addr, rel_time_t time ) -{ - MEM_ACCESS( time, addr ) - - // RAM - int result = RAM [addr]; - int reg = addr - 0xF0; - if ( reg >= 0 ) // 40% - { - reg -= 0x10; - if ( (unsigned) reg >= 0xFF00 ) // 21% - { - reg += 0x10 - r_t0out; - - // Timers - if ( (unsigned) reg < timer_count ) // 90% - { - Timer* t = &m.timers [reg]; - if ( time >= t->next_time ) - t = run_timer_( t, time ); - result = t->counter; - t->counter = 0; - } - // Other registers - else if ( reg < 0 ) // 10% - { - result = cpu_read_smp_reg( reg + r_t0out, time ); - } - else // 1% - { - assert( reg + (r_t0out + 0xF0 - 0x10000) < 0x100 ); - result = cpu_read( reg + (r_t0out + 0xF0 - 0x10000), time ); - } - } - } - - return result; -} - - -//// Run - -// Prefix and suffix for CPU emulator function -#define SPC_CPU_RUN_FUNC \ -BOOST::uint8_t* SNES_SPC::run_until_( time_t end_time )\ -{\ - rel_time_t rel_time = m.spc_time - end_time;\ - /*assert( rel_time <= 0 );*/\ - m.spc_time = end_time;\ - m.dsp_time += rel_time;\ - m.timers [0].next_time += rel_time;\ - m.timers [1].next_time += rel_time;\ - m.timers [2].next_time += rel_time; - -#define SPC_CPU_RUN_FUNC_END \ - m.spc_time += rel_time;\ - m.dsp_time -= rel_time;\ - m.timers [0].next_time -= rel_time;\ - m.timers [1].next_time -= rel_time;\ - m.timers [2].next_time -= rel_time;\ - /*assert( m.spc_time >= end_time );*/\ - return ®S [r_cpuio0];\ -} - -int const cpu_lag_max = 12 - 1; // DIV YA,X takes 12 clocks - -void SNES_SPC::end_frame( time_t end_time ) -{ - // Catch CPU up to as close to end as possible. If final instruction - // would exceed end, does NOT execute it and leaves m.spc_time < end. - if ( end_time > m.spc_time ) - run_until_( end_time ); - - m.spc_time -= end_time; - m.extra_clocks += end_time; - - // Greatest number of clocks early that emulation can stop early due to - // not being able to execute current instruction without going over - // allowed time. - assert( -cpu_lag_max <= m.spc_time && m.spc_time <= cpu_lag_max ); - - // Catch timers up to CPU - for ( int i = 0; i < timer_count; i++ ) - run_timer( &m.timers [i], 0 ); - - // Catch DSP up to CPU - if ( m.dsp_time < 0 ) - { - RUN_DSP( 0, max_reg_time ); - } - - // Save any extra samples beyond what should be generated - if ( m.buf_begin ) - save_extra(); -} - -// Inclusion here allows static memory access functions and better optimization -#include "SPC_CPU.h" diff --git a/apu/SNES_SPC.h b/apu/SNES_SPC.h deleted file mode 100644 index baf90063..00000000 --- a/apu/SNES_SPC.h +++ /dev/null @@ -1,316 +0,0 @@ -// SNES SPC-700 APU emulator - -// snes_spc 0.9.0 -#ifndef SNES_SPC_H -#define SNES_SPC_H - -#include "SPC_DSP.h" -#include "blargg_endian.h" - -#ifdef DEBUGGER -#include "snes9x.h" -#include "display.h" -#include "debug.h" -#endif - -struct SNES_SPC { -public: - typedef BOOST::uint8_t uint8_t; - - // Must be called once before using - blargg_err_t init(); - - // Sample pairs generated per second - enum { sample_rate = 32000 }; - -// Emulator use - - // Sets IPL ROM data. Library does not include ROM data. Most SPC music files - // don't need ROM, but a full emulator must provide this. - enum { rom_size = 0x40 }; - void init_rom( uint8_t const rom [rom_size] ); - - // Sets destination for output samples - typedef short sample_t; - void set_output( sample_t* out, int out_size ); - - // Number of samples written to output since last set - int sample_count() const; - - // Resets SPC to power-on state. This resets your output buffer, so you must - // call set_output() after this. - void reset(); - - // Emulates pressing reset switch on SNES. This resets your output buffer, so - // you must call set_output() after this. - void soft_reset(); - - // 1024000 SPC clocks per second, sample pair every 32 clocks - typedef int time_t; - enum { clock_rate = 1024000 }; - enum { clocks_per_sample = 32 }; - - // Emulated port read/write at specified time - enum { port_count = 4 }; - int read_port ( time_t, int port ); - void write_port( time_t, int port, int data ); - - // Runs SPC to end_time and starts a new time frame at 0 - void end_frame( time_t end_time ); - -// Sound control - - // Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events). - // Reduces emulation accuracy. - enum { voice_count = 8 }; - void mute_voices( int mask ); - - // If true, prevents channels and global volumes from being phase-negated. - // Only supported by fast DSP. - void disable_surround( bool disable = true ); - - // Sets tempo, where tempo_unit = normal, tempo_unit / 2 = half speed, etc. - enum { tempo_unit = 0x100 }; - void set_tempo( int ); - -// SPC music files - - // Loads SPC data into emulator - enum { spc_min_file_size = 0x10180 }; - enum { spc_file_size = 0x10200 }; - blargg_err_t load_spc( void const* in, long size ); - - // Clears echo region. Useful after loading an SPC as many have garbage in echo. - void clear_echo(); - - // Plays for count samples and write samples to out. Discards samples if out - // is NULL. Count must be a multiple of 2 since output is stereo. - blargg_err_t play( int count, sample_t* out ); - - // Skips count samples. Several times faster than play() when using fast DSP. - blargg_err_t skip( int count ); - -// State save/load (only available with accurate DSP) - -#if !SPC_NO_COPY_STATE_FUNCS - // Saves/loads state - enum { state_size = 68 * 1024L }; // maximum space needed when saving - typedef SPC_DSP::copy_func_t copy_func_t; - void copy_state( unsigned char** io, copy_func_t ); - - // Writes minimal header to spc_out - static void init_header( void* spc_out ); - - // Saves emulator state as SPC file data. Writes spc_file_size bytes to spc_out. - // Does not set up SPC header; use init_header() for that. - void save_spc( void* spc_out ); - - // Returns true if new key-on events occurred since last check. Useful for - // trimming silence while saving an SPC. - bool check_kon(); -#endif - -//// Snes9x Accessor - - void spc_allow_time_overflow( bool ); - - void dsp_set_spc_snapshot_callback( void (*callback) (void) ); - void dsp_dump_spc_snapshot( void ); - void dsp_set_stereo_switch( int ); - uint8_t dsp_reg_value( int, int ); - int dsp_envx_value( int ); - -//// Snes9x Debugger - -#ifdef DEBUGGER - void debug_toggle_trace( void ); - bool debug_is_enabled( void ); - void debug_do_trace( int, int, int, uint8_t const *, uint8_t *, int, int, int, int ); - void debug_op_print( char *, int, int, int, uint8_t const *, uint8_t *, int, int, int, int ); - void debug_io_print( char * ); -#endif - -public: - BLARGG_DISABLE_NOTHROW - - typedef BOOST::uint16_t uint16_t; - - // Time relative to m_spc_time. Speeds up code a bit by eliminating need to - // constantly add m_spc_time to time from CPU. CPU uses time that ends at - // 0 to eliminate reloading end time every instruction. It pays off. - typedef int rel_time_t; - - struct Timer - { - rel_time_t next_time; // time of next event - int prescaler; - int period; - int divider; - int enabled; - int counter; - }; - enum { reg_count = 0x10 }; - enum { timer_count = 3 }; - enum { extra_size = SPC_DSP::extra_size }; - - enum { signature_size = 35 }; - -private: - SPC_DSP dsp; - - #if SPC_LESS_ACCURATE - static signed char const reg_times_ [256]; - signed char reg_times [256]; - #endif - - struct state_t - { - Timer timers [timer_count]; - - uint8_t smp_regs [2] [reg_count]; - - struct - { - int pc; - int a; - int x; - int y; - int psw; - int sp; - } cpu_regs; - - rel_time_t dsp_time; - time_t spc_time; - bool echo_accessed; - - int tempo; - int skipped_kon; - int skipped_koff; - const char* cpu_error; - - int extra_clocks; - sample_t* buf_begin; - sample_t const* buf_end; - sample_t* extra_pos; - sample_t extra_buf [extra_size]; - - int rom_enabled; - uint8_t rom [rom_size]; - uint8_t hi_ram [rom_size]; - - unsigned char cycle_table [256]; - - struct - { - // padding to neutralize address overflow - union { - uint8_t padding1 [0x100]; - uint16_t align; // makes compiler align data for 16-bit access - } padding1 [1]; - uint8_t ram [0x10000]; - uint8_t padding2 [0x100]; - } ram; - }; - state_t m; - - enum { rom_addr = 0xFFC0 }; - - enum { skipping_time = 127 }; - - // Value that padding should be filled with - enum { cpu_pad_fill = 0xFF }; - - enum { - r_test = 0x0, r_control = 0x1, - r_dspaddr = 0x2, r_dspdata = 0x3, - r_cpuio0 = 0x4, r_cpuio1 = 0x5, - r_cpuio2 = 0x6, r_cpuio3 = 0x7, - r_f8 = 0x8, r_f9 = 0x9, - r_t0target = 0xA, r_t1target = 0xB, r_t2target = 0xC, - r_t0out = 0xD, r_t1out = 0xE, r_t2out = 0xF - }; - - void timers_loaded(); - void enable_rom( int enable ); - void reset_buf(); - void save_extra(); - void load_regs( uint8_t const in [reg_count] ); - void ram_loaded(); - void regs_loaded(); - void reset_time_regs(); - void reset_common( int timer_counter_init ); - - Timer* run_timer_ ( Timer* t, rel_time_t ); - Timer* run_timer ( Timer* t, rel_time_t ); - int dsp_read ( rel_time_t ); - void dsp_write ( int data, rel_time_t ); - void cpu_write_smp_reg_( int data, rel_time_t, int addr ); - void cpu_write_smp_reg ( int data, rel_time_t, int addr ); - void cpu_write_high ( int data, int i, rel_time_t ); - void cpu_write ( int data, int addr, rel_time_t ); - int cpu_read_smp_reg ( int i, rel_time_t ); - int cpu_read ( int addr, rel_time_t ); - unsigned CPU_mem_bit ( uint8_t const* pc, rel_time_t ); - - bool check_echo_access ( int addr ); - uint8_t* run_until_( time_t end_time ); - - struct spc_file_t - { - char signature [signature_size]; - uint8_t has_id666; - uint8_t version; - uint8_t pcl, pch; - uint8_t a; - uint8_t x; - uint8_t y; - uint8_t psw; - uint8_t sp; - char text [212]; - uint8_t ram [0x10000]; - uint8_t dsp [128]; - uint8_t unused [0x40]; - uint8_t ipl_rom [0x40]; - }; - - static char const signature [signature_size + 1]; - - void save_regs( uint8_t out [reg_count] ); - -// Snes9x timing hack - bool allow_time_overflow; -// Snes9x debugger -#ifdef DEBUGGER - FILE *apu_trace; - bool debug_trace; -#endif -}; - -#include - -inline int SNES_SPC::sample_count() const { return (m.extra_clocks >> 5) * 2; } - -inline int SNES_SPC::read_port( time_t t, int port ) -{ - assert( (unsigned) port < port_count ); - return run_until_( t ) [port]; -} - -inline void SNES_SPC::write_port( time_t t, int port, int data ) -{ - assert( (unsigned) port < port_count ); - run_until_( t ) [0x10 + port] = data; - m.ram.ram [0xF4 + port] = data; -} - -inline void SNES_SPC::mute_voices( int mask ) { dsp.mute_voices( mask ); } - -inline void SNES_SPC::disable_surround( bool disable ) { dsp.disable_surround( disable ); } - -#if !SPC_NO_COPY_STATE_FUNCS -inline bool SNES_SPC::check_kon() { return dsp.check_kon(); } -#endif - -inline void SNES_SPC::spc_allow_time_overflow( bool allow ) { allow_time_overflow = allow; } - -#endif diff --git a/apu/SNES_SPC_misc.cpp b/apu/SNES_SPC_misc.cpp deleted file mode 100644 index 078120d2..00000000 --- a/apu/SNES_SPC_misc.cpp +++ /dev/null @@ -1,855 +0,0 @@ -// SPC emulation support: init, sample buffering, reset, SPC loading - -// snes_spc 0.9.0. http://www.slack.net/~ant/ - -#include "SNES_SPC.h" - -#include - -/* Copyright (C) 2004-2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -#define RAM (m.ram.ram) -#define REGS (m.smp_regs [0]) -#define REGS_IN (m.smp_regs [1]) - -// (n ? n : 256) -#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1) - - -//// Init - -blargg_err_t SNES_SPC::init() -{ - memset( &m, 0, sizeof m ); - dsp.init( RAM ); - - m.tempo = tempo_unit; - - // Most SPC music doesn't need ROM, and almost all the rest only rely - // on these two bytes - m.rom [0x3E] = 0xFF; - m.rom [0x3F] = 0xC0; - - static unsigned char const cycle_table [128] = - {// 01 23 45 67 89 AB CD EF - 0x28,0x47,0x34,0x36,0x26,0x54,0x54,0x68, // 0 - 0x48,0x47,0x45,0x56,0x55,0x65,0x22,0x46, // 1 - 0x28,0x47,0x34,0x36,0x26,0x54,0x54,0x74, // 2 - 0x48,0x47,0x45,0x56,0x55,0x65,0x22,0x38, // 3 - 0x28,0x47,0x34,0x36,0x26,0x44,0x54,0x66, // 4 - 0x48,0x47,0x45,0x56,0x55,0x45,0x22,0x43, // 5 - 0x28,0x47,0x34,0x36,0x26,0x44,0x54,0x75, // 6 - 0x48,0x47,0x45,0x56,0x55,0x55,0x22,0x36, // 7 - 0x28,0x47,0x34,0x36,0x26,0x54,0x52,0x45, // 8 - 0x48,0x47,0x45,0x56,0x55,0x55,0x22,0xC5, // 9 - 0x38,0x47,0x34,0x36,0x26,0x44,0x52,0x44, // A - 0x48,0x47,0x45,0x56,0x55,0x55,0x22,0x34, // B - 0x38,0x47,0x45,0x47,0x25,0x64,0x52,0x49, // C - 0x48,0x47,0x56,0x67,0x45,0x55,0x22,0x83, // D - 0x28,0x47,0x34,0x36,0x24,0x53,0x43,0x40, // E - 0x48,0x47,0x45,0x56,0x34,0x54,0x22,0x60, // F - }; - - // unpack cycle table - for ( int i = 0; i < 128; i++ ) - { - int n = cycle_table [i]; - m.cycle_table [i * 2 + 0] = n >> 4; - m.cycle_table [i * 2 + 1] = n & 0x0F; - } - - allow_time_overflow = false; - - dsp.rom = m.rom; - dsp.hi_ram = m.hi_ram; - -#ifdef DEBUGGER - apu_trace = NULL; - debug_trace = false; -#endif - - #if SPC_LESS_ACCURATE - memcpy( reg_times, reg_times_, sizeof reg_times ); - #endif - - reset(); - return 0; -} - -void SNES_SPC::init_rom( uint8_t const in [rom_size] ) -{ - memcpy( m.rom, in, sizeof m.rom ); -} - -void SNES_SPC::set_tempo( int t ) -{ - m.tempo = t; - int const timer2_shift = 4; // 64 kHz - int const other_shift = 3; // 8 kHz - - #if SPC_DISABLE_TEMPO - m.timers [2].prescaler = timer2_shift; - m.timers [1].prescaler = timer2_shift + other_shift; - m.timers [0].prescaler = timer2_shift + other_shift; - #else - if ( !t ) - t = 1; - int const timer2_rate = 1 << timer2_shift; - int rate = (timer2_rate * tempo_unit + (t >> 1)) / t; - if ( rate < timer2_rate / 4 ) - rate = timer2_rate / 4; // max 4x tempo - m.timers [2].prescaler = rate; - m.timers [1].prescaler = rate << other_shift; - m.timers [0].prescaler = rate << other_shift; - #endif -} - -// Timer registers have been loaded. Applies these to the timers. Does not -// reset timer prescalers or dividers. -void SNES_SPC::timers_loaded() -{ - int i; - for ( i = 0; i < timer_count; i++ ) - { - Timer* t = &m.timers [i]; - t->period = IF_0_THEN_256( REGS [r_t0target + i] ); - t->enabled = REGS [r_control] >> i & 1; - t->counter = REGS_IN [r_t0out + i] & 0x0F; - } - - set_tempo( m.tempo ); -} - -// Loads registers from unified 16-byte format -void SNES_SPC::load_regs( uint8_t const in [reg_count] ) -{ - memcpy( REGS, in, reg_count ); - memcpy( REGS_IN, REGS, reg_count ); - - // These always read back as 0 - REGS_IN [r_test ] = 0; - REGS_IN [r_control ] = 0; - REGS_IN [r_t0target] = 0; - REGS_IN [r_t1target] = 0; - REGS_IN [r_t2target] = 0; -} - -// RAM was just loaded from SPC, with $F0-$FF containing SMP registers -// and timer counts. Copies these to proper registers. -void SNES_SPC::ram_loaded() -{ - m.rom_enabled = dsp.rom_enabled = 0; - load_regs( &RAM [0xF0] ); - - // Put STOP instruction around memory to catch PC underflow/overflow - memset( m.ram.padding1, cpu_pad_fill, sizeof m.ram.padding1 ); - memset( m.ram.padding2, cpu_pad_fill, sizeof m.ram.padding2 ); -} - -// Registers were just loaded. Applies these new values. -void SNES_SPC::regs_loaded() -{ - enable_rom( REGS [r_control] & 0x80 ); - timers_loaded(); -} - -void SNES_SPC::reset_time_regs() -{ - m.cpu_error = 0; - m.echo_accessed = 0; - m.spc_time = 0; - m.dsp_time = 0; - #if SPC_LESS_ACCURATE - m.dsp_time = clocks_per_sample + 1; - #endif - - for ( int i = 0; i < timer_count; i++ ) - { - Timer* t = &m.timers [i]; - t->next_time = 1; - t->divider = 0; - } - - regs_loaded(); - - m.extra_clocks = 0; - reset_buf(); -} - -void SNES_SPC::reset_common( int timer_counter_init ) -{ - int i; - for ( i = 0; i < timer_count; i++ ) - REGS_IN [r_t0out + i] = timer_counter_init; - - // Run IPL ROM - memset( &m.cpu_regs, 0, sizeof m.cpu_regs ); - m.cpu_regs.pc = rom_addr; - - REGS [r_test ] = 0x0A; - REGS [r_control] = 0xB0; // ROM enabled, clear ports - for ( i = 0; i < port_count; i++ ) - REGS_IN [r_cpuio0 + i] = 0; - - reset_time_regs(); -} - -void SNES_SPC::soft_reset() -{ - reset_common( 0 ); - dsp.soft_reset(); -} - -void SNES_SPC::reset() -{ - m.cpu_regs.pc = 0xFFC0; - m.cpu_regs.a = 0x00; - m.cpu_regs.x = 0x00; - m.cpu_regs.y = 0x00; - m.cpu_regs.psw = 0x02; - m.cpu_regs.sp = 0xEF; - memset( RAM, 0x00, 0x10000 ); - ram_loaded(); - reset_common( 0x0F ); - dsp.reset(); -} - -char const SNES_SPC::signature [signature_size + 1] = - "SNES-SPC700 Sound File Data v0.30\x1A\x1A"; - -blargg_err_t SNES_SPC::load_spc( void const* data, long size ) -{ - spc_file_t const* const spc = (spc_file_t const*) data; - - // be sure compiler didn't insert any padding into fle_t - assert( sizeof (spc_file_t) == spc_min_file_size + 0x80 ); - - // Check signature and file size - if ( size < signature_size || memcmp( spc, signature, 27 ) ) - return "Not an SPC file"; - - if ( size < spc_min_file_size ) - return "Corrupt SPC file"; - - // CPU registers - m.cpu_regs.pc = spc->pch * 0x100 + spc->pcl; - m.cpu_regs.a = spc->a; - m.cpu_regs.x = spc->x; - m.cpu_regs.y = spc->y; - m.cpu_regs.psw = spc->psw; - m.cpu_regs.sp = spc->sp; - - // RAM and registers - memcpy( RAM, spc->ram, 0x10000 ); - ram_loaded(); - - // DSP registers - dsp.load( spc->dsp ); - - reset_time_regs(); - - return 0; -} - -void SNES_SPC::clear_echo() -{ - if ( !(dsp.read( SPC_DSP::r_flg ) & 0x20) ) - { - int addr = 0x100 * dsp.read( SPC_DSP::r_esa ); - int end = addr + 0x800 * (dsp.read( SPC_DSP::r_edl ) & 0x0F); - if ( end > 0x10000 ) - end = 0x10000; - memset( &RAM [addr], 0xFF, end - addr ); - } -} - - -//// Sample output - -void SNES_SPC::reset_buf() -{ - // Start with half extra buffer of silence - sample_t* out = m.extra_buf; - while ( out < &m.extra_buf [extra_size / 2] ) - *out++ = 0; - - m.extra_pos = out; - m.buf_begin = 0; - - dsp.set_output( 0, 0 ); -} - -void SNES_SPC::set_output( sample_t* out, int size ) -{ - require( (size & 1) == 0 ); // size must be even - - m.extra_clocks &= clocks_per_sample - 1; - if ( out ) - { - sample_t const* out_end = out + size; - m.buf_begin = out; - m.buf_end = out_end; - - // Copy extra to output - sample_t const* in = m.extra_buf; - while ( in < m.extra_pos && out < out_end ) - *out++ = *in++; - - // Handle output being full already - if ( out >= out_end ) - { - // Have DSP write to remaining extra space - out = dsp.extra(); - out_end = &dsp.extra() [extra_size]; - - // Copy any remaining extra samples as if DSP wrote them - while ( in < m.extra_pos ) - *out++ = *in++; - assert( out <= out_end ); - } - - dsp.set_output( out, out_end - out ); - } - else - { - reset_buf(); - } -} - -void SNES_SPC::save_extra() -{ - // Get end pointers - sample_t const* main_end = m.buf_end; // end of data written to buf - sample_t const* dsp_end = dsp.out_pos(); // end of data written to dsp.extra() - if ( m.buf_begin <= dsp_end && dsp_end <= main_end ) - { - main_end = dsp_end; - dsp_end = dsp.extra(); // nothing in DSP's extra - } - - // Copy any extra samples at these ends into extra_buf - sample_t* out = m.extra_buf; - sample_t const* in; - for ( in = m.buf_begin + sample_count(); in < main_end; in++ ) - *out++ = *in; - for ( in = dsp.extra(); in < dsp_end ; in++ ) - *out++ = *in; - - m.extra_pos = out; - assert( out <= &m.extra_buf [extra_size] ); -} - -blargg_err_t SNES_SPC::play( int count, sample_t* out ) -{ - require( (count & 1) == 0 ); // must be even - if ( count ) - { - set_output( out, count ); - end_frame( count * (clocks_per_sample / 2) ); - } - - const char* err = m.cpu_error; - m.cpu_error = 0; - return err; -} - -blargg_err_t SNES_SPC::skip( int count ) -{ - #if SPC_LESS_ACCURATE - if ( count > 2 * sample_rate * 2 ) - { - set_output( 0, 0 ); - - // Skip a multiple of 4 samples - time_t end = count; - count = (count & 3) + 1 * sample_rate * 2; - end = (end - count) * (clocks_per_sample / 2); - - m.skipped_kon = 0; - m.skipped_koff = 0; - - // Preserve DSP and timer synchronization - // TODO: verify that this really preserves it - int old_dsp_time = m.dsp_time + m.spc_time; - m.dsp_time = end - m.spc_time + skipping_time; - end_frame( end ); - m.dsp_time = m.dsp_time - skipping_time + old_dsp_time; - - dsp.write( SPC_DSP::r_koff, m.skipped_koff & ~m.skipped_kon ); - dsp.write( SPC_DSP::r_kon , m.skipped_kon ); - clear_echo(); - } - #endif - - return play( count, 0 ); -} - -//// Snes9x Accessor - -void SNES_SPC::dsp_set_spc_snapshot_callback( void (*callback) (void) ) -{ - dsp.set_spc_snapshot_callback( callback ); -} - -void SNES_SPC::dsp_dump_spc_snapshot( void ) -{ - dsp.dump_spc_snapshot(); -} - -void SNES_SPC::dsp_set_stereo_switch( int value ) -{ - dsp.set_stereo_switch( value ); -} - -SNES_SPC::uint8_t SNES_SPC::dsp_reg_value( int ch, int addr ) -{ - return dsp.reg_value( ch, addr ); -} - -int SNES_SPC::dsp_envx_value( int ch ) -{ - return dsp.envx_value( ch ); -} - -//// Snes9x debugger - -#ifdef DEBUGGER - -void SNES_SPC::debug_toggle_trace( void ) -{ - debug_trace = !debug_trace; - - if (debug_trace) - { - printf("APU tracing enabled.\n"); - ENSURE_TRACE_OPEN(apu_trace, "apu_trace.log", "wb") - } - else - { - printf("APU tracing disabled.\n"); - fclose(apu_trace); - apu_trace = NULL; - } -} - -bool SNES_SPC::debug_is_enabled( void ) { return debug_trace; } - -void SNES_SPC::debug_do_trace( int a, int x, int y, uint8_t const *pc, uint8_t *sp, int psw, int c, int nz, int dp ) -{ - char msg[512]; - - ENSURE_TRACE_OPEN(apu_trace, "apu_trace.log", "a") - - debug_op_print(msg, a, x, y, pc, sp, psw, c, nz, dp); - fprintf(apu_trace, "%s ", msg); - debug_io_print(msg); - fprintf(apu_trace, "%s ", msg); - S9xPrintHVPosition(msg); - fprintf(apu_trace, "%s\n", msg); -} - -void SNES_SPC::debug_op_print( char *buffer, int a, int x, int y, uint8_t const *pc, uint8_t *sp, int psw, int c, int nz, int dp ) -{ - static char mnemonics[256][20] = - { - "NOP", - "TCALL 0", - "SET1 $%02X.0", - "BBS $%02X.0,$%04X", - "OR A,$%02X", - "OR A,!$%04X", - "OR A,(X)", - "OR A,[$%02X+X]", - "OR A,#$%02X", - "OR $%02X,$%02X", - "OR1 C,$%04X.%d", - "ASL $%02X", - "MOV !$%04X,Y", - "PUSH PSW", - "TSET1 !$%04X", - "BRK", - "BPL $%04X", - "TCALL 1", - "CLR1 $%02X.0", - "BBC $%02X.0,$%04X", - "OR A,$%02X+X", - "OR A,!$%04X+X", - "OR A,!$%04X+Y", - "OR A,[$%02X]+Y", - "OR $%02X,#$%02X", - "OR (X),(Y)", - "DECW $%02X", - "ASL $%02X+X", - "ASL A", - "DEC X", - "CMP X,!$%04X", - "JMP [!$%04X+X]", - "CLRP", - "TCALL 2", - "SET1 $%02X.1", - "BBS $%02X.1,$%04X", - "AND A,$%02X", - "AND A,!$%04X", - "AND A,(X)", - "AND A,[$%02X+X]", - "AND A,#$%02X", - "AND $%02X,$%02X", - "OR1 C,/$%04X.%d", - "ROL $%02X", - "ROL !$%04X", - "PUSH A", - "CBNE $%02X,$%04X", - "BRA $%04X", - "BMI $%04X", - "TCALL 3", - "CLR1 $%02X.1", - "BBC $%02X.1,$%04X", - "AND A,$%02X+X", - "AND A,!$%04X+X", - "AND A,!$%04X+Y", - "AND A,[$%02X]+Y", - "AND $%02X,#$%02X", - "AND (X),(Y)", - "INCW $%02X", - "ROL $%02X+X", - "ROL A", - "INC X", - "CMP X,$%02X", - "CALL !$%04X", - "SETP", - "TCALL 4", - "SET1 $%02X.2", - "BBS $%02X.2,$%04X", - "EOR A,$%02X", - "EOR A,!$%04X", - "EOR A,(X)", - "EOR A,[$%02X+X]", - "EOR A,#$%02X", - "EOR $%02X,$%02X", - "AND1 C,$%04X.%d", - "LSR $%02X", - "LSR !$%04X", - "PUSH X", - "TCLR1 !$%04X", - "PCALL $%02X", - "BVC $%04X", - "TCALL 5", - "CLR1 $%02X.2", - "BBC $%02X.2,$%04X", - "EOR A,$%02X+X", - "EOR A,!$%04X+X", - "EOR A,!$%04X+Y", - "EOR A,[$%02X]+Y", - "EOR $%02X,#$%02X", - "EOR (X),(Y)", - "CMPW YA,$%02X", - "LSR $%02X+X", - "LSR A", - "MOV X,A", - "CMP Y,!$%04X", - "JMP !$%04X", - "CLRC", - "TCALL 6", - "SET1 $%02X.3", - "BBS $%02X.3,$%04X", - "CMP A,$%02X", - "CMP A,!$%04X", - "CMP A,(X)", - "CMP A,[$%02X+X]", - "CMP A,#$%02X", - "CMP $%02X,$%02X", - "AND1 C,/$%04X.%d", - "ROR $%02X", - "ROR !$%04X", - "PUSH Y", - "DBNZ $%02X,$%04X", - "RET", - "BVS $%04X", - "TCALL 7", - "CLR1 $%02X.3", - "BBC $%02X.3,$%04X", - "CMP A,$%02X+X", - "CMP A,!$%04X+X", - "CMP A,!$%04X+Y", - "CMP A,[$%02X]+Y", - "CMP $%02X,#$%02X", - "CMP (X),(Y)", - "ADDW YA,$%02X", - "ROR $%02X+X", - "ROR A", - "MOV A,X", - "CMP Y,$%02X", - "RET1", - "SETC", - "TCALL 8", - "SET1 $%02X.4", - "BBS $%02X.4,$%04X", - "ADC A,$%02X", - "ADC A,!$%04X", - "ADC A,(X)", - "ADC A,[$%02X+X]", - "ADC A,#$%02X", - "ADC $%02X,$%02X", - "EOR1 C,$%04X.%d", - "DEC $%02X", - "DEC !$%04X", - "MOV Y,#$%02X", - "POP PSW", - "MOV $%02X,#$%02X", - "BCC $%04X", - "TCALL 9", - "CLR1 $%02X.4", - "BBC $%02X.4,$%04X", - "ADC A,$%02X+X", - "ADC A,!$%04X+X", - "ADC A,!$%04X+Y", - "ADC A,[$%02X]+Y", - "ADC $%02X,#$%02X", - "ADC (X),(Y)", - "SUBW YA,$%02X", - "DEC $%02X+X", - "DEC A", - "MOV X,SP", - "DIV YA,X", - "XCN A", - "EI", - "TCALL 10", - "SET1 $%02X.5", - "BBS $%02X.5,$%04X", - "SBC A,$%02X", - "SBC A,!$%04X", - "SBC A,(X)", - "SBC A,[$%02X+X]", - "SBC A,#$%02X", - "SBC $%02X,$%02X", - "MOV1 C,$%04X.%d", - "INC $%02X", - "INC !$%04X", - "CMP Y,#$%02X", - "POP A", - "MOV (X)+,A", - "BCS $%04X", - "TCALL 11", - "CLR1 $%02X.5", - "BBC $%02X.5,$%04X", - "SBC A,$%02X+X", - "SBC A,!$%04X+X", - "SBC A,!$%04X+Y", - "SBC A,[$%02X]+Y", - "SBC $%02X,#$%02X", - "SBC (X),(Y)", - "MOVW YA,$%02X", - "INC $%02X+X", - "INC A", - "MOV SP,X", - "DAS A", - "MOV A,(X)+", - "DI", - "TCALL 12", - "SET1 $%02X.6", - "BBS $%02X.6,$%04X", - "MOV $%02X,A", - "MOV !$%04X,A", - "MOV (X),A", - "MOV [$%02X+X],A", - "CMP X,#$%02X", - "MOV !$%04X,X", - "MOV1 $%04X.%d,C", - "MOV $%02X,Y", - "ASL !$%04X", - "MOV X,#$%02X", - "POP X", - "MUL YA", - "BNE $%04X", - "TCALL 13", - "CLR1 $%02X.6", - "BBC $%02X.6,$%04X", - "MOV $%02X+X,A", - "MOV !$%04X+X,A", - "MOV !$%04X+Y,A", - "MOV [$%02X]+Y,A", - "MOV $%02X,X", - "MOV $%02X+Y,X", - "MOVW $%02X,YA", - "MOV $%02X+X,Y", - "DEC Y", - "MOV A,Y", - "CBNE $%02X+X,$%04X", - "DAA A", - "CLRV", - "TCALL 14", - "SET1 $%02X.7", - "BBS $%02X.7,$%04X", - "MOV A,$%02X", - "MOV A,!$%04X", - "MOV A,(X)", - "MOV A,[$%02X+X]", - "MOV A,#$%02X", - "MOV X,!$%04X", - "NOT1 $%04X.%d", - "MOV Y,$%02X", - "MOV Y,!$%04X", - "NOTC", - "POP Y", - "SLEEP", - "BEQ $%04X", - "TCALL 15", - "CLR1 $%02X.7", - "BBC $%02X.7,$%04X", - "MOV A,$%02X+X", - "MOV A,!$%04X+X", - "MOV A,!$%04X+Y", - "MOV A,[$%02X]+Y", - "MOV X,$%02X", - "MOV X,$%02X+Y", - "MOV $%02X,$%02X", - "MOV Y,$%02X+X", - "INC Y", - "MOV Y,A", - "DBNZ Y,$%04X", - "STOP" - }; - - static int modes[256] = - { - 2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 2, 1, 2, - 7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 1, 1, - 2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 2, 5, 7, - 7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 0, 1, - 2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 2, 1, 0, - 7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 1, 1, - 2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 2, 5, 2, - 7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 0, 2, - 2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 0, 2, 4, - 7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 2, 2, - 2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 0, 2, 2, - 7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 2, 2, - 2, 2, 0, 5, 0, 1, 2, 0, 0, 1, 6, 0, 1, 0, 2, 2, - 7, 2, 0, 5, 0, 1, 1, 0, 0, 0, 0, 0, 2, 2, 5, 2, - 2, 2, 0, 5, 0, 1, 2, 0, 0, 1, 6, 0, 1, 2, 2, 2, - 7, 2, 0, 5, 0, 1, 1, 0, 0, 0, 3, 0, 2, 2, 7, 2 - }; - - static int modesToBytes[] = - { - 2, 3, 1, 3, 3, 3, 3, 2 - }; - - int const n80 = 0x80; // nz - int const p20 = 0x20; // dp - int const z02 = 0x02; // nz - int const c01 = 0x01; // c - - #define GET_PC() (pc - ram) - #define GET_SP() (sp - 0x101 - ram) - #define GET_PSW( out )\ - {\ - out = psw & ~(n80 | p20 | z02 | c01);\ - out |= c >> 8 & c01;\ - out |= dp >> 3 & p20;\ - out |= ((nz >> 4) | nz) & n80;\ - if ( !(uint8_t) nz ) out |= z02;\ - } - - uint8_t const *ram = RAM; - - int addr; - int tsp, tpsw; - uint8_t d0, d1, d2; - - addr = GET_PC(); - tsp = GET_SP(); - GET_PSW(tpsw); - - d0 = *pc; - d1 = (addr < 0xffff) ? *(pc + 1) : 0; - d2 = (addr < 0xfffe) ? *(pc + 2) : 0; - - int mode = modes[d0]; - int bytes = modesToBytes[mode]; - char mnem[100]; - - switch (bytes) - { - case 1: - sprintf(buffer, "%04X %02X ", addr, d0); - break; - - case 2: - sprintf(buffer, "%04X %02X %02X ", addr, d0, d1); - break; - - case 3: - sprintf(buffer, "%04X %02X %02X %02X ", addr, d0, d1, d2); - break; - } - - switch (mode) - { - case 0: - sprintf(mnem, mnemonics[d0], d1); - break; - - case 1: - sprintf(mnem, mnemonics[d0], d1 + (d2 << 8)); - break; - - case 2: - strcpy (mnem, mnemonics[d0]); - break; - - case 3: - sprintf(mnem, mnemonics[d0], d2, d1); - break; - - case 4: - sprintf(mnem, mnemonics[d0], d2, d1); - break; - - case 5: - sprintf(mnem, mnemonics[d0], d1, addr + 3 + (int8_t) d2); - break; - - case 6: - sprintf(mnem, mnemonics[d0], (d1 + (d2 << 8)) & 0x1fff, d2 >> 5); - break; - - case 7: - sprintf(mnem, mnemonics[d0], addr + 2 + (int8_t) d1); - break; - } - - sprintf(buffer, "%s %-20s A:%02X X:%02X Y:%02X S:%02X P:%c%c%c%c%c%c%c%c ROM:%d", - buffer, mnem, a, x, y, tsp, - (tpsw & 0x80) ? 'N' : 'n', - (tpsw & 0x40) ? 'V' : 'v', - (tpsw & 0x20) ? 'P' : 'p', - (tpsw & 0x10) ? 'B' : 'b', - (tpsw & 0x08) ? 'H' : 'h', - (tpsw & 0x04) ? 'I' : 'i', - (tpsw & 0x02) ? 'Z' : 'z', - (tpsw & 0x01) ? 'C' : 'c', - m.rom_enabled ? 1 : 0); -} - -void SNES_SPC::debug_io_print( char *buffer ) -{ - sprintf(buffer, "i/o %02X/%02X %02X/%02X %02X/%02X %02X/%02X", - m.smp_regs[1][r_cpuio0], m.smp_regs[0][r_cpuio0], - m.smp_regs[1][r_cpuio1], m.smp_regs[0][r_cpuio1], - m.smp_regs[1][r_cpuio2], m.smp_regs[0][r_cpuio2], - m.smp_regs[1][r_cpuio3], m.smp_regs[0][r_cpuio3]); -} - -#endif diff --git a/apu/SNES_SPC_state.cpp b/apu/SNES_SPC_state.cpp deleted file mode 100644 index 3d9d3f3a..00000000 --- a/apu/SNES_SPC_state.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// SPC emulation state save/load: copy_state(), save_spc() -// Separate file to avoid linking in unless needed - -// snes_spc 0.9.0. http://www.slack.net/‾ant/ - -#include "SNES_SPC.h" - -#if !SPC_NO_COPY_STATE_FUNCS - -#include - -/* Copyright (C) 2004-2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include -#include "blargg_source.h" - -#define RAM (m.ram.ram) -#define REGS (m.smp_regs [0]) -#define REGS_IN (m.smp_regs [1]) - -void SNES_SPC::save_regs( uint8_t out [reg_count] ) -{ - // Use current timer counter values - for ( int i = 0; i < timer_count; i++ ) - out [r_t0out + i] = m.timers [i].counter; - - // Last written values - memcpy( out, REGS, r_t0out ); -} - -void SNES_SPC::init_header( void* spc_out ) -{ - spc_file_t* const spc = (spc_file_t*) spc_out; - - spc->has_id666 = 26; // has none - spc->version = 30; - memcpy( spc, signature, sizeof spc->signature ); - memset( spc->text, 0, sizeof spc->text ); -} - -void SNES_SPC::save_spc( void* spc_out ) -{ - spc_file_t* const spc = (spc_file_t*) spc_out; - - // CPU - spc->pcl = (uint8_t) (m.cpu_regs.pc >> 0); - spc->pch = (uint8_t) (m.cpu_regs.pc >> 8); - spc->a = m.cpu_regs.a; - spc->x = m.cpu_regs.x; - spc->y = m.cpu_regs.y; - spc->psw = m.cpu_regs.psw; - spc->sp = m.cpu_regs.sp; - - // RAM, ROM - memcpy( spc->ram, RAM, sizeof spc->ram ); - if ( m.rom_enabled ) - memcpy( spc->ram + rom_addr, m.hi_ram, sizeof m.hi_ram ); - memset( spc->unused, 0, sizeof spc->unused ); - memcpy( spc->ipl_rom, m.rom, sizeof spc->ipl_rom ); - - // SMP registers - save_regs( &spc->ram [0xF0] ); - int i; - for ( i = 0; i < port_count; i++ ) - spc->ram [0xF0 + r_cpuio0 + i] = REGS_IN [r_cpuio0 + i]; - - // DSP registers - for ( i = 0; i < SPC_DSP::register_count; i++ ) - spc->dsp [i] = dsp.read( i ); -} - -#undef IF_0_THEN_256 -#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1) -void SNES_SPC::copy_state( unsigned char** io, copy_func_t copy ) -{ - SPC_State_Copier copier( io, copy ); - - // Make state data more readable by putting 64K RAM, 16 SMP registers, - // then DSP (with its 128 registers) first - - // RAM - enable_rom( 0 ); // will get re-enabled if necessary in regs_loaded() below - copier.copy( RAM, 0x10000 ); - - { - // SMP registers - uint8_t regs [reg_count]; - uint8_t regs_in [reg_count]; - - memcpy( regs, REGS, reg_count ); - memcpy( regs_in, REGS_IN, reg_count ); - - copier.copy( regs, sizeof regs ); - copier.copy( regs_in, sizeof regs_in ); - - memcpy( REGS, regs, reg_count); - memcpy( REGS_IN, regs_in, reg_count ); - - enable_rom( REGS [r_control] & 0x80 ); - } - - // CPU registers - SPC_COPY( uint16_t, m.cpu_regs.pc ); - SPC_COPY( uint8_t, m.cpu_regs.a ); - SPC_COPY( uint8_t, m.cpu_regs.x ); - SPC_COPY( uint8_t, m.cpu_regs.y ); - SPC_COPY( uint8_t, m.cpu_regs.psw ); - SPC_COPY( uint8_t, m.cpu_regs.sp ); - copier.extra(); - - SPC_COPY( int16_t, m.spc_time ); - SPC_COPY( int16_t, m.dsp_time ); - - // DSP - dsp.copy_state( io, copy ); - - // Timers - for ( int i = 0; i < timer_count; i++ ) - { - Timer* t = &m.timers [i]; - t->period = IF_0_THEN_256( REGS [r_t0target + i] ); - t->enabled = REGS [r_control] >> i & 1; - SPC_COPY( int16_t, t->next_time ); - SPC_COPY( uint8_t, t->divider ); - SPC_COPY( uint8_t, t->counter ); - copier.extra(); - } - - set_tempo( m.tempo ); - - copier.extra(); -} -#endif diff --git a/apu/SPC_CPU.h b/apu/SPC_CPU.h deleted file mode 100644 index 67fee8da..00000000 --- a/apu/SPC_CPU.h +++ /dev/null @@ -1,1228 +0,0 @@ -// snes_spc 0.9.0. http://www.slack.net/~ant/ - -/* Copyright (C) 2004-2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -//// Memory access - -#if SPC_MORE_ACCURACY - #define SUSPICIOUS_OPCODE( name ) ((void) 0) -#else - #define SUSPICIOUS_OPCODE( name ) dprintf( "SPC: suspicious opcode: " name "\n" ) -#endif - -#define CPU_READ( time, offset, addr )\ - cpu_read( addr, time + offset ) - -#define CPU_WRITE( time, offset, addr, data )\ - cpu_write( data, addr, time + offset ) - -#if SPC_MORE_ACCURACY - #define CPU_READ_TIMER( time, offset, addr, out )\ - { out = CPU_READ( time, offset, addr ); } - -#else - // timers are by far the most common thing read from dp - #define CPU_READ_TIMER( time, offset, addr_, out )\ - {\ - rel_time_t adj_time = time + offset;\ - int dp_addr = addr_;\ - int ti = dp_addr - (r_t0out + 0xF0);\ - if ( (unsigned) ti < timer_count )\ - {\ - Timer* t = &m.timers [ti];\ - if ( adj_time >= t->next_time )\ - t = run_timer_( t, adj_time );\ - out = t->counter;\ - t->counter = 0;\ - }\ - else\ - {\ - out = ram [dp_addr];\ - int i = dp_addr - 0xF0;\ - if ( (unsigned) i < 0x10 )\ - out = cpu_read_smp_reg( i, adj_time );\ - }\ - } -#endif - -#define TIME_ADJ( n ) (n) - -#define READ_TIMER( time, addr, out ) CPU_READ_TIMER( rel_time, TIME_ADJ(time), (addr), out ) -#define READ( time, addr ) CPU_READ ( rel_time, TIME_ADJ(time), (addr) ) -#define WRITE( time, addr, data ) CPU_WRITE( rel_time, TIME_ADJ(time), (addr), (data) ) - -#define DP_ADDR( addr ) (dp + (addr)) - -#define READ_DP_TIMER( time, addr, out ) CPU_READ_TIMER( rel_time, TIME_ADJ(time), DP_ADDR( addr ), out ) -#define READ_DP( time, addr ) READ ( time, DP_ADDR( addr ) ) -#define WRITE_DP( time, addr, data ) WRITE( time, DP_ADDR( addr ), data ) - -#define READ_PROG16( addr ) GET_LE16( ram + (addr) ) - -#define SET_PC( n ) (pc = ram + (n)) -#define GET_PC() (pc - ram) -#define READ_PC( pc ) (*(pc)) -#define READ_PC16( pc ) GET_LE16( pc ) - -// TODO: remove non-wrapping versions? -#define SPC_NO_SP_WRAPAROUND 0 - -#define SET_SP( v ) (sp = ram + 0x101 + (v)) -#define GET_SP() (sp - 0x101 - ram) - -#if SPC_NO_SP_WRAPAROUND -#define PUSH16( v ) (sp -= 2, SET_LE16( sp, v )) -#define PUSH( v ) (void) (*--sp = (uint8_t) (v)) -#define POP( out ) (void) ((out) = *sp++) - -#else -#define PUSH16( data )\ -{\ - int addr = (sp -= 2) - ram;\ - if ( addr > 0x100 )\ - {\ - SET_LE16( sp, data );\ - }\ - else\ - {\ - ram [(uint8_t) addr + 0x100] = (uint8_t) data;\ - sp [1] = (uint8_t) (data >> 8);\ - sp += 0x100;\ - }\ -} - -#define PUSH( data )\ -{\ - *--sp = (uint8_t) (data);\ - if ( sp - ram == 0x100 )\ - sp += 0x100;\ -} - -#define POP( out )\ -{\ - out = *sp++;\ - if ( sp - ram == 0x201 )\ - {\ - out = sp [-0x101];\ - sp -= 0x100;\ - }\ -} - -#endif - -#define MEM_BIT( rel ) CPU_mem_bit( pc, rel_time + rel ) - -unsigned SNES_SPC::CPU_mem_bit( uint8_t const* pc, rel_time_t rel_time ) -{ - unsigned addr = READ_PC16( pc ); - unsigned t = READ( 0, addr & 0x1FFF ) >> (addr >> 13); - return t << 8 & 0x100; -} - -//// Status flag handling - -// Hex value in name to clarify code and bit shifting. -// Flag stored in indicated variable during emulation -int const n80 = 0x80; // nz -int const v40 = 0x40; // psw -int const p20 = 0x20; // dp -int const b10 = 0x10; // psw -int const h08 = 0x08; // psw -int const i04 = 0x04; // psw -int const z02 = 0x02; // nz -int const c01 = 0x01; // c - -int const nz_neg_mask = 0x880; // either bit set indicates N flag set - -#define GET_PSW( out )\ -{\ - out = psw & ~(n80 | p20 | z02 | c01);\ - out |= c >> 8 & c01;\ - out |= dp >> 3 & p20;\ - out |= ((nz >> 4) | nz) & n80;\ - if ( !(uint8_t) nz ) out |= z02;\ -} - -#define SET_PSW( in )\ -{\ - psw = in;\ - c = in << 8;\ - dp = in << 3 & 0x100;\ - nz = (in << 4 & 0x800) | (~in & z02);\ -} - -SPC_CPU_RUN_FUNC -{ - uint8_t* const ram = RAM; - int a = m.cpu_regs.a; - int x = m.cpu_regs.x; - int y = m.cpu_regs.y; - uint8_t const* pc; - uint8_t* sp; - int psw; - int c; - int nz; - int dp; - - SET_PC( m.cpu_regs.pc ); - SET_SP( m.cpu_regs.sp ); - SET_PSW( m.cpu_regs.psw ); - - goto loop; - - - // Main loop - -cbranch_taken_loop: - pc += *(BOOST::int8_t const*) pc; -inc_pc_loop: - pc++; -loop: -{ - unsigned opcode; - unsigned data; - - check( (unsigned) a < 0x100 ); - check( (unsigned) x < 0x100 ); - check( (unsigned) y < 0x100 ); - - opcode = *pc; - if (allow_time_overflow && rel_time >= 0 ) - goto stop; - if ( (rel_time += m.cycle_table [opcode]) > 0 && !allow_time_overflow) - goto out_of_time; - - #ifdef SPC_CPU_OPCODE_HOOK - SPC_CPU_OPCODE_HOOK( GET_PC(), opcode ); - #endif - /* - //SUB_CASE_COUNTER( 1 ); - #define PROFILE_TIMER_LOOP( op, addr, len )\ - if ( opcode == op )\ - {\ - int cond = (unsigned) ((addr) - 0xFD) < 3 &&\ - pc [len] == 0xF0 && pc [len+1] == 0xFE - len;\ - SUB_CASE_COUNTER( op && cond );\ - } - - PROFILE_TIMER_LOOP( 0xEC, GET_LE16( pc + 1 ), 3 ); - PROFILE_TIMER_LOOP( 0xEB, pc [1], 2 ); - PROFILE_TIMER_LOOP( 0xE4, pc [1], 2 ); - */ - -#ifdef DEBUGGER - if (debug_trace) - debug_do_trace(a, x, y, pc, sp, psw, c, nz, dp); -#endif - - - // TODO: if PC is at end of memory, this will get wrong operand (very obscure) - data = *++pc; - switch ( opcode ) - { - -// Common instructions - -#define BRANCH( cond )\ -{\ - pc++;\ - pc += (BOOST::int8_t) data;\ - if ( cond )\ - goto loop;\ - pc -= (BOOST::int8_t) data;\ - rel_time -= 2;\ - goto loop;\ -} - - case 0xF0: // BEQ - BRANCH( !(uint8_t) nz ) // 89% taken - - case 0xD0: // BNE - BRANCH( (uint8_t) nz ) - - case 0x3F:{// CALL - int old_addr = GET_PC() + 2; - SET_PC( READ_PC16( pc ) ); - PUSH16( old_addr ); - goto loop; - } - - case 0x6F:// RET - #if SPC_NO_SP_WRAPAROUND - { - SET_PC( GET_LE16( sp ) ); - sp += 2; - } - #else - { - int addr = sp - ram; - SET_PC( GET_LE16( sp ) ); - sp += 2; - if ( addr < 0x1FF ) - goto loop; - - SET_PC( sp [-0x101] * 0x100 + ram [(uint8_t) addr + 0x100] ); - sp -= 0x100; - } - #endif - goto loop; - - case 0xE4: // MOV a,dp - ++pc; - // 80% from timer - READ_DP_TIMER( 0, data, a = nz ); - goto loop; - - case 0xFA:{// MOV dp,dp - int temp; - READ_DP_TIMER( -2, data, temp ); - data = temp + no_read_before_write ; - } - // fall through - case 0x8F:{// MOV dp,#imm - int temp = READ_PC( pc + 1 ); - pc += 2; - - #if !SPC_MORE_ACCURACY - { - int i = dp + temp; - ram [i] = (uint8_t) data; - i -= 0xF0; - if ( (unsigned) i < 0x10 ) // 76% - { - REGS [i] = (uint8_t) data; - - // Registers other than $F2 and $F4-$F7 - //if ( i != 2 && i != 4 && i != 5 && i != 6 && i != 7 ) - if ( ((~0x2F00 << (bits_in_int - 16)) << i) < 0 ) // 12% - cpu_write_smp_reg( data, rel_time, i ); - } - } - #else - WRITE_DP( 0, temp, data ); - #endif - goto loop; - } - - case 0xC4: // MOV dp,a - ++pc; - #if !SPC_MORE_ACCURACY - { - int i = dp + data; - ram [i] = (uint8_t) a; - i -= 0xF0; - if ( (unsigned) i < 0x10 ) // 39% - { - unsigned sel = i - 2; - REGS [i] = (uint8_t) a; - - if ( sel == 1 ) // 51% $F3 - dsp_write( a, rel_time ); - else if ( sel > 1 ) // 1% not $F2 or $F3 - cpu_write_smp_reg_( a, rel_time, i ); - } - } - #else - WRITE_DP( 0, data, a ); - #endif - goto loop; - -#define CASE( n ) case n: - -// Define common address modes based on opcode for immediate mode. Execution -// ends with data set to the address of the operand. -#define ADDR_MODES_( op )\ - CASE( op - 0x02 ) /* (X) */\ - data = x + dp;\ - pc--;\ - goto end_##op;\ - CASE( op + 0x0F ) /* (dp)+Y */\ - data = READ_PROG16( data + dp ) + y;\ - goto end_##op;\ - CASE( op - 0x01 ) /* (dp+X) */\ - data = READ_PROG16( ((uint8_t) (data + x)) + dp );\ - goto end_##op;\ - CASE( op + 0x0E ) /* abs+Y */\ - data += y;\ - goto abs_##op;\ - CASE( op + 0x0D ) /* abs+X */\ - data += x;\ - CASE( op - 0x03 ) /* abs */\ - abs_##op:\ - data += 0x100 * READ_PC( ++pc );\ - goto end_##op;\ - CASE( op + 0x0C ) /* dp+X */\ - data = (uint8_t) (data + x); - -#define ADDR_MODES_NO_DP( op )\ - ADDR_MODES_( op )\ - data += dp;\ - end_##op: - -#define ADDR_MODES( op )\ - ADDR_MODES_( op )\ - CASE( op - 0x04 ) /* dp */\ - data += dp;\ - end_##op: - -// 1. 8-bit Data Transmission Commands. Group I - - ADDR_MODES_NO_DP( 0xE8 ) // MOV A,addr - a = nz = READ( 0, data ); - goto inc_pc_loop; - - case 0xBF:{// MOV A,(X)+ - int temp = x + dp; - x = (uint8_t) (x + 1); - a = nz = READ( -1, temp ); - goto loop; - } - - case 0xE8: // MOV A,imm - a = data; - nz = data; - goto inc_pc_loop; - - case 0xF9: // MOV X,dp+Y - data = (uint8_t) (data + y); - case 0xF8: // MOV X,dp - READ_DP_TIMER( 0, data, x = nz ); - goto inc_pc_loop; - - case 0xE9: // MOV X,abs - data = READ_PC16( pc ); - ++pc; - data = READ( 0, data ); - case 0xCD: // MOV X,imm - x = data; - nz = data; - goto inc_pc_loop; - - case 0xFB: // MOV Y,dp+X - data = (uint8_t) (data + x); - case 0xEB: // MOV Y,dp - // 70% from timer - pc++; - READ_DP_TIMER( 0, data, y = nz ); - goto loop; - - case 0xEC:{// MOV Y,abs - int temp = READ_PC16( pc ); - pc += 2; - READ_TIMER( 0, temp, y = nz ); - //y = nz = READ( 0, temp ); - goto loop; - } - - case 0x8D: // MOV Y,imm - y = data; - nz = data; - goto inc_pc_loop; - -// 2. 8-BIT DATA TRANSMISSION COMMANDS, GROUP 2 - - ADDR_MODES_NO_DP( 0xC8 ) // MOV addr,A - WRITE( 0, data, a ); - goto inc_pc_loop; - - { - int temp; - case 0xCC: // MOV abs,Y - temp = y; - goto mov_abs_temp; - case 0xC9: // MOV abs,X - temp = x; - mov_abs_temp: - WRITE( 0, READ_PC16( pc ), temp ); - pc += 2; - goto loop; - } - - case 0xD9: // MOV dp+Y,X - data = (uint8_t) (data + y); - case 0xD8: // MOV dp,X - WRITE( 0, data + dp, x ); - goto inc_pc_loop; - - case 0xDB: // MOV dp+X,Y - data = (uint8_t) (data + x); - case 0xCB: // MOV dp,Y - WRITE( 0, data + dp, y ); - goto inc_pc_loop; - -// 3. 8-BIT DATA TRANSMISSIN COMMANDS, GROUP 3. - - case 0x7D: // MOV A,X - a = x; - nz = x; - goto loop; - - case 0xDD: // MOV A,Y - a = y; - nz = y; - goto loop; - - case 0x5D: // MOV X,A - x = a; - nz = a; - goto loop; - - case 0xFD: // MOV Y,A - y = a; - nz = a; - goto loop; - - case 0x9D: // MOV X,SP - x = nz = GET_SP(); - goto loop; - - case 0xBD: // MOV SP,X - SET_SP( x ); - goto loop; - - //case 0xC6: // MOV (X),A (handled by MOV addr,A in group 2) - - case 0xAF: // MOV (X)+,A - WRITE_DP( 0, x, a + no_read_before_write ); - x++; - goto loop; - -// 5. 8-BIT LOGIC OPERATION COMMANDS - -#define LOGICAL_OP( op, func )\ - ADDR_MODES( op ) /* addr */\ - data = READ( 0, data );\ - case op: /* imm */\ - nz = a func##= data;\ - goto inc_pc_loop;\ - { unsigned addr;\ - case op + 0x11: /* X,Y */\ - data = READ_DP( -2, y );\ - addr = x + dp;\ - goto addr_##op;\ - case op + 0x01: /* dp,dp */\ - data = READ_DP( -3, data );\ - case op + 0x10:{/*dp,imm*/\ - uint8_t const* addr2 = pc + 1;\ - pc += 2;\ - addr = READ_PC( addr2 ) + dp;\ - }\ - addr_##op:\ - nz = data func READ( -1, addr );\ - WRITE( 0, addr, nz );\ - goto loop;\ - } - - LOGICAL_OP( 0x28, & ); // AND - - LOGICAL_OP( 0x08, | ); // OR - - LOGICAL_OP( 0x48, ^ ); // EOR - -// 4. 8-BIT ARITHMETIC OPERATION COMMANDS - - ADDR_MODES( 0x68 ) // CMP addr - data = READ( 0, data ); - case 0x68: // CMP imm - nz = a - data; - c = ~nz; - nz &= 0xFF; - goto inc_pc_loop; - - case 0x79: // CMP (X),(Y) - data = READ_DP( -2, y ); - nz = READ_DP( -1, x ) - data; - c = ~nz; - nz &= 0xFF; - goto loop; - - case 0x69: // CMP dp,dp - data = READ_DP( -3, data ); - case 0x78: // CMP dp,imm - nz = READ_DP( -1, READ_PC( ++pc ) ) - data; - c = ~nz; - nz &= 0xFF; - goto inc_pc_loop; - - case 0x3E: // CMP X,dp - data += dp; - goto cmp_x_addr; - case 0x1E: // CMP X,abs - data = READ_PC16( pc ); - pc++; - cmp_x_addr: - data = READ( 0, data ); - case 0xC8: // CMP X,imm - nz = x - data; - c = ~nz; - nz &= 0xFF; - goto inc_pc_loop; - - case 0x7E: // CMP Y,dp - data += dp; - goto cmp_y_addr; - case 0x5E: // CMP Y,abs - data = READ_PC16( pc ); - pc++; - cmp_y_addr: - data = READ( 0, data ); - case 0xAD: // CMP Y,imm - nz = y - data; - c = ~nz; - nz &= 0xFF; - goto inc_pc_loop; - - { - int addr; - case 0xB9: // SBC (x),(y) - case 0x99: // ADC (x),(y) - pc--; // compensate for inc later - data = READ_DP( -2, y ); - addr = x + dp; - goto adc_addr; - case 0xA9: // SBC dp,dp - case 0x89: // ADC dp,dp - data = READ_DP( -3, data ); - case 0xB8: // SBC dp,imm - case 0x98: // ADC dp,imm - addr = READ_PC( ++pc ) + dp; - adc_addr: - nz = READ( -1, addr ); - goto adc_data; - -// catch ADC and SBC together, then decode later based on operand -#undef CASE -#define CASE( n ) case n: case (n) + 0x20: - ADDR_MODES( 0x88 ) // ADC/SBC addr - data = READ( 0, data ); - case 0xA8: // SBC imm - case 0x88: // ADC imm - addr = -1; // A - nz = a; - adc_data: { - int flags; - if ( opcode >= 0xA0 ) // SBC - data ^= 0xFF; - - flags = data ^ nz; - nz += data + (c >> 8 & 1); - flags ^= nz; - - psw = (psw & ~(v40 | h08)) | - (flags >> 1 & h08) | - ((flags + 0x80) >> 2 & v40); - c = nz; - if ( addr < 0 ) - { - a = (uint8_t) nz; - goto inc_pc_loop; - } - WRITE( 0, addr, /*(uint8_t)*/ nz ); - goto inc_pc_loop; - } - - } - -// 6. ADDITION & SUBTRACTION COMMANDS - -#define INC_DEC_REG( reg, op )\ - nz = reg op;\ - reg = (uint8_t) nz;\ - goto loop; - - case 0xBC: INC_DEC_REG( a, + 1 ) // INC A - case 0x3D: INC_DEC_REG( x, + 1 ) // INC X - case 0xFC: INC_DEC_REG( y, + 1 ) // INC Y - - case 0x9C: INC_DEC_REG( a, - 1 ) // DEC A - case 0x1D: INC_DEC_REG( x, - 1 ) // DEC X - case 0xDC: INC_DEC_REG( y, - 1 ) // DEC Y - - case 0x9B: // DEC dp+X - case 0xBB: // INC dp+X - data = (uint8_t) (data + x); - case 0x8B: // DEC dp - case 0xAB: // INC dp - data += dp; - goto inc_abs; - case 0x8C: // DEC abs - case 0xAC: // INC abs - data = READ_PC16( pc ); - pc++; - inc_abs: - nz = (opcode >> 4 & 2) - 1; - nz += READ( -1, data ); - WRITE( 0, data, /*(uint8_t)*/ nz ); - goto inc_pc_loop; - -// 7. SHIFT, ROTATION COMMANDS - - case 0x5C: // LSR A - c = 0; - case 0x7C:{// ROR A - nz = (c >> 1 & 0x80) | (a >> 1); - c = a << 8; - a = nz; - goto loop; - } - - case 0x1C: // ASL A - c = 0; - case 0x3C:{// ROL A - int temp = c >> 8 & 1; - c = a << 1; - nz = c | temp; - a = (uint8_t) nz; - goto loop; - } - - case 0x0B: // ASL dp - c = 0; - data += dp; - goto rol_mem; - case 0x1B: // ASL dp+X - c = 0; - case 0x3B: // ROL dp+X - data = (uint8_t) (data + x); - case 0x2B: // ROL dp - data += dp; - goto rol_mem; - case 0x0C: // ASL abs - c = 0; - case 0x2C: // ROL abs - data = READ_PC16( pc ); - pc++; - rol_mem: - nz = c >> 8 & 1; - nz |= (c = READ( -1, data ) << 1); - WRITE( 0, data, /*(uint8_t)*/ nz ); - goto inc_pc_loop; - - case 0x4B: // LSR dp - c = 0; - data += dp; - goto ror_mem; - case 0x5B: // LSR dp+X - c = 0; - case 0x7B: // ROR dp+X - data = (uint8_t) (data + x); - case 0x6B: // ROR dp - data += dp; - goto ror_mem; - case 0x4C: // LSR abs - c = 0; - case 0x6C: // ROR abs - data = READ_PC16( pc ); - pc++; - ror_mem: { - int temp = READ( -1, data ); - nz = (c >> 1 & 0x80) | (temp >> 1); - c = temp << 8; - WRITE( 0, data, nz ); - goto inc_pc_loop; - } - - case 0x9F: // XCN - nz = a = (a >> 4) | (uint8_t) (a << 4); - goto loop; - -// 8. 16-BIT TRANSMISION COMMANDS - - case 0xBA: // MOVW YA,dp - a = READ_DP( -2, data ); - nz = (a & 0x7F) | (a >> 1); - y = READ_DP( 0, (uint8_t) (data + 1) ); - nz |= y; - goto inc_pc_loop; - - case 0xDA: // MOVW dp,YA - WRITE_DP( -1, data, a ); - WRITE_DP( 0, (uint8_t) (data + 1), y + no_read_before_write ); - goto inc_pc_loop; - -// 9. 16-BIT OPERATION COMMANDS - - case 0x3A: // INCW dp - case 0x1A:{// DECW dp - int temp; - // low byte - data += dp; - temp = READ( -3, data ); - temp += (opcode >> 4 & 2) - 1; // +1 for INCW, -1 for DECW - nz = ((temp >> 1) | temp) & 0x7F; - WRITE( -2, data, /*(uint8_t)*/ temp ); - - // high byte - data = (uint8_t) (data + 1) + dp; - temp = (uint8_t) ((temp >> 8) + READ( -1, data )); - nz |= temp; - WRITE( 0, data, temp ); - - goto inc_pc_loop; - } - - case 0x7A: // ADDW YA,dp - case 0x9A:{// SUBW YA,dp - int lo = READ_DP( -2, data ); - int hi = READ_DP( 0, (uint8_t) (data + 1) ); - int result; - int flags; - - if ( opcode == 0x9A ) // SUBW - { - lo = (lo ^ 0xFF) + 1; - hi ^= 0xFF; - } - - lo += a; - result = y + hi + (lo >> 8); - flags = hi ^ y ^ result; - - psw = (psw & ~(v40 | h08)) | - (flags >> 1 & h08) | - ((flags + 0x80) >> 2 & v40); - c = result; - a = (uint8_t) lo; - result = (uint8_t) result; - y = result; - nz = (((lo >> 1) | lo) & 0x7F) | result; - - goto inc_pc_loop; - } - - case 0x5A: { // CMPW YA,dp - int temp = a - READ_DP( -1, data ); - nz = ((temp >> 1) | temp) & 0x7F; - temp = y + (temp >> 8); - temp -= READ_DP( 0, (uint8_t) (data + 1) ); - nz |= temp; - c = ~temp; - nz &= 0xFF; - goto inc_pc_loop; - } - -// 10. MULTIPLICATION & DIVISON COMMANDS - - case 0xCF: { // MUL YA - unsigned temp = y * a; - a = (uint8_t) temp; - nz = ((temp >> 1) | temp) & 0x7F; - y = temp >> 8; - nz |= y; - goto loop; - } - - case 0x9E: // DIV YA,X - { - unsigned ya = y * 0x100 + a; - - psw &= ~(h08 | v40); - - if ( y >= x ) - psw |= v40; - - if ( (y & 15) >= (x & 15) ) - psw |= h08; - - if ( y < x * 2 ) - { - a = ya / x; - y = ya - a * x; - } - else - { - a = 255 - (ya - x * 0x200) / (256 - x); - y = x + (ya - x * 0x200) % (256 - x); - } - - nz = (uint8_t) a; - a = (uint8_t) a; - - goto loop; - } - -// 11. DECIMAL COMPENSATION COMMANDS - - case 0xDF: // DAA - SUSPICIOUS_OPCODE( "DAA" ); - if ( a > 0x99 || c & 0x100 ) - { - a += 0x60; - c = 0x100; - } - - if ( (a & 0x0F) > 9 || psw & h08 ) - a += 0x06; - - nz = a; - a = (uint8_t) a; - goto loop; - - case 0xBE: // DAS - SUSPICIOUS_OPCODE( "DAS" ); - if ( a > 0x99 || !(c & 0x100) ) - { - a -= 0x60; - c = 0; - } - - if ( (a & 0x0F) > 9 || !(psw & h08) ) - a -= 0x06; - - nz = a; - a = (uint8_t) a; - goto loop; - -// 12. BRANCHING COMMANDS - - case 0x2F: // BRA rel - pc += (BOOST::int8_t) data; - goto inc_pc_loop; - - case 0x30: // BMI - BRANCH( (nz & nz_neg_mask) ) - - case 0x10: // BPL - BRANCH( !(nz & nz_neg_mask) ) - - case 0xB0: // BCS - BRANCH( c & 0x100 ) - - case 0x90: // BCC - BRANCH( !(c & 0x100) ) - - case 0x70: // BVS - BRANCH( psw & v40 ) - - case 0x50: // BVC - BRANCH( !(psw & v40) ) - - #define CBRANCH( cond )\ - {\ - pc++;\ - if ( cond )\ - goto cbranch_taken_loop;\ - rel_time -= 2;\ - goto inc_pc_loop;\ - } - - case 0x03: // BBS dp.bit,rel - case 0x23: - case 0x43: - case 0x63: - case 0x83: - case 0xA3: - case 0xC3: - case 0xE3: - CBRANCH( READ_DP( -4, data ) >> (opcode >> 5) & 1 ) - - case 0x13: // BBC dp.bit,rel - case 0x33: - case 0x53: - case 0x73: - case 0x93: - case 0xB3: - case 0xD3: - case 0xF3: - CBRANCH( !(READ_DP( -4, data ) >> (opcode >> 5) & 1) ) - - case 0xDE: // CBNE dp+X,rel - data = (uint8_t) (data + x); - // fall through - case 0x2E:{// CBNE dp,rel - int temp; - // 61% from timer - READ_DP_TIMER( -4, data, temp ); - CBRANCH( temp != a ) - } - - case 0x6E: { // DBNZ dp,rel - unsigned temp = READ_DP( -4, data ) - 1; - WRITE_DP( -3, (uint8_t) data, /*(uint8_t)*/ temp + no_read_before_write ); - CBRANCH( temp ) - } - - case 0xFE: // DBNZ Y,rel - y = (uint8_t) (y - 1); - BRANCH( y ) - - case 0x1F: // JMP [abs+X] - SET_PC( READ_PC16( pc ) + x ); - // fall through - case 0x5F: // JMP abs - SET_PC( READ_PC16( pc ) ); - goto loop; - -// 13. SUB-ROUTINE CALL RETURN COMMANDS - - case 0x0F:{// BRK - int temp; - int ret_addr = GET_PC(); - SUSPICIOUS_OPCODE( "BRK" ); - SET_PC( READ_PROG16( 0xFFDE ) ); // vector address verified - PUSH16( ret_addr ); - GET_PSW( temp ); - psw = (psw | b10) & ~i04; - PUSH( temp ); - goto loop; - } - - case 0x4F:{// PCALL offset - int ret_addr = GET_PC() + 1; - SET_PC( 0xFF00 | data ); - PUSH16( ret_addr ); - goto loop; - } - - case 0x01: // TCALL n - case 0x11: - case 0x21: - case 0x31: - case 0x41: - case 0x51: - case 0x61: - case 0x71: - case 0x81: - case 0x91: - case 0xA1: - case 0xB1: - case 0xC1: - case 0xD1: - case 0xE1: - case 0xF1: { - int ret_addr = GET_PC(); - SET_PC( READ_PROG16( 0xFFDE - (opcode >> 3) ) ); - PUSH16( ret_addr ); - goto loop; - } - -// 14. STACK OPERATION COMMANDS - - { - int temp; - case 0x7F: // RET1 - temp = *sp; - SET_PC( GET_LE16( sp + 1 ) ); - sp += 3; - goto set_psw; - case 0x8E: // POP PSW - POP( temp ); - set_psw: - SET_PSW( temp ); - goto loop; - } - - case 0x0D: { // PUSH PSW - int temp; - GET_PSW( temp ); - PUSH( temp ); - goto loop; - } - - case 0x2D: // PUSH A - PUSH( a ); - goto loop; - - case 0x4D: // PUSH X - PUSH( x ); - goto loop; - - case 0x6D: // PUSH Y - PUSH( y ); - goto loop; - - case 0xAE: // POP A - POP( a ); - goto loop; - - case 0xCE: // POP X - POP( x ); - goto loop; - - case 0xEE: // POP Y - POP( y ); - goto loop; - -// 15. BIT OPERATION COMMANDS - - case 0x02: // SET1 - case 0x22: - case 0x42: - case 0x62: - case 0x82: - case 0xA2: - case 0xC2: - case 0xE2: - case 0x12: // CLR1 - case 0x32: - case 0x52: - case 0x72: - case 0x92: - case 0xB2: - case 0xD2: - case 0xF2: { - int bit = 1 << (opcode >> 5); - int mask = ~bit; - if ( opcode & 0x10 ) - bit = 0; - data += dp; - WRITE( 0, data, (READ( -1, data ) & mask) | bit ); - goto inc_pc_loop; - } - - case 0x0E: // TSET1 abs - case 0x4E: // TCLR1 abs - data = READ_PC16( pc ); - pc += 2; - { - unsigned temp = READ( -2, data ); - nz = (uint8_t) (a - temp); - temp &= ~a; - if ( opcode == 0x0E ) - temp |= a; - WRITE( 0, data, temp ); - } - goto loop; - - case 0x4A: // AND1 C,mem.bit - c &= MEM_BIT( 0 ); - pc += 2; - goto loop; - - case 0x6A: // AND1 C,/mem.bit - c &= ~MEM_BIT( 0 ); - pc += 2; - goto loop; - - case 0x0A: // OR1 C,mem.bit - c |= MEM_BIT( -1 ); - pc += 2; - goto loop; - - case 0x2A: // OR1 C,/mem.bit - c |= ~MEM_BIT( -1 ); - pc += 2; - goto loop; - - case 0x8A: // EOR1 C,mem.bit - c ^= MEM_BIT( -1 ); - pc += 2; - goto loop; - - case 0xEA: // NOT1 mem.bit - data = READ_PC16( pc ); - pc += 2; - { - unsigned temp = READ( -1, data & 0x1FFF ); - temp ^= 1 << (data >> 13); - WRITE( 0, data & 0x1FFF, temp ); - } - goto loop; - - case 0xCA: // MOV1 mem.bit,C - data = READ_PC16( pc ); - pc += 2; - { - unsigned temp = READ( -2, data & 0x1FFF ); - unsigned bit = data >> 13; - temp = (temp & ~(1 << bit)) | ((c >> 8 & 1) << bit); - WRITE( 0, data & 0x1FFF, temp + no_read_before_write ); - } - goto loop; - - case 0xAA: // MOV1 C,mem.bit - c = MEM_BIT( 0 ); - pc += 2; - goto loop; - -// 16. PROGRAM PSW FLAG OPERATION COMMANDS - - case 0x60: // CLRC - c = 0; - goto loop; - - case 0x80: // SETC - c = ~0; - goto loop; - - case 0xED: // NOTC - c ^= 0x100; - goto loop; - - case 0xE0: // CLRV - psw &= ~(v40 | h08); - goto loop; - - case 0x20: // CLRP - dp = 0; - goto loop; - - case 0x40: // SETP - dp = 0x100; - goto loop; - - case 0xA0: // EI - SUSPICIOUS_OPCODE( "EI" ); - psw |= i04; - goto loop; - - case 0xC0: // DI - SUSPICIOUS_OPCODE( "DI" ); - psw &= ~i04; - goto loop; - -// 17. OTHER COMMANDS - - case 0x00: // NOP - goto loop; - - case 0xFF:{// STOP - // handle PC wrap-around - unsigned addr = GET_PC() - 1; - if ( addr >= 0x10000 ) - { - addr &= 0xFFFF; - SET_PC( addr ); - dprintf( "SPC: PC wrapped around\n" ); - goto loop; - } - } - // fall through - case 0xEF: // SLEEP - SUSPICIOUS_OPCODE( "STOP/SLEEP" ); - --pc; - rel_time = 0; - m.cpu_error = "SPC emulation error"; - goto stop; - } // switch - - assert( 0 ); // catch any unhandled instructions -} -out_of_time: - rel_time -= m.cycle_table [*pc]; // undo partial execution of opcode -stop: - - // Uncache registers - if ( GET_PC() >= 0x10000 ) - dprintf( "SPC: PC wrapped around\n" ); - m.cpu_regs.pc = (uint16_t) GET_PC(); - m.cpu_regs.sp = ( uint8_t) GET_SP(); - m.cpu_regs.a = ( uint8_t) a; - m.cpu_regs.x = ( uint8_t) x; - m.cpu_regs.y = ( uint8_t) y; - { - int temp; - GET_PSW( temp ); - m.cpu_regs.psw = (uint8_t) temp; - } -} -SPC_CPU_RUN_FUNC_END diff --git a/apu/SPC_DSP.cpp b/apu/SPC_DSP.cpp deleted file mode 100644 index e6ba49ed..00000000 --- a/apu/SPC_DSP.cpp +++ /dev/null @@ -1,1072 +0,0 @@ -// snes_spc 0.9.0. http://www.slack.net/~ant/ - -#include "SPC_DSP.h" - -#include "blargg_endian.h" -#include - -/* Copyright (C) 2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -#ifdef BLARGG_ENABLE_OPTIMIZER - #include BLARGG_ENABLE_OPTIMIZER -#endif - -#if INT_MAX < 0x7FFFFFFF - #error "Requires that int type have at least 32 bits" -#endif - -// TODO: add to blargg_endian.h -#define GET_LE16SA( addr ) ((BOOST::int16_t) GET_LE16( addr )) -#define GET_LE16A( addr ) GET_LE16( addr ) -#define SET_LE16A( addr, data ) SET_LE16( addr, data ) - -static BOOST::uint8_t const initial_regs [SPC_DSP::register_count] = -{ - 0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80, - 0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF, - 0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A, - 0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF, - 0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67, - 0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x00,0x4E,0x7B,0xFF, - 0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F, - 0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF -}; - -// if ( io < -32768 ) io = -32768; -// if ( io > 32767 ) io = 32767; -#define CLAMP16( io )\ -{\ - if ( (int16_t) io != io )\ - io = (io >> 31) ^ 0x7FFF;\ -} - -// Access global DSP register -#define REG(n) m.regs [r_##n] - -// Access voice DSP register -#define VREG(r,n) r [v_##n] - -#define WRITE_SAMPLES( l, r, out ) \ -{\ - out [0] = l;\ - out [1] = r;\ - out += 2;\ - if ( out >= m.out_end )\ - {\ - check( out == m.out_end );\ - check( m.out_end != &m.extra [extra_size] || \ - (m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\ - out = m.extra;\ - m.out_end = &m.extra [extra_size];\ - }\ -}\ - -void SPC_DSP::set_output( sample_t* out, int size ) -{ - require( (size & 1) == 0 ); // must be even - if ( !out ) - { - out = m.extra; - size = extra_size; - } - m.out_begin = out; - m.out = out; - m.out_end = out + size; -} - -// Volume registers and efb are signed! Easy to forget int8_t cast. -// Prefixes are to avoid accidental use of locals with same names. - -// Gaussian interpolation - -static short const gauss [512] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, - 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, - 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, - 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, 17, - 18, 19, 19, 20, 20, 21, 21, 22, 23, 23, 24, 24, 25, 26, 27, 27, - 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 36, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 58, 59, 60, 61, 62, 64, 65, 66, 67, 69, 70, 71, 73, 74, 76, 77, - 78, 80, 81, 83, 84, 86, 87, 89, 90, 92, 94, 95, 97, 99, 100, 102, - 104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132, - 134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168, - 171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210, - 212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257, - 260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311, - 314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370, - 374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434, - 439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504, - 508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577, - 582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654, - 659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732, - 737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811, - 816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889, - 894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965, - 969, 974, 978, 983, 988, 992, 997,1001,1005,1010,1014,1019,1023,1027,1032,1036, -1040,1045,1049,1053,1057,1061,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102, -1106,1109,1113,1117,1121,1125,1128,1132,1136,1139,1143,1146,1150,1153,1157,1160, -1164,1167,1170,1174,1177,1180,1183,1186,1190,1193,1196,1199,1202,1205,1207,1210, -1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251, -1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280, -1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298, -1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305, -}; - -inline int SPC_DSP::interpolate( voice_t const* v ) -{ - // Make pointers into gaussian based on fractional position between samples - int offset = v->interp_pos >> 4 & 0xFF; - short const* fwd = gauss + 255 - offset; - short const* rev = gauss + offset; // mirror left half of gaussian - - int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; - int out; - out = (fwd [ 0] * in [0]) >> 11; - out += (fwd [256] * in [1]) >> 11; - out += (rev [256] * in [2]) >> 11; - out = (int16_t) out; - out += (rev [ 0] * in [3]) >> 11; - - CLAMP16( out ); - out &= ~1; - return out; -} - - -//// Counters - -int const simple_counter_range = 2048 * 5 * 3; // 30720 - -static unsigned const counter_rates [32] = -{ - simple_counter_range + 1, // never fires - 2048, 1536, - 1280, 1024, 768, - 640, 512, 384, - 320, 256, 192, - 160, 128, 96, - 80, 64, 48, - 40, 32, 24, - 20, 16, 12, - 10, 8, 6, - 5, 4, 3, - 2, - 1 -}; - -static unsigned const counter_offsets [32] = -{ - 1, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 0, - 0 -}; - -inline void SPC_DSP::init_counter() -{ - m.counter = 0; -} - -inline void SPC_DSP::run_counters() -{ - if ( --m.counter < 0 ) - m.counter = simple_counter_range - 1; -} - -inline unsigned SPC_DSP::read_counter( int rate ) -{ - return ((unsigned) m.counter + counter_offsets [rate]) % counter_rates [rate]; -} - - -//// Envelope - -inline void SPC_DSP::run_envelope( voice_t* const v ) -{ - int env = v->env; - if ( v->env_mode == env_release ) // 60% - { - if ( (env -= 0x8) < 0 ) - env = 0; - v->env = env; - } - else - { - int rate; - int env_data = VREG(v->regs,adsr1); - if ( m.t_adsr0 & 0x80 ) // 99% ADSR - { - if ( v->env_mode >= env_decay ) // 99% - { - env--; - env -= env >> 8; - rate = env_data & 0x1F; - if ( v->env_mode == env_decay ) // 1% - rate = (m.t_adsr0 >> 3 & 0x0E) + 0x10; - } - else // env_attack - { - rate = (m.t_adsr0 & 0x0F) * 2 + 1; - env += rate < 31 ? 0x20 : 0x400; - } - } - else // GAIN - { - int mode; - env_data = VREG(v->regs,gain); - mode = env_data >> 5; - if ( mode < 4 ) // direct - { - env = env_data * 0x10; - rate = 31; - } - else - { - rate = env_data & 0x1F; - if ( mode == 4 ) // 4: linear decrease - { - env -= 0x20; - } - else if ( mode < 6 ) // 5: exponential decrease - { - env--; - env -= env >> 8; - } - else // 6,7: linear increase - { - env += 0x20; - if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 ) - env += 0x8 - 0x20; // 7: two-slope linear increase - } - } - } - - // Sustain level - if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay ) - v->env_mode = env_sustain; - - v->hidden_env = env; - - // unsigned cast because linear decrease going negative also triggers this - if ( (unsigned) env > 0x7FF ) - { - env = (env < 0 ? 0 : 0x7FF); - if ( v->env_mode == env_attack ) - v->env_mode = env_decay; - } - - if ( !read_counter( rate ) ) - v->env = env; // nothing else is controlled by the counter - } -} - - -//// BRR Decoding - -inline void SPC_DSP::decode_brr( voice_t* v ) -{ - // Arrange the four input nybbles in 0xABCD order for easy decoding - int nybbles = m.t_brr_byte * 0x100 + m.ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF]; - - int const header = m.t_brr_header; - - // Write to next four samples in circular buffer - int* pos = &v->buf [v->buf_pos]; - int* end; - if ( (v->buf_pos += 4) >= brr_buf_size ) - v->buf_pos = 0; - - // Decode four samples - for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 ) - { - // Extract nybble and sign-extend - int s = (int16_t) nybbles >> 12; - - // Shift sample based on header - int const shift = header >> 4; - s = (s << shift) >> 1; - if ( shift >= 0xD ) // handle invalid range - s = (s >> 25) << 11; // same as: s = (s < 0 ? -0x800 : 0) - - // Apply IIR filter (8 is the most commonly used) - int const filter = header & 0x0C; - int const p1 = pos [brr_buf_size - 1]; - int const p2 = pos [brr_buf_size - 2] >> 1; - if ( filter >= 8 ) - { - s += p1; - s -= p2; - if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875 - { - s += p2 >> 4; - s += (p1 * -3) >> 6; - } - else // s += p1 * 0.8984375 - p2 * 0.40625 - { - s += (p1 * -13) >> 7; - s += (p2 * 3) >> 4; - } - } - else if ( filter ) // s += p1 * 0.46875 - { - s += p1 >> 1; - s += (-p1) >> 5; - } - - // Adjust and write sample - CLAMP16( s ); - s = (int16_t) (s * 2); - pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around - } -} - - -//// Misc - -#define MISC_CLOCK( n ) inline void SPC_DSP::misc_##n() - -MISC_CLOCK( 27 ) -{ - m.t_pmon = REG(pmon) & 0xFE; // voice 0 doesn't support PMON -} -MISC_CLOCK( 28 ) -{ - m.t_non = REG(non); - m.t_eon = REG(eon); - m.t_dir = REG(dir); -} -MISC_CLOCK( 29 ) -{ - if ( (m.every_other_sample ^= 1) != 0 ) - m.new_kon &= ~m.kon; // clears KON 63 clocks after it was last read -} -MISC_CLOCK( 30 ) -{ - if ( m.every_other_sample ) - { - m.kon = m.new_kon; - m.t_koff = REG(koff) | m.mute_mask; - } - - run_counters(); - - // Noise - if ( !read_counter( REG(flg) & 0x1F ) ) - { - int feedback = (m.noise << 13) ^ (m.noise << 14); - m.noise = (feedback & 0x4000) ^ (m.noise >> 1); - } -} - - -//// Voices - -#define VOICE_CLOCK( n ) void SPC_DSP::voice_##n( voice_t* const v ) - -inline VOICE_CLOCK( V1 ) -{ - m.t_dir_addr = m.t_dir * 0x100 + m.t_srcn * 4; - m.t_srcn = VREG(v->regs,srcn); -} -inline VOICE_CLOCK( V2 ) -{ - // Read sample pointer (ignored if not needed) - uint8_t const* entry = &m.ram [m.t_dir_addr]; - if ( !v->kon_delay ) - entry += 2; - m.t_brr_next_addr = GET_LE16A( entry ); - - m.t_adsr0 = VREG(v->regs,adsr0); - - // Read pitch, spread over two clocks - m.t_pitch = VREG(v->regs,pitchl); -} -inline VOICE_CLOCK( V3a ) -{ - m.t_pitch += (VREG(v->regs,pitchh) & 0x3F) << 8; -} -inline VOICE_CLOCK( V3b ) -{ - // Read BRR header and byte - m.t_brr_byte = m.ram [(v->brr_addr + v->brr_offset) & 0xFFFF]; - m.t_brr_header = m.ram [v->brr_addr]; // brr_addr doesn't need masking -} -VOICE_CLOCK( V3c ) -{ - // Pitch modulation using previous voice's output - if ( m.t_pmon & v->vbit ) - m.t_pitch += ((m.t_output >> 5) * m.t_pitch) >> 10; - - if ( v->kon_delay ) - { - // Get ready to start BRR decoding on next sample - if ( v->kon_delay == 5 ) - { - v->brr_addr = m.t_brr_next_addr; - v->brr_offset = 1; - v->buf_pos = 0; - m.t_brr_header = 0; // header is ignored on this sample - m.kon_check = true; - - if (take_spc_snapshot) - { - take_spc_snapshot = 0; - if (spc_snapshot_callback) - spc_snapshot_callback(); - } - } - - // Envelope is never run during KON - v->env = 0; - v->hidden_env = 0; - - // Disable BRR decoding until last three samples - v->interp_pos = 0; - if ( --v->kon_delay & 3 ) - v->interp_pos = 0x4000; - - // Pitch is never added during KON - m.t_pitch = 0; - } - - // Gaussian interpolation - { - int output = interpolate( v ); - - // Noise - if ( m.t_non & v->vbit ) - output = (int16_t) (m.noise * 2); - - // Apply envelope - m.t_output = (output * v->env) >> 11 & ~1; - v->t_envx_out = (uint8_t) (v->env >> 4); - } - - // Immediate silence due to end of sample or soft reset - if ( REG(flg) & 0x80 || (m.t_brr_header & 3) == 1 ) - { - v->env_mode = env_release; - v->env = 0; - } - - if ( m.every_other_sample ) - { - // KOFF - if ( m.t_koff & v->vbit ) - v->env_mode = env_release; - - // KON - if ( m.kon & v->vbit ) - { - v->kon_delay = 5; - v->env_mode = env_attack; - } - } - - // Run envelope for next sample - if ( !v->kon_delay ) - run_envelope( v ); -} - -inline void SPC_DSP::voice_output( voice_t const* v, int ch ) -{ - // Apply left/right volume - int amp = (m.t_output * (int8_t) VREG(v->regs,voll + ch)) >> 7; - amp *= ((stereo_switch & (1 << (v->voice_number + ch * voice_count))) ? 1 : 0); - - // Add to output total - m.t_main_out [ch] += amp; - CLAMP16( m.t_main_out [ch] ); - - // Optionally add to echo total - if ( m.t_eon & v->vbit ) - { - m.t_echo_out [ch] += amp; - CLAMP16( m.t_echo_out [ch] ); - } -} -VOICE_CLOCK( V4 ) -{ - // Decode BRR - m.t_looped = 0; - if ( v->interp_pos >= 0x4000 ) - { - decode_brr( v ); - - if ( (v->brr_offset += 2) >= brr_block_size ) - { - // Start decoding next BRR block - assert( v->brr_offset == brr_block_size ); - v->brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF; - if ( m.t_brr_header & 1 ) - { - v->brr_addr = m.t_brr_next_addr; - m.t_looped = v->vbit; - } - v->brr_offset = 1; - } - } - - // Apply pitch - v->interp_pos = (v->interp_pos & 0x3FFF) + m.t_pitch; - - // Keep from getting too far ahead (when using pitch modulation) - if ( v->interp_pos > 0x7FFF ) - v->interp_pos = 0x7FFF; - - // Output left - voice_output( v, 0 ); -} -inline VOICE_CLOCK( V5 ) -{ - // Output right - voice_output( v, 1 ); - - // ENDX, OUTX, and ENVX won't update if you wrote to them 1-2 clocks earlier - int endx_buf = REG(endx) | m.t_looped; - - // Clear bit in ENDX if KON just began - if ( v->kon_delay == 5 ) - endx_buf &= ~v->vbit; - m.endx_buf = (uint8_t) endx_buf; -} -inline VOICE_CLOCK( V6 ) -{ - (void) v; // avoid compiler warning about unused v - m.outx_buf = (uint8_t) (m.t_output >> 8); -} -inline VOICE_CLOCK( V7 ) -{ - // Update ENDX - REG(endx) = m.endx_buf; - - m.envx_buf = v->t_envx_out; -} -inline VOICE_CLOCK( V8 ) -{ - // Update OUTX - VREG(v->regs,outx) = m.outx_buf; -} -inline VOICE_CLOCK( V9 ) -{ - // Update ENVX - VREG(v->regs,envx) = m.envx_buf; -} - -// Most voices do all these in one clock, so make a handy composite -inline VOICE_CLOCK( V3 ) -{ - voice_V3a( v ); - voice_V3b( v ); - voice_V3c( v ); -} - -// Common combinations of voice steps on different voices. This greatly reduces -// code size and allows everything to be inlined in these functions. -VOICE_CLOCK(V7_V4_V1) { voice_V7(v); voice_V1(v+3); voice_V4(v+1); } -VOICE_CLOCK(V8_V5_V2) { voice_V8(v); voice_V5(v+1); voice_V2(v+2); } -VOICE_CLOCK(V9_V6_V3) { voice_V9(v); voice_V6(v+1); voice_V3(v+2); } - - -//// Echo - -// Current echo buffer pointer for left/right channel -#define ECHO_PTR( ch ) (&m.ram [m.t_echo_ptr + ch * 2]) - -// Sample in echo history buffer, where 0 is the oldest -#define ECHO_FIR( i ) (m.echo_hist_pos [i]) - -// Calculate FIR point for left/right channel -#define CALC_FIR( i, ch ) ((ECHO_FIR( i + 1 ) [ch] * (int8_t) REG(fir + i * 0x10)) >> 6) - -#define ECHO_CLOCK( n ) inline void SPC_DSP::echo_##n() - -inline void SPC_DSP::echo_read( int ch ) -{ - int s; - if ( m.t_echo_ptr >= 0xffc0 && rom_enabled ) - s = GET_LE16SA( &hi_ram [m.t_echo_ptr + ch * 2 - 0xffc0] ); - else - s = GET_LE16SA( ECHO_PTR( ch ) ); - // second copy simplifies wrap-around handling - ECHO_FIR( 0 ) [ch] = ECHO_FIR( 8 ) [ch] = s >> 1; -} - -ECHO_CLOCK( 22 ) -{ - // History - if ( ++m.echo_hist_pos >= &m.echo_hist [echo_hist_size] ) - m.echo_hist_pos = m.echo_hist; - - m.t_echo_ptr = (m.t_esa * 0x100 + m.echo_offset) & 0xFFFF; - echo_read( 0 ); - - // FIR (using l and r temporaries below helps compiler optimize) - int l = CALC_FIR( 0, 0 ); - int r = CALC_FIR( 0, 1 ); - - m.t_echo_in [0] = l; - m.t_echo_in [1] = r; -} -ECHO_CLOCK( 23 ) -{ - int l = CALC_FIR( 1, 0 ) + CALC_FIR( 2, 0 ); - int r = CALC_FIR( 1, 1 ) + CALC_FIR( 2, 1 ); - - m.t_echo_in [0] += l; - m.t_echo_in [1] += r; - - echo_read( 1 ); -} -ECHO_CLOCK( 24 ) -{ - int l = CALC_FIR( 3, 0 ) + CALC_FIR( 4, 0 ) + CALC_FIR( 5, 0 ); - int r = CALC_FIR( 3, 1 ) + CALC_FIR( 4, 1 ) + CALC_FIR( 5, 1 ); - - m.t_echo_in [0] += l; - m.t_echo_in [1] += r; -} -ECHO_CLOCK( 25 ) -{ - int l = m.t_echo_in [0] + CALC_FIR( 6, 0 ); - int r = m.t_echo_in [1] + CALC_FIR( 6, 1 ); - - l = (int16_t) l; - r = (int16_t) r; - - l += (int16_t) CALC_FIR( 7, 0 ); - r += (int16_t) CALC_FIR( 7, 1 ); - - CLAMP16( l ); - CLAMP16( r ); - - m.t_echo_in [0] = l & ~1; - m.t_echo_in [1] = r & ~1; -} -inline int SPC_DSP::echo_output( int ch ) -{ - int out = (int16_t) ((m.t_main_out [ch] * (int8_t) REG(mvoll + ch * 0x10)) >> 7) + - (int16_t) ((m.t_echo_in [ch] * (int8_t) REG(evoll + ch * 0x10)) >> 7); - CLAMP16( out ); - return out; -} -ECHO_CLOCK( 26 ) -{ - // Left output volumes - // (save sample for next clock so we can output both together) - m.t_main_out [0] = echo_output( 0 ); - - // Echo feedback - int l = m.t_echo_out [0] + (int16_t) ((m.t_echo_in [0] * (int8_t) REG(efb)) >> 7); - int r = m.t_echo_out [1] + (int16_t) ((m.t_echo_in [1] * (int8_t) REG(efb)) >> 7); - - CLAMP16( l ); - CLAMP16( r ); - - m.t_echo_out [0] = l & ~1; - m.t_echo_out [1] = r & ~1; -} -ECHO_CLOCK( 27 ) -{ - // Output - int l = m.t_main_out [0]; - int r = echo_output( 1 ); - m.t_main_out [0] = 0; - m.t_main_out [1] = 0; - - // TODO: global muting isn't this simple (turns DAC on and off - // or something, causing small ~37-sample pulse when first muted) - if ( REG(flg) & 0x40 ) - { - l = 0; - r = 0; - } - - // Output sample to DAC - #ifdef SPC_DSP_OUT_HOOK - SPC_DSP_OUT_HOOK( l, r ); - #else - sample_t* out = m.out; - WRITE_SAMPLES( l, r, out ); - m.out = out; - #endif -} -ECHO_CLOCK( 28 ) -{ - m.t_echo_enabled = REG(flg); -} -inline void SPC_DSP::echo_write( int ch ) -{ - if ( !(m.t_echo_enabled & 0x20) ) - { - if ( m.t_echo_ptr >= 0xffc0 && rom_enabled ) - SET_LE16A( &hi_ram [m.t_echo_ptr + ch * 2 - 0xffc0], m.t_echo_out [ch] ); - else - SET_LE16A( ECHO_PTR( ch ), m.t_echo_out [ch] ); - } - - m.t_echo_out [ch] = 0; -} -ECHO_CLOCK( 29 ) -{ - m.t_esa = REG(esa); - - if ( !m.echo_offset ) - m.echo_length = (REG(edl) & 0x0F) * 0x800; - - m.echo_offset += 4; - if ( m.echo_offset >= m.echo_length ) - m.echo_offset = 0; - - // Write left echo - echo_write( 0 ); - - m.t_echo_enabled = REG(flg); -} -ECHO_CLOCK( 30 ) -{ - // Write right echo - echo_write( 1 ); -} - - -//// Timing - -// Execute clock for a particular voice -#define V( clock, voice ) voice_##clock( &m.voices [voice] ); - -/* The most common sequence of clocks uses composite operations -for efficiency. For example, the following are equivalent to the -individual steps on the right: - -V(V7_V4_V1,2) -> V(V7,2) V(V4,3) V(V1,5) -V(V8_V5_V2,2) -> V(V8,2) V(V5,3) V(V2,4) -V(V9_V6_V3,2) -> V(V9,2) V(V6,3) V(V3,4) */ - -// Voice 0 1 2 3 4 5 6 7 -#define GEN_DSP_TIMING \ -PHASE( 0) V(V5,0)V(V2,1)\ -PHASE( 1) V(V6,0)V(V3,1)\ -PHASE( 2) V(V7_V4_V1,0)\ -PHASE( 3) V(V8_V5_V2,0)\ -PHASE( 4) V(V9_V6_V3,0)\ -PHASE( 5) V(V7_V4_V1,1)\ -PHASE( 6) V(V8_V5_V2,1)\ -PHASE( 7) V(V9_V6_V3,1)\ -PHASE( 8) V(V7_V4_V1,2)\ -PHASE( 9) V(V8_V5_V2,2)\ -PHASE(10) V(V9_V6_V3,2)\ -PHASE(11) V(V7_V4_V1,3)\ -PHASE(12) V(V8_V5_V2,3)\ -PHASE(13) V(V9_V6_V3,3)\ -PHASE(14) V(V7_V4_V1,4)\ -PHASE(15) V(V8_V5_V2,4)\ -PHASE(16) V(V9_V6_V3,4)\ -PHASE(17) V(V1,0) V(V7,5)V(V4,6)\ -PHASE(18) V(V8_V5_V2,5)\ -PHASE(19) V(V9_V6_V3,5)\ -PHASE(20) V(V1,1) V(V7,6)V(V4,7)\ -PHASE(21) V(V8,6)V(V5,7) V(V2,0) /* t_brr_next_addr order dependency */\ -PHASE(22) V(V3a,0) V(V9,6)V(V6,7) echo_22();\ -PHASE(23) V(V7,7) echo_23();\ -PHASE(24) V(V8,7) echo_24();\ -PHASE(25) V(V3b,0) V(V9,7) echo_25();\ -PHASE(26) echo_26();\ -PHASE(27) misc_27(); echo_27();\ -PHASE(28) misc_28(); echo_28();\ -PHASE(29) misc_29(); echo_29();\ -PHASE(30) misc_30();V(V3c,0) echo_30();\ -PHASE(31) V(V4,0) V(V1,2)\ - -#if !SPC_DSP_CUSTOM_RUN - -void SPC_DSP::run( int clocks_remain ) -{ - require( clocks_remain > 0 ); - - int const phase = m.phase; - m.phase = (phase + clocks_remain) & 31; - switch ( phase ) - { - loop: - - #define PHASE( n ) if ( n && !--clocks_remain ) break; case n: - GEN_DSP_TIMING - #undef PHASE - - if ( --clocks_remain ) - goto loop; - } -} - -#endif - - -//// Setup - -void SPC_DSP::init( void* ram_64k ) -{ - m.ram = (uint8_t*) ram_64k; - mute_voices( 0 ); - disable_surround( false ); - set_output( 0, 0 ); - reset(); - - stereo_switch = 0xffff; - take_spc_snapshot = 0; - spc_snapshot_callback = 0; - - #ifndef NDEBUG - // be sure this sign-extends - assert( (int16_t) 0x8000 == -0x8000 ); - - // be sure right shift preserves sign - assert( (-1 >> 1) == -1 ); - - // check clamp macro - int i; - i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF ); - i = -0x8001; CLAMP16( i ); assert( i == -0x8000 ); - - blargg_verify_byte_order(); - #endif -} - -void SPC_DSP::soft_reset_common() -{ - require( m.ram ); // init() must have been called already - - m.noise = 0x4000; - m.echo_hist_pos = m.echo_hist; - m.every_other_sample = 1; - m.echo_offset = 0; - m.phase = 0; - - init_counter(); - - for (int i = 0; i < voice_count; i++) - m.voices[i].voice_number = i; -} - -void SPC_DSP::soft_reset() -{ - REG(flg) = 0xE0; - soft_reset_common(); -} - -void SPC_DSP::load( uint8_t const regs [register_count] ) -{ - memcpy( m.regs, regs, sizeof m.regs ); - memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count ); - - // Internal state - for ( int i = voice_count; --i >= 0; ) - { - voice_t* v = &m.voices [i]; - v->brr_offset = 1; - v->vbit = 1 << i; - v->regs = &m.regs [i * 0x10]; - } - m.new_kon = REG(kon); - m.t_dir = REG(dir); - m.t_esa = REG(esa); - - soft_reset_common(); -} - -void SPC_DSP::reset() { load( initial_regs ); } - - -//// State save/load - -#if !SPC_NO_COPY_STATE_FUNCS - -void SPC_State_Copier::copy( void* state, size_t size ) -{ - func( buf, state, size ); -} - -int SPC_State_Copier::copy_int( int state, int size ) -{ - BOOST::uint8_t s [2]; - SET_LE16( s, state ); - func( buf, &s, size ); - return GET_LE16( s ); -} - -void SPC_State_Copier::skip( int count ) -{ - if ( count > 0 ) - { - char temp [64]; - memset( temp, 0, sizeof temp ); - do - { - int n = sizeof temp; - if ( n > count ) - n = count; - count -= n; - func( buf, temp, n ); - } - while ( count ); - } -} - -void SPC_State_Copier::extra() -{ - int n = 0; - SPC_State_Copier& copier = *this; - SPC_COPY( uint8_t, n ); - skip( n ); -} - -void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy ) -{ - SPC_State_Copier copier( io, copy ); - - // DSP registers - copier.copy( m.regs, register_count ); - - // Internal state - - // Voices - int i; - for ( i = 0; i < voice_count; i++ ) - { - voice_t* v = &m.voices [i]; - - // BRR buffer - int i; - for ( i = 0; i < brr_buf_size; i++ ) - { - int s = v->buf [i]; - SPC_COPY( int16_t, s ); - v->buf [i] = v->buf [i + brr_buf_size] = s; - } - - SPC_COPY( uint16_t, v->interp_pos ); - SPC_COPY( uint16_t, v->brr_addr ); - SPC_COPY( uint16_t, v->env ); - SPC_COPY( int16_t, v->hidden_env ); - SPC_COPY( uint8_t, v->buf_pos ); - SPC_COPY( uint8_t, v->brr_offset ); - SPC_COPY( uint8_t, v->kon_delay ); - { - int m = v->env_mode; - SPC_COPY( uint8_t, m ); - v->env_mode = (enum env_mode_t) m; - } - SPC_COPY( uint8_t, v->t_envx_out ); - - copier.extra(); - } - - // Echo history - for ( i = 0; i < echo_hist_size; i++ ) - { - int j; - for ( j = 0; j < 2; j++ ) - { - int s = m.echo_hist_pos [i] [j]; - SPC_COPY( int16_t, s ); - m.echo_hist [i] [j] = s; // write back at offset 0 - } - } - m.echo_hist_pos = m.echo_hist; - memcpy( &m.echo_hist [echo_hist_size], m.echo_hist, echo_hist_size * sizeof m.echo_hist [0] ); - - // Misc - SPC_COPY( uint8_t, m.every_other_sample ); - SPC_COPY( uint8_t, m.kon ); - - SPC_COPY( uint16_t, m.noise ); - SPC_COPY( uint16_t, m.counter ); - SPC_COPY( uint16_t, m.echo_offset ); - SPC_COPY( uint16_t, m.echo_length ); - SPC_COPY( uint8_t, m.phase ); - - SPC_COPY( uint8_t, m.new_kon ); - SPC_COPY( uint8_t, m.endx_buf ); - SPC_COPY( uint8_t, m.envx_buf ); - SPC_COPY( uint8_t, m.outx_buf ); - - SPC_COPY( uint8_t, m.t_pmon ); - SPC_COPY( uint8_t, m.t_non ); - SPC_COPY( uint8_t, m.t_eon ); - SPC_COPY( uint8_t, m.t_dir ); - SPC_COPY( uint8_t, m.t_koff ); - - SPC_COPY( uint16_t, m.t_brr_next_addr ); - SPC_COPY( uint8_t, m.t_adsr0 ); - SPC_COPY( uint8_t, m.t_brr_header ); - SPC_COPY( uint8_t, m.t_brr_byte ); - SPC_COPY( uint8_t, m.t_srcn ); - SPC_COPY( uint8_t, m.t_esa ); - SPC_COPY( uint8_t, m.t_echo_enabled ); - - SPC_COPY( int16_t, m.t_main_out [0] ); - SPC_COPY( int16_t, m.t_main_out [1] ); - SPC_COPY( int16_t, m.t_echo_out [0] ); - SPC_COPY( int16_t, m.t_echo_out [1] ); - SPC_COPY( int16_t, m.t_echo_in [0] ); - SPC_COPY( int16_t, m.t_echo_in [1] ); - - SPC_COPY( uint16_t, m.t_dir_addr ); - SPC_COPY( uint16_t, m.t_pitch ); - SPC_COPY( int16_t, m.t_output ); - SPC_COPY( uint16_t, m.t_echo_ptr ); - SPC_COPY( uint8_t, m.t_looped ); - - copier.extra(); -} -#endif - - -//// Snes9x Accessor - -void SPC_DSP::set_spc_snapshot_callback( void (*callback) (void) ) -{ - spc_snapshot_callback = callback; -} - -void SPC_DSP::dump_spc_snapshot( void ) -{ - take_spc_snapshot = 1; -} - -void SPC_DSP::set_stereo_switch( int value ) -{ - stereo_switch = value; -} - -SPC_DSP::uint8_t SPC_DSP::reg_value( int ch, int addr ) -{ - return m.voices[ch].regs[addr]; -} - -int SPC_DSP::envx_value( int ch ) -{ - return m.voices[ch].env; -} diff --git a/apu/SPC_DSP.h b/apu/SPC_DSP.h deleted file mode 100644 index 61d05ab5..00000000 --- a/apu/SPC_DSP.h +++ /dev/null @@ -1,319 +0,0 @@ -// Highly accurate SNES SPC-700 DSP emulator - -// snes_spc 0.9.0 -#ifndef SPC_DSP_H -#define SPC_DSP_H - -#include "blargg_common.h" - -extern "C" { typedef void (*dsp_copy_func_t)( unsigned char** io, void* state, size_t ); } - -class SPC_DSP { -public: - typedef BOOST::uint8_t uint8_t; - -// Setup - - // Initializes DSP and has it use the 64K RAM provided - void init( void* ram_64k ); - - // Sets destination for output samples. If out is NULL or out_size is 0, - // doesn't generate any. - typedef short sample_t; - void set_output( sample_t* out, int out_size ); - - // Number of samples written to output since it was last set, always - // a multiple of 2. Undefined if more samples were generated than - // output buffer could hold. - int sample_count() const; - -// Emulation - - // Resets DSP to power-on state - void reset(); - - // Emulates pressing reset switch on SNES - void soft_reset(); - - // Reads/writes DSP registers. For accuracy, you must first call run() - // to catch the DSP up to present. - int read ( int addr ) const; - void write( int addr, int data ); - - // Runs DSP for specified number of clocks (~1024000 per second). Every 32 clocks - // a pair of samples is be generated. - void run( int clock_count ); - -// Sound control - - // Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events). - // Reduces emulation accuracy. - enum { voice_count = 8 }; - void mute_voices( int mask ); - -// State - - // Resets DSP and uses supplied values to initialize registers - enum { register_count = 128 }; - void load( uint8_t const regs [register_count] ); - - // Saves/loads exact emulator state - enum { state_size = 640 }; // maximum space needed when saving - typedef dsp_copy_func_t copy_func_t; - void copy_state( unsigned char** io, copy_func_t ); - - // Returns non-zero if new key-on events occurred since last call - bool check_kon(); - -// Snes9x Accessor - - int stereo_switch; - int take_spc_snapshot; - int rom_enabled; // mirror - uint8_t *rom, *hi_ram; // mirror - void (*spc_snapshot_callback) (void); - - void set_spc_snapshot_callback( void (*callback) (void) ); - void dump_spc_snapshot( void ); - void set_stereo_switch( int ); - uint8_t reg_value( int, int ); - int envx_value( int ); - -// DSP register addresses - - // Global registers - enum { - r_mvoll = 0x0C, r_mvolr = 0x1C, - r_evoll = 0x2C, r_evolr = 0x3C, - r_kon = 0x4C, r_koff = 0x5C, - r_flg = 0x6C, r_endx = 0x7C, - r_efb = 0x0D, r_pmon = 0x2D, - r_non = 0x3D, r_eon = 0x4D, - r_dir = 0x5D, r_esa = 0x6D, - r_edl = 0x7D, - r_fir = 0x0F // 8 coefficients at 0x0F, 0x1F ... 0x7F - }; - - // Voice registers - enum { - v_voll = 0x00, v_volr = 0x01, - v_pitchl = 0x02, v_pitchh = 0x03, - v_srcn = 0x04, v_adsr0 = 0x05, - v_adsr1 = 0x06, v_gain = 0x07, - v_envx = 0x08, v_outx = 0x09 - }; - -public: - enum { extra_size = 16 }; - sample_t* extra() { return m.extra; } - sample_t const* out_pos() const { return m.out; } - void disable_surround( bool ) { } // not supported -public: - BLARGG_DISABLE_NOTHROW - - typedef BOOST::int8_t int8_t; - typedef BOOST::int16_t int16_t; - - enum { echo_hist_size = 8 }; - - enum env_mode_t { env_release, env_attack, env_decay, env_sustain }; - enum { brr_buf_size = 12 }; - struct voice_t - { - int buf [brr_buf_size*2];// decoded samples (twice the size to simplify wrap handling) - int buf_pos; // place in buffer where next samples will be decoded - int interp_pos; // relative fractional position in sample (0x1000 = 1.0) - int brr_addr; // address of current BRR block - int brr_offset; // current decoding offset in BRR block - uint8_t* regs; // pointer to voice's DSP registers - int vbit; // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc. - int kon_delay; // KON delay/current setup phase - env_mode_t env_mode; - int env; // current envelope level - int hidden_env; // used by GAIN mode 7, very obscure quirk - uint8_t t_envx_out; - int voice_number; - }; -private: - enum { brr_block_size = 9 }; - - struct state_t - { - uint8_t regs [register_count]; - - // Echo history keeps most recent 8 samples (twice the size to simplify wrap handling) - int echo_hist [echo_hist_size * 2] [2]; - int (*echo_hist_pos) [2]; // &echo_hist [0 to 7] - - int every_other_sample; // toggles every sample - int kon; // KON value when last checked - int noise; - int counter; - int echo_offset; // offset from ESA in echo buffer - int echo_length; // number of bytes that echo_offset will stop at - int phase; // next clock cycle to run (0-31) - bool kon_check; // set when a new KON occurs - - // Hidden registers also written to when main register is written to - int new_kon; - uint8_t endx_buf; - uint8_t envx_buf; - uint8_t outx_buf; - - // Temporary state between clocks - - // read once per sample - int t_pmon; - int t_non; - int t_eon; - int t_dir; - int t_koff; - - // read a few clocks ahead then used - int t_brr_next_addr; - int t_adsr0; - int t_brr_header; - int t_brr_byte; - int t_srcn; - int t_esa; - int t_echo_enabled; - - // internal state that is recalculated every sample - int t_dir_addr; - int t_pitch; - int t_output; - int t_looped; - int t_echo_ptr; - - // left/right sums - int t_main_out [2]; - int t_echo_out [2]; - int t_echo_in [2]; - - voice_t voices [voice_count]; - - // non-emulation state - uint8_t* ram; // 64K shared RAM between DSP and SMP - int mute_mask; - sample_t* out; - sample_t* out_end; - sample_t* out_begin; - sample_t extra [extra_size]; - }; - state_t m; - - void init_counter(); - void run_counters(); - unsigned read_counter( int rate ); - - int interpolate( voice_t const* v ); - void run_envelope( voice_t* const v ); - void decode_brr( voice_t* v ); - - void misc_27(); - void misc_28(); - void misc_29(); - void misc_30(); - - void voice_output( voice_t const* v, int ch ); - void voice_V1( voice_t* const ); - void voice_V2( voice_t* const ); - void voice_V3( voice_t* const ); - void voice_V3a( voice_t* const ); - void voice_V3b( voice_t* const ); - void voice_V3c( voice_t* const ); - void voice_V4( voice_t* const ); - void voice_V5( voice_t* const ); - void voice_V6( voice_t* const ); - void voice_V7( voice_t* const ); - void voice_V8( voice_t* const ); - void voice_V9( voice_t* const ); - void voice_V7_V4_V1( voice_t* const ); - void voice_V8_V5_V2( voice_t* const ); - void voice_V9_V6_V3( voice_t* const ); - - void echo_read( int ch ); - int echo_output( int ch ); - void echo_write( int ch ); - void echo_22(); - void echo_23(); - void echo_24(); - void echo_25(); - void echo_26(); - void echo_27(); - void echo_28(); - void echo_29(); - void echo_30(); - - void soft_reset_common(); -}; - -#include - -inline int SPC_DSP::sample_count() const { return m.out - m.out_begin; } - -inline int SPC_DSP::read( int addr ) const -{ - assert( (unsigned) addr < register_count ); - return m.regs [addr]; -} - -inline void SPC_DSP::write( int addr, int data ) -{ - assert( (unsigned) addr < register_count ); - - m.regs [addr] = (uint8_t) data; - switch ( addr & 0x0F ) - { - case v_envx: - m.envx_buf = (uint8_t) data; - break; - - case v_outx: - m.outx_buf = (uint8_t) data; - break; - - case 0x0C: - if ( addr == r_kon ) - m.new_kon = (uint8_t) data; - - if ( addr == r_endx ) // always cleared, regardless of data written - { - m.endx_buf = 0; - m.regs [r_endx] = 0; - } - break; - } -} - -inline void SPC_DSP::mute_voices( int mask ) { m.mute_mask = mask; } - -inline bool SPC_DSP::check_kon() -{ - bool old = m.kon_check; - m.kon_check = 0; - return old; -} - -#if !SPC_NO_COPY_STATE_FUNCS - -class SPC_State_Copier { - SPC_DSP::copy_func_t func; - unsigned char** buf; -public: - SPC_State_Copier( unsigned char** p, SPC_DSP::copy_func_t f ) { func = f; buf = p; } - void copy( void* state, size_t size ); - int copy_int( int state, int size ); - void skip( int count ); - void extra(); -}; - -#define SPC_COPY( type, state )\ -{\ - state = (BOOST::type) copier.copy_int( state, sizeof (BOOST::type) );\ - assert( (BOOST::type) state == state );\ -} - -#endif - -#endif diff --git a/apu/SPC_Filter.cpp b/apu/SPC_Filter.cpp deleted file mode 100644 index b3d57708..00000000 --- a/apu/SPC_Filter.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// snes_spc 0.9.0. http://www.slack.net/~ant/ - -#include "SPC_Filter.h" - -#include - -/* Copyright (C) 2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -void SPC_Filter::clear() { memset( ch, 0, sizeof ch ); } - -SPC_Filter::SPC_Filter() -{ - gain = gain_unit; - bass = bass_norm; - clear(); -} - -void SPC_Filter::run( short* io, int count ) -{ - require( (count & 1) == 0 ); // must be even - - int const gain = this->gain; - int const bass = this->bass; - chan_t* c = &ch [2]; - do - { - // cache in registers - int sum = (--c)->sum; - int pp1 = c->pp1; - int p1 = c->p1; - - for ( int i = 0; i < count; i += 2 ) - { - // Low-pass filter (two point FIR with coeffs 0.25, 0.75) - int f = io [i] + p1; - p1 = io [i] * 3; - - // High-pass filter ("leaky integrator") - int delta = f - pp1; - pp1 = f; - int s = sum >> (gain_bits + 2); - sum += (delta * gain) - (sum >> bass); - - // Clamp to 16 bits - if ( (short) s != s ) - s = (s >> 31) ^ 0x7FFF; - - io [i] = (short) s; - } - - c->p1 = p1; - c->pp1 = pp1; - c->sum = sum; - ++io; - } - while ( c != ch ); -} diff --git a/apu/SPC_Filter.h b/apu/SPC_Filter.h deleted file mode 100644 index d5c83cb8..00000000 --- a/apu/SPC_Filter.h +++ /dev/null @@ -1,47 +0,0 @@ -// Simple low-pass and high-pass filter to better match sound output of a SNES - -// snes_spc 0.9.0 -#ifndef SPC_FILTER_H -#define SPC_FILTER_H - -#include "blargg_common.h" - -struct SPC_Filter { -public: - - // Filters count samples of stereo sound in place. Count must be a multiple of 2. - typedef short sample_t; - void run( sample_t* io, int count ); - -// Optional features - - // Clears filter to silence - void clear(); - - // Sets gain (volume), where gain_unit is normal. Gains greater than gain_unit - // are fine, since output is clamped to 16-bit sample range. - enum { gain_unit = 0x100 }; - void set_gain( int gain ); - - // Sets amount of bass (logarithmic scale) - enum { bass_none = 0 }; - enum { bass_norm = 8 }; // normal amount - enum { bass_max = 31 }; - void set_bass( int bass ); - -public: - SPC_Filter(); - BLARGG_DISABLE_NOTHROW -private: - enum { gain_bits = 8 }; - int gain; - int bass; - struct chan_t { int p1, pp1, sum; }; - chan_t ch [2]; -}; - -inline void SPC_Filter::set_gain( int g ) { gain = g; } - -inline void SPC_Filter::set_bass( int b ) { bass = b; } - -#endif diff --git a/apu/apu.cpp b/apu/apu.cpp index 47f03b6b..de70a4e1 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -175,14 +175,13 @@ Nintendo Co., Limited and its subsidiary companies. ***********************************************************************************/ - #include #include "snes9x.h" #include "apu.h" #include "snapshot.h" #include "display.h" -#include "linear_resampler.h" #include "hermite_resampler.h" + #include "snes/snes.hpp" #define APU_DEFAULT_INPUT_RATE 32000 @@ -192,27 +191,12 @@ #define APU_DENOMINATOR_NTSC 328125 #define APU_NUMERATOR_PAL 34176 #define APU_DENOMINATOR_PAL 709379 -#define APU_DEFAULT_RESAMPLER HermiteResampler - -SNES_SPC *spc_core = NULL; namespace SNES { CPU cpu; } -static uint8 APUROM[64] = -{ - 0xCD, 0xEF, 0xBD, 0xE8, 0x00, 0xC6, 0x1D, 0xD0, - 0xFC, 0x8F, 0xAA, 0xF4, 0x8F, 0xBB, 0xF5, 0x78, - 0xCC, 0xF4, 0xD0, 0xFB, 0x2F, 0x19, 0xEB, 0xF4, - 0xD0, 0xFC, 0x7E, 0xF4, 0xD0, 0x0B, 0xE4, 0xF5, - 0xCB, 0xF4, 0xD7, 0x00, 0xFC, 0xD0, 0xF3, 0xAB, - 0x01, 0x10, 0xEF, 0x7E, 0xF4, 0x10, 0xEB, 0xBA, - 0xF6, 0xDA, 0x00, 0xBA, 0xF4, 0xC4, 0xF4, 0xDD, - 0x5D, 0xD0, 0xDB, 0x1F, 0x00, 0x00, 0xC0, 0xFF -}; - namespace spc { static apu_callback sa_callback = NULL; @@ -233,8 +217,8 @@ namespace spc static int32 reference_time; static uint32 remainder; - static const int timing_hack_numerator = SNES_SPC::tempo_unit; - static int timing_hack_denominator = SNES_SPC::tempo_unit; + static const int timing_hack_numerator = 256; + static int timing_hack_denominator = 256; /* Set these to NTSC for now. Will change to PAL in S9xAPUTimingSetSpeedup if necessary on game load. */ static uint32 ratio_numerator = APU_NUMERATOR_NTSC; @@ -360,11 +344,12 @@ int S9xGetSampleCount (void) return (spc::resampler->avail() >> (Settings.Stereo ? 0 : 1)); } +/* TODO: Attach */ void S9xFinalizeSamples (void) { if (!Settings.Mute) { - if (!spc::resampler->push((short *) spc::landing_buffer, spc_core->sample_count())) + if (!spc::resampler->push((short *) spc::landing_buffer, SNES::dsp.spc_dsp.sample_count ())) { /* We weren't able to process the entire buffer. Potential overrun. */ spc::sound_in_sync = FALSE; @@ -382,7 +367,7 @@ void S9xFinalizeSamples (void) else spc::sound_in_sync = FALSE; - spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + SNES::dsp.spc_dsp.set_output((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); } void S9xLandSamples (void) @@ -458,7 +443,7 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms) arguments. Use 2x in the resampler for buffer leveling with SoundSync */ if (!spc::resampler) { - spc::resampler = new APU_DEFAULT_RESAMPLER(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)); + spc::resampler = new HermiteResampler(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)); if (!spc::resampler) { delete[] spc::landing_buffer; @@ -468,7 +453,7 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms) else spc::resampler->resize(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)); - spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); UpdatePlaybackRate(); @@ -479,7 +464,8 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms) void S9xSetSoundControl (uint8 voice_switch) { - spc_core->dsp_set_stereo_switch(voice_switch << 8 | voice_switch); + /* + spc_core->dsp_set_stereo_switch(voice_switch << 8 | voice_switch); */ } void S9xSetSoundMute (bool8 mute) @@ -491,7 +477,8 @@ void S9xSetSoundMute (bool8 mute) void S9xDumpSPCSnapshot (void) { - spc_core->dsp_dump_spc_snapshot(); +/* No SPC dumping ATM in byuu SMP */ +/* spc_core->dsp_dump_spc_snapshot(); */ } static void SPCSnapshotCallback (void) @@ -502,15 +489,6 @@ static void SPCSnapshotCallback (void) bool8 S9xInitAPU (void) { - spc_core = new SNES_SPC; - if (!spc_core) - return (FALSE); - - spc_core->init(); - spc_core->init_rom(APUROM); - - spc_core->dsp_set_spc_snapshot_callback(SPCSnapshotCallback); - spc::landing_buffer = NULL; spc::shrink_buffer = NULL; spc::resampler = NULL; @@ -520,12 +498,6 @@ bool8 S9xInitAPU (void) void S9xDeinitAPU (void) { - if (spc_core) - { - delete spc_core; - spc_core = NULL; - } - if (spc::resampler) { delete spc::resampler; @@ -559,12 +531,14 @@ static inline int S9xAPUGetClockRemainder (int32 cpucycles) uint8 S9xAPUReadPort (int port) { - return ((uint8) spc_core->read_port(S9xAPUGetClock(CPU.Cycles), port)); + S9xAPUExecute (); + return ((uint8) SNES::smp.port_read (port & 3)); } void S9xAPUWritePort (int port, uint8 byte) { - spc_core->write_port(S9xAPUGetClock(CPU.Cycles), port, byte); + S9xAPUExecute (); + SNES::smp.port_write (port & 3, byte); } void S9xAPUSetReferenceTime (int32 cpucycles) @@ -574,8 +548,8 @@ void S9xAPUSetReferenceTime (int32 cpucycles) void S9xAPUExecute (void) { - /* Accumulate partial APU cycles */ - spc_core->end_frame(S9xAPUGetClock(CPU.Cycles)); + SNES::smp.clock -= S9xAPUGetClock (CPU.Cycles); + SNES::smp.enter (); spc::remainder = S9xAPUGetClockRemainder(CPU.Cycles); @@ -586,7 +560,7 @@ void S9xAPUEndScanline (void) { S9xAPUExecute(); - if (spc_core->sample_count() >= APU_MINIMUM_SAMPLE_BLOCK || !spc::sound_in_sync) + if (SNES::dsp.spc_dsp.sample_count() >= APU_MINIMUM_SAMPLE_BLOCK || !spc::sound_in_sync) S9xLandSamples(); } @@ -595,8 +569,7 @@ void S9xAPUTimingSetSpeedup (int ticks) if (ticks != 0) printf("APU speedup hack: %d\n", ticks); - spc::timing_hack_denominator = SNES_SPC::tempo_unit - ticks; - spc_core->set_tempo(spc::timing_hack_denominator); + spc::timing_hack_denominator = 256 - ticks; spc::ratio_numerator = Settings.PAL ? APU_NUMERATOR_PAL : APU_NUMERATOR_NTSC; spc::ratio_denominator = Settings.PAL ? APU_DENOMINATOR_PAL : APU_DENOMINATOR_NTSC; @@ -610,15 +583,18 @@ void S9xAPUAllowTimeOverflow (bool allow) if (allow) printf("APU time overflow allowed\n"); - spc_core->spc_allow_time_overflow(allow); + /* spc_core->spc_allow_time_overflow(allow); */ } void S9xResetAPU (void) { spc::reference_time = 0; spc::remainder = 0; - spc_core->reset(); - spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + + SNES::cpu.frequency = Settings.PAL ? PAL_MASTER_CLOCK : NTSC_MASTER_CLOCK; + SNES::smp.power (); + SNES::dsp.power (); + SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); spc::resampler->clear(); } @@ -627,38 +603,27 @@ void S9xSoftResetAPU (void) { spc::reference_time = 0; spc::remainder = 0; - spc_core->soft_reset(); - spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + SNES::smp.reset (); + SNES::dsp.reset (); + SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); spc::resampler->clear(); } -static void from_apu_to_state (uint8 **buf, void *var, size_t size) -{ - memcpy(*buf, var, size); - *buf += size; -} - -static void to_apu_from_state (uint8 **buf, void *var, size_t size) -{ - memcpy(var, *buf, size); - *buf += size; -} - void S9xAPUSaveState (uint8 *block) { - uint8 *ptr = block; +/* uint8 *ptr = block; spc_core->copy_state(&ptr, from_apu_to_state); SET_LE32(ptr, spc::reference_time); ptr += sizeof(int32); - SET_LE32(ptr, spc::remainder); + SET_LE32(ptr, spc::remainder); */ } void S9xAPULoadState (uint8 *block) { - uint8 *ptr = block; + /*uint8 *ptr = block; S9xResetAPU(); @@ -666,5 +631,5 @@ void S9xAPULoadState (uint8 *block) spc::reference_time = GET_LE32(ptr); ptr += sizeof(int32); - spc::remainder = GET_LE32(ptr); + spc::remainder = GET_LE32(ptr); */ } diff --git a/apu/apu.h b/apu/apu.h index 358469da..c0967caa 100644 --- a/apu/apu.h +++ b/apu/apu.h @@ -180,7 +180,6 @@ #define _APU_H_ #include "snes9x.h" -#include "SNES_SPC.h" typedef void (*apu_callback) (void *); @@ -214,6 +213,4 @@ void S9xClearSamples (void); bool8 S9xMixSamples (uint8 *, int); void S9xSetSamplesAvailableCallback (apu_callback, void *); -extern SNES_SPC *spc_core; - #endif diff --git a/apu/bapu/dsp/dsp.cpp b/apu/bapu/dsp/dsp.cpp index f82bd824..c0a2a9c8 100755 --- a/apu/bapu/dsp/dsp.cpp +++ b/apu/bapu/dsp/dsp.cpp @@ -18,12 +18,6 @@ void DSP::synchronize_smp() { void DSP::enter() { spc_dsp.run(1); step(24); - -/* signed count = spc_dsp.sample_count(); - if(count > 0) { - for(unsigned n = 0; n < count; n += 2) audio.sample(samplebuffer[n + 0], samplebuffer[n + 1]); - spc_dsp.set_output(samplebuffer, 8192); - } */ } uint8 DSP::read(uint8 addr) { @@ -37,12 +31,10 @@ void DSP::write(uint8 addr, uint8 data) { void DSP::power() { spc_dsp.init(smp.apuram); spc_dsp.reset(); - spc_dsp.set_output(samplebuffer, 8192); } void DSP::reset() { spc_dsp.soft_reset(); - spc_dsp.set_output(samplebuffer, 8192); } void DSP::channel_enable(unsigned channel, bool enable) { diff --git a/apu/bapu/dsp/dsp.hpp b/apu/bapu/dsp/dsp.hpp index 634c6da4..ef2dc7c7 100755 --- a/apu/bapu/dsp/dsp.hpp +++ b/apu/bapu/dsp/dsp.hpp @@ -17,9 +17,9 @@ public: DSP(); -private: SPC_DSP spc_dsp; - int16 samplebuffer[8192]; + +private: bool channel_enabled[8]; }; diff --git a/apu/bapu/smp/smp.cpp b/apu/bapu/smp/smp.cpp index ba26d0b4..04a2da4e 100755 --- a/apu/bapu/smp/smp.cpp +++ b/apu/bapu/smp/smp.cpp @@ -42,8 +42,6 @@ void SMP::enter() { void SMP::power() { #ifdef BSNES Processor::frequency = system.apu_frequency(); -#else - Processor::frequency = 1025600; #endif Processor::clock = 0; diff --git a/apu/bapu/snes/snes.hpp b/apu/bapu/snes/snes.hpp index 47b687ff..b4010a67 100755 --- a/apu/bapu/snes/snes.hpp +++ b/apu/bapu/snes/snes.hpp @@ -23,10 +23,12 @@ public: void enter () { + return; } void port_write (uint8 port, uint8 data) { + } uint8 port_read (uint8 port) diff --git a/apu/blargg_common.h b/apu/blargg_common.h deleted file mode 100644 index 75edff39..00000000 --- a/apu/blargg_common.h +++ /dev/null @@ -1,186 +0,0 @@ -// Sets up common environment for Shay Green's libraries. -// To change configuration options, modify blargg_config.h, not this file. - -// snes_spc 0.9.0 -#ifndef BLARGG_COMMON_H -#define BLARGG_COMMON_H - -#include -#include -#include -#include - -#undef BLARGG_COMMON_H -// allow blargg_config.h to #include blargg_common.h -#include "blargg_config.h" -#ifndef BLARGG_COMMON_H -#define BLARGG_COMMON_H - -// BLARGG_RESTRICT: equivalent to restrict, where supported -#if defined (__GNUC__) || _MSC_VER >= 1100 - #define BLARGG_RESTRICT __restrict -#else - #define BLARGG_RESTRICT -#endif - -// STATIC_CAST(T,expr): Used in place of static_cast (expr) -#ifndef STATIC_CAST - #define STATIC_CAST(T,expr) ((T) (expr)) -#endif - -// blargg_err_t (0 on success, otherwise error string) -#ifndef blargg_err_t - typedef const char* blargg_err_t; -#endif - -// blargg_vector - very lightweight vector of POD types (no constructor/destructor) -template -class blargg_vector { - T* begin_; - size_t size_; -public: - blargg_vector() : begin_( 0 ), size_( 0 ) { } - ~blargg_vector() { free( begin_ ); } - size_t size() const { return size_; } - T* begin() const { return begin_; } - T* end() const { return begin_ + size_; } - blargg_err_t resize( size_t n ) - { - // TODO: blargg_common.cpp to hold this as an outline function, ugh - void* p = realloc( begin_, n * sizeof (T) ); - if ( p ) - begin_ = (T*) p; - else if ( n > size_ ) // realloc failure only a problem if expanding - return "Out of memory"; - size_ = n; - return 0; - } - void clear() { void* p = begin_; begin_ = 0; size_ = 0; free( p ); } - T& operator [] ( size_t n ) const - { - assert( n <= size_ ); // <= to allow past-the-end value - return begin_ [n]; - } -}; - -#ifndef BLARGG_DISABLE_NOTHROW - // throw spec mandatory in ISO C++ if operator new can return NULL - #if __cplusplus >= 199711 || defined (__GNUC__) - #define BLARGG_THROWS( spec ) throw spec - #else - #define BLARGG_THROWS( spec ) - #endif - #define BLARGG_DISABLE_NOTHROW \ - void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\ - void operator delete ( void* p ) { free( p ); } - #define BLARGG_NEW new -#else - #include - #define BLARGG_NEW new (std::nothrow) -#endif - -// BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant) -#define BLARGG_4CHAR( a, b, c, d ) \ - ((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF)) - -// BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0. -#ifndef BOOST_STATIC_ASSERT - #ifdef _MSC_VER - // MSVC6 (_MSC_VER < 1300) fails for use of __LINE__ when /Zl is specified - #define BOOST_STATIC_ASSERT( expr ) \ - void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] ) - #else - // Some other compilers fail when declaring same function multiple times in class, - // so differentiate them by line - #define BOOST_STATIC_ASSERT( expr ) \ - void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] ) - #endif -#endif - -// BLARGG_COMPILER_HAS_BOOL: If 0, provides bool support for old compiler. If 1, -// compiler is assumed to support bool. If undefined, availability is determined. -#ifndef BLARGG_COMPILER_HAS_BOOL - #if defined (__MWERKS__) - #if !__option(bool) - #define BLARGG_COMPILER_HAS_BOOL 0 - #endif - #elif defined (_MSC_VER) - #if _MSC_VER < 1100 - #define BLARGG_COMPILER_HAS_BOOL 0 - #endif - #elif defined (__GNUC__) - // supports bool - #elif __cplusplus < 199711 - #define BLARGG_COMPILER_HAS_BOOL 0 - #endif -#endif -#if defined (BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL - // If you get errors here, modify your blargg_config.h file - typedef int bool; - const bool true = 1; - const bool false = 0; -#endif - -// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough - -#if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF - typedef long blargg_long; -#else - typedef int blargg_long; -#endif - -#if UINT_MAX < 0xFFFFFFFF || ULONG_MAX == 0xFFFFFFFF - typedef unsigned long blargg_ulong; -#else - typedef unsigned blargg_ulong; -#endif - -// BOOST::int8_t etc. - -// HAVE_STDINT_H: If defined, use for int8_t etc. -#if defined (HAVE_STDINT_H) - #include - #define BOOST - -// HAVE_INTTYPES_H: If defined, use for int8_t etc. -#elif defined (HAVE_INTTYPES_H) - #include - #define BOOST - -#else - struct BOOST - { - #if UCHAR_MAX == 0xFF && SCHAR_MAX == 0x7F - typedef signed char int8_t; - typedef unsigned char uint8_t; - #else - // No suitable 8-bit type available - typedef struct see_blargg_common_h int8_t; - typedef struct see_blargg_common_h uint8_t; - #endif - - #if USHRT_MAX == 0xFFFF - typedef short int16_t; - typedef unsigned short uint16_t; - #else - // No suitable 16-bit type available - typedef struct see_blargg_common_h int16_t; - typedef struct see_blargg_common_h uint16_t; - #endif - - #if ULONG_MAX == 0xFFFFFFFF - typedef long int32_t; - typedef unsigned long uint32_t; - #elif UINT_MAX == 0xFFFFFFFF - typedef int int32_t; - typedef unsigned int uint32_t; - #else - // No suitable 32-bit type available - typedef struct see_blargg_common_h int32_t; - typedef struct see_blargg_common_h uint32_t; - #endif - }; -#endif - -#endif -#endif diff --git a/apu/blargg_config.h b/apu/blargg_config.h deleted file mode 100644 index 9dc69db8..00000000 --- a/apu/blargg_config.h +++ /dev/null @@ -1,24 +0,0 @@ -// snes_spc 0.9.0 user configuration file. Don't replace when updating library. - -// snes_spc 0.9.0 -#ifndef BLARGG_CONFIG_H -#define BLARGG_CONFIG_H - -// Uncomment to disable debugging checks -//#define NDEBUG 1 - -// Uncomment to enable platform-specific (and possibly non-portable) optimizations -//#define BLARGG_NONPORTABLE 1 - -// Uncomment if automatic byte-order determination doesn't work -//#define BLARGG_BIG_ENDIAN 1 - -// Uncomment if you get errors in the bool section of blargg_common.h -//#define BLARGG_COMPILER_HAS_BOOL 1 - -// Use standard config.h if present -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif - -#endif diff --git a/apu/blargg_endian.h b/apu/blargg_endian.h deleted file mode 100644 index f2daca64..00000000 --- a/apu/blargg_endian.h +++ /dev/null @@ -1,185 +0,0 @@ -// CPU Byte Order Utilities - -// snes_spc 0.9.0 -#ifndef BLARGG_ENDIAN -#define BLARGG_ENDIAN - -#include "blargg_common.h" - -// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16) -#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \ - defined (__x86_64__) || defined (__ia64__) || defined (__i386__) - #define BLARGG_CPU_X86 1 - #define BLARGG_CPU_CISC 1 -#endif - -#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc) - #define BLARGG_CPU_POWERPC 1 - #define BLARGG_CPU_RISC 1 -#endif - -// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only -// one may be #defined to 1. Only needed if something actually depends on byte order. -#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN) -#ifdef __GLIBC__ - // GCC handles this for us - #include - #if __BYTE_ORDER == __LITTLE_ENDIAN - #define BLARGG_LITTLE_ENDIAN 1 - #elif __BYTE_ORDER == __BIG_ENDIAN - #define BLARGG_BIG_ENDIAN 1 - #endif -#else - -#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \ - (defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234) - #define BLARGG_LITTLE_ENDIAN 1 -#endif - -#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \ - defined (__sparc__) || BLARGG_CPU_POWERPC || \ - (defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321) - #define BLARGG_BIG_ENDIAN 1 -#elif !defined (__mips__) - // No endian specified; assume little-endian, since it's most common - #define BLARGG_LITTLE_ENDIAN 1 -#endif -#endif -#endif - -#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN - #undef BLARGG_LITTLE_ENDIAN - #undef BLARGG_BIG_ENDIAN -#endif - -inline void blargg_verify_byte_order() -{ - #ifndef NDEBUG - #if BLARGG_BIG_ENDIAN - volatile int i = 1; - assert( *(volatile char*) &i == 0 ); - #elif BLARGG_LITTLE_ENDIAN - volatile int i = 1; - assert( *(volatile char*) &i != 0 ); - #endif - #endif -} - -inline unsigned get_le16( void const* p ) -{ - return (unsigned) ((unsigned char const*) p) [1] << 8 | - (unsigned) ((unsigned char const*) p) [0]; -} - -inline unsigned get_be16( void const* p ) -{ - return (unsigned) ((unsigned char const*) p) [0] << 8 | - (unsigned) ((unsigned char const*) p) [1]; -} - -inline blargg_ulong get_le32( void const* p ) -{ - return (blargg_ulong) ((unsigned char const*) p) [3] << 24 | - (blargg_ulong) ((unsigned char const*) p) [2] << 16 | - (blargg_ulong) ((unsigned char const*) p) [1] << 8 | - (blargg_ulong) ((unsigned char const*) p) [0]; -} - -inline blargg_ulong get_be32( void const* p ) -{ - return (blargg_ulong) ((unsigned char const*) p) [0] << 24 | - (blargg_ulong) ((unsigned char const*) p) [1] << 16 | - (blargg_ulong) ((unsigned char const*) p) [2] << 8 | - (blargg_ulong) ((unsigned char const*) p) [3]; -} - -inline void set_le16( void* p, unsigned n ) -{ - ((unsigned char*) p) [1] = (unsigned char) (n >> 8); - ((unsigned char*) p) [0] = (unsigned char) n; -} - -inline void set_be16( void* p, unsigned n ) -{ - ((unsigned char*) p) [0] = (unsigned char) (n >> 8); - ((unsigned char*) p) [1] = (unsigned char) n; -} - -inline void set_le32( void* p, blargg_ulong n ) -{ - ((unsigned char*) p) [0] = (unsigned char) n; - ((unsigned char*) p) [1] = (unsigned char) (n >> 8); - ((unsigned char*) p) [2] = (unsigned char) (n >> 16); - ((unsigned char*) p) [3] = (unsigned char) (n >> 24); -} - -inline void set_be32( void* p, blargg_ulong n ) -{ - ((unsigned char*) p) [3] = (unsigned char) n; - ((unsigned char*) p) [2] = (unsigned char) (n >> 8); - ((unsigned char*) p) [1] = (unsigned char) (n >> 16); - ((unsigned char*) p) [0] = (unsigned char) (n >> 24); -} - -#if BLARGG_NONPORTABLE - // Optimized implementation if byte order is known - #if BLARGG_LITTLE_ENDIAN - #define GET_LE16( addr ) (*(BOOST::uint16_t*) (addr)) - #define GET_LE32( addr ) (*(BOOST::uint32_t*) (addr)) - #define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) - #define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) - #elif BLARGG_BIG_ENDIAN - #define GET_BE16( addr ) (*(BOOST::uint16_t*) (addr)) - #define GET_BE32( addr ) (*(BOOST::uint32_t*) (addr)) - #define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) - #define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) - - #if BLARGG_CPU_POWERPC - // PowerPC has special byte-reversed instructions - #if defined (__MWERKS__) - #define GET_LE16( addr ) (__lhbrx( addr, 0 )) - #define GET_LE32( addr ) (__lwbrx( addr, 0 )) - #define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 )) - #define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 )) - #elif defined (__GNUC__) - #define GET_LE16( addr ) ({unsigned ppc_lhbrx_; asm( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr), "0" (ppc_lhbrx_) ); ppc_lhbrx_;}) - #define GET_LE32( addr ) ({unsigned ppc_lwbrx_; asm( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr), "0" (ppc_lwbrx_) ); ppc_lwbrx_;}) - #define SET_LE16( addr, in ) ({asm( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) );}) - #define SET_LE32( addr, in ) ({asm( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) );}) - #endif - #endif - #endif -#endif - -#ifndef GET_LE16 - #define GET_LE16( addr ) get_le16( addr ) - #define SET_LE16( addr, data ) set_le16( addr, data ) -#endif - -#ifndef GET_LE32 - #define GET_LE32( addr ) get_le32( addr ) - #define SET_LE32( addr, data ) set_le32( addr, data ) -#endif - -#ifndef GET_BE16 - #define GET_BE16( addr ) get_be16( addr ) - #define SET_BE16( addr, data ) set_be16( addr, data ) -#endif - -#ifndef GET_BE32 - #define GET_BE32( addr ) get_be32( addr ) - #define SET_BE32( addr, data ) set_be32( addr, data ) -#endif - -// auto-selecting versions - -inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); } -inline void set_le( BOOST::uint32_t* p, blargg_ulong n ) { SET_LE32( p, n ); } -inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); } -inline void set_be( BOOST::uint32_t* p, blargg_ulong n ) { SET_BE32( p, n ); } -inline unsigned get_le( BOOST::uint16_t* p ) { return GET_LE16( p ); } -inline blargg_ulong get_le( BOOST::uint32_t* p ) { return GET_LE32( p ); } -inline unsigned get_be( BOOST::uint16_t* p ) { return GET_BE16( p ); } -inline blargg_ulong get_be( BOOST::uint32_t* p ) { return GET_BE32( p ); } - -#endif diff --git a/apu/blargg_source.h b/apu/blargg_source.h deleted file mode 100644 index 5e45c4fb..00000000 --- a/apu/blargg_source.h +++ /dev/null @@ -1,100 +0,0 @@ -/* Included at the beginning of library source files, after all other #include lines. -Sets up helpful macros and services used in my source code. They don't need -module an annoying module prefix on their names since they are defined after -all other #include lines. */ - -// snes_spc 0.9.0 -#ifndef BLARGG_SOURCE_H -#define BLARGG_SOURCE_H - -// If debugging is enabled, abort program if expr is false. Meant for checking -// internal state and consistency. A failed assertion indicates a bug in the module. -// void assert( bool expr ); -#include - -// If debugging is enabled and expr is false, abort program. Meant for checking -// caller-supplied parameters and operations that are outside the control of the -// module. A failed requirement indicates a bug outside the module. -// void require( bool expr ); -#undef require -#define require( expr ) assert( expr ) - -// Like printf() except output goes to debug log file. Might be defined to do -// nothing (not even evaluate its arguments). -// void dprintf( const char* format, ... ); -static inline void blargg_dprintf_( const char*, ... ) { } -#undef dprintf -#define dprintf (1) ? (void) 0 : blargg_dprintf_ - -// If enabled, evaluate expr and if false, make debug log entry with source file -// and line. Meant for finding situations that should be examined further, but that -// don't indicate a problem. In all cases, execution continues normally. -#undef check -#define check( expr ) ((void) 0) - -// If expr yields error string, return it from current function, otherwise continue. -#undef RETURN_ERR -#define RETURN_ERR( expr ) do { \ - blargg_err_t blargg_return_err_ = (expr); \ - if ( blargg_return_err_ ) return blargg_return_err_; \ - } while ( 0 ) - -// If ptr is 0, return out of memory error string. -#undef CHECK_ALLOC -#define CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 ) - -// Avoid any macros which evaluate their arguments multiple times -#undef min -#undef max - -#define DEF_MIN_MAX( type ) \ - static inline type min( type x, type y ) { if ( x < y ) return x; return y; }\ - static inline type max( type x, type y ) { if ( y < x ) return x; return y; } - -DEF_MIN_MAX( int ) -DEF_MIN_MAX( unsigned ) -DEF_MIN_MAX( long ) -DEF_MIN_MAX( unsigned long ) -DEF_MIN_MAX( float ) -DEF_MIN_MAX( double ) - -#undef DEF_MIN_MAX - -/* -// using const references generates crappy code, and I am currenly only using these -// for built-in types, so they take arguments by value - -// TODO: remove -inline int min( int x, int y ) -template -inline T min( T x, T y ) -{ - if ( x < y ) - return x; - return y; -} - -template -inline T max( T x, T y ) -{ - if ( x < y ) - return y; - return x; -} -*/ - -// TODO: good idea? bad idea? -#undef byte -#define byte byte_ -typedef unsigned char byte; - -// deprecated -#define BLARGG_CHECK_ALLOC CHECK_ALLOC -#define BLARGG_RETURN_ERR RETURN_ERR - -// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf and check -#ifdef BLARGG_SOURCE_BEGIN - #include BLARGG_SOURCE_BEGIN -#endif - -#endif diff --git a/apu/license.txt b/apu/license.txt deleted file mode 100644 index 5ab7695a..00000000 --- a/apu/license.txt +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/apu/linear_resampler.h b/apu/linear_resampler.h deleted file mode 100644 index 35789db1..00000000 --- a/apu/linear_resampler.h +++ /dev/null @@ -1,115 +0,0 @@ -/* Simple fixed-point linear resampler by BearOso*/ - -#ifndef __LINEAR_RESAMPLER_H -#define __LINEAR_RESAMPLER_H - -#include "resampler.h" -#include "snes9x.h" - -static const int f_prec = 15; -static const uint32 f__one = (1 << f_prec); - -#define lerp(t, a, b) (((((b) - (a)) * (t)) >> f_prec) + (a)) - -class LinearResampler : public Resampler -{ - protected: - uint32 f__r_step; - uint32 f__inv_r_step; - uint32 f__r_frac; - int r_left, r_right; - - public: - LinearResampler (int num_samples) : Resampler (num_samples) - { - f__r_frac = 0; - } - - ~LinearResampler () - { - } - - void - time_ratio (double ratio) - { - if (ratio == 0.0) - ratio = 1.0; - f__r_step = (uint32) (ratio * f__one); - f__inv_r_step = (uint32) (f__one / ratio); - clear (); - } - - void - clear (void) - { - ring_buffer::clear (); - f__r_frac = 0; - r_left = 0; - r_right = 0; - } - - void - read (short *data, int num_samples) - { - int i_position = start >> 1; - short *internal_buffer = (short *) buffer; - int o_position = 0; - int consumed = 0; - int max_samples = (buffer_size >> 1); - - while (o_position < num_samples && consumed < buffer_size) - { - if (f__r_step == f__one) - { - data[o_position] = internal_buffer[i_position]; - data[o_position + 1] = internal_buffer[i_position + 1]; - - o_position += 2; - i_position += 2; - if (i_position >= max_samples) - i_position -= max_samples; - consumed += 2; - - continue; - } - - while (f__r_frac <= f__one && o_position < num_samples) - { - data[o_position] = lerp (f__r_frac, - r_left, - internal_buffer[i_position]); - data[o_position + 1] = lerp (f__r_frac, - r_right, - internal_buffer[i_position + 1]); - - o_position += 2; - - f__r_frac += f__r_step; - } - - if (f__r_frac > f__one) - { - f__r_frac -= f__one; - r_left = internal_buffer[i_position]; - r_right = internal_buffer[i_position + 1]; - i_position += 2; - if (i_position >= max_samples) - i_position -= max_samples; - consumed += 2; - } - } - - size -= consumed << 1; - start += consumed << 1; - if (start >= buffer_size) - start -= buffer_size; - } - - inline int - avail (void) - { - return (((size >> 2) * f__inv_r_step) - ((f__r_frac * f__inv_r_step) >> f_prec)) >> (f_prec - 1); - } -}; - -#endif /* __LINEAR_RESAMPLER_H */ diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 4ec45d06..607d70bb 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -119,11 +119,7 @@ endif # APU snes9x_gtk_SOURCES += \ - ../apu/apu.cpp \ - ../apu/SNES_SPC.cpp \ - ../apu/SNES_SPC_misc.cpp \ - ../apu/SNES_SPC_state.cpp \ - ../apu/SPC_Filter.cpp + ../apu/apu.cpp # Byuu's APU snes9x_gtk_SOURCES += \ diff --git a/snapshot.cpp b/snapshot.cpp index 7b758b42..e2163de6 100644 --- a/snapshot.cpp +++ b/snapshot.cpp @@ -1269,7 +1269,7 @@ bool8 S9xUnfreezeGame (const char *filename) void S9xFreezeToStream (STREAM stream) { char buffer[1024]; - uint8 *soundsnapshot = new uint8[SPC_SAVE_STATE_BLOCK_SIZE]; + //uint8 *soundsnapshot = new uint8[SPC_SAVE_STATE_BLOCK_SIZE]; S9xSetSoundMute(TRUE); @@ -1298,8 +1298,8 @@ void S9xFreezeToStream (STREAM stream) FreezeBlock (stream, "FIL", Memory.FillRAM, 0x8000); - S9xAPUSaveState(soundsnapshot); - FreezeBlock (stream, "SND", soundsnapshot, SPC_SAVE_STATE_BLOCK_SIZE); + //S9xAPUSaveState(soundsnapshot); + //FreezeBlock (stream, "SND", soundsnapshot, SPC_SAVE_STATE_BLOCK_SIZE); struct SControlSnapshot ctl_snap; S9xControlPreSaveState(&ctl_snap); @@ -1410,7 +1410,7 @@ void S9xFreezeToStream (STREAM stream) S9xSetSoundMute(FALSE); - delete [] soundsnapshot; + //delete [] soundsnapshot; } int S9xUnfreezeFromStream (STREAM stream) @@ -1496,7 +1496,7 @@ int S9xUnfreezeFromStream (STREAM stream) if (result != SUCCESS) break; - result = UnfreezeBlockCopy (stream, "SND", &local_apu_sound, SPC_SAVE_STATE_BLOCK_SIZE); + // result = UnfreezeBlockCopy (stream, "SND", &local_apu_sound, SPC_SAVE_STATE_BLOCK_SIZE); if (result != SUCCESS) break; @@ -2278,6 +2278,8 @@ static void UnfreezeStructFromCopy (void *sbase, FreezeData *fields, int num_fie bool8 S9xSPCDump (const char *filename) { + /* No SPC dumping in byuu SMP */ + /* FILE *fs; uint8 buf[SNES_SPC::spc_file_size]; size_t ignore; @@ -2296,6 +2298,6 @@ bool8 S9xSPCDump (const char *filename) fclose(fs); S9xSetSoundMute(FALSE); - + */ return (TRUE); } From 5d5eaedd5e9d95f6d275962dd498c839f97ebe80 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 22 Jun 2011 06:03:29 -0500 Subject: [PATCH 03/33] New SMP is tentatively "running" now. --- apu/apu.cpp | 4 +- apu/bapu/smp/core.cpp | 8 + apu/bapu/smp/smp.cpp | 2 + apu/bapu/snes/snes.hpp | 27 +- gtk/src/snes9x.ui | 14804 +++++++++++++++++++++------------------ 5 files changed, 8004 insertions(+), 6841 deletions(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index de70a4e1..65df1b59 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -538,7 +538,7 @@ uint8 S9xAPUReadPort (int port) void S9xAPUWritePort (int port, uint8 byte) { S9xAPUExecute (); - SNES::smp.port_write (port & 3, byte); + SNES::cpu.port_write (port & 3, byte); } void S9xAPUSetReferenceTime (int32 cpucycles) @@ -591,6 +591,7 @@ void S9xResetAPU (void) spc::reference_time = 0; spc::remainder = 0; + SNES::cpu.reset (); SNES::cpu.frequency = Settings.PAL ? PAL_MASTER_CLOCK : NTSC_MASTER_CLOCK; SNES::smp.power (); SNES::dsp.power (); @@ -603,6 +604,7 @@ void S9xSoftResetAPU (void) { spc::reference_time = 0; spc::remainder = 0; + SNES::cpu.reset (); SNES::smp.reset (); SNES::dsp.reset (); SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp index 6e0a29b2..eb03b46e 100755 --- a/apu/bapu/smp/core.cpp +++ b/apu/bapu/smp/core.cpp @@ -3,7 +3,11 @@ void SMP::tick() { timer1.tick(); timer2.tick(); +#ifdef BSNES clock += cycle_step_cpu; +#else + clock++; +#endif dsp.clock -= 24; synchronize_dsp(); } @@ -71,7 +75,11 @@ void SMP::op_step() { timer1.tick(cycle_count_table[opcode]); timer2.tick(cycle_count_table[opcode]); +#ifdef BSNES clock += cycle_table_cpu[opcode]; +#else + clock += cycle_count_table[opcode]; +#endif dsp.clock -= cycle_table_dsp[opcode]; synchronize_dsp(); diff --git a/apu/bapu/smp/smp.cpp b/apu/bapu/smp/smp.cpp index 04a2da4e..7a1b2e25 100755 --- a/apu/bapu/smp/smp.cpp +++ b/apu/bapu/smp/smp.cpp @@ -20,11 +20,13 @@ namespace SNES { #include "timing.cpp" void SMP::synchronize_cpu() { +#ifdef BSNES if(CPU::Threaded == true) { //if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); } else { while(clock >= 0) cpu.enter(); } +#endif } void SMP::synchronize_dsp() { diff --git a/apu/bapu/snes/snes.hpp b/apu/bapu/snes/snes.hpp index b4010a67..30845973 100755 --- a/apu/bapu/snes/snes.hpp +++ b/apu/bapu/snes/snes.hpp @@ -1,6 +1,8 @@ #ifndef __SNES_HPP #define __SNES_HPP +#define CYCLE_ACCURATE + #include "snes9x.h" #define alwaysinline inline @@ -12,36 +14,43 @@ namespace SNES struct Processor { unsigned frequency; - int64 clock; + int clock; }; +#include "smp/smp.hpp" +#include "dsp/dsp.hpp" + class CPU { public: enum { Threaded = false }; int frequency; + uint8 registers[4]; - void enter () + inline void enter () { return; } - void port_write (uint8 port, uint8 data) + inline void reset () { - + registers[0] = registers[1] = registers[2] = registers[3] = 0; } - uint8 port_read (uint8 port) + inline void port_write (uint8 port, uint8 data) { - return 0; + registers[port & 3] = data; + } + + inline uint8 port_read (uint8 port) + { + // printf ("APU Read %2x from port %d\n", registers[port & 3], port & 3); + return registers[port & 3]; } }; extern CPU cpu; -#include "smp/smp.hpp" -#include "dsp/dsp.hpp" - } /* namespace SNES */ #endif diff --git a/gtk/src/snes9x.ui b/gtk/src/snes9x.ui index 3f86e43d..2cd0e909 100644 --- a/gtk/src/snes9x.ui +++ b/gtk/src/snes9x.ui @@ -1,5822 +1,108 @@ - + - - GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_SUBSTRUCTURE_MASK - Snes9x - - - - - - - - - True - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - _File - True - - - - - _Open ROM Image... - True - True - image2 - False - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Open Recent - True - - - - - True - - - - - Open with _NetPlay... - True - Open a ROM to use with NetPlay - True - image3 - False - - - - - - True - Open _MultiCart... - True - - - - - - True - - - - - True - _Load State - True - - - - - - True - Slot _0 - True - - - - - - True - Slot _1 - True - - - - - - True - Slot _2 - True - - - - - - True - Slot _3 - True - - - - - - True - Slot _4 - True - - - - - - True - Slot _5 - True - - - - - - True - Slot _6 - True - - - - - - True - Slot _7 - True - - - - - - True - Slot _8 - True - - - - - - True - - - - - True - From _File... - True - - - - - - - - - - True - _Save State - True - - - - - - True - Slot _0 - True - - - - - - True - Slot _1 - True - - - - - - True - Slot _2 - True - - - - - - True - Slot _3 - True - - - - - - True - Slot _4 - True - - - - - - True - Slot _5 - True - - - - - - True - Slot _6 - True - - - - - - True - Slot _7 - True - - - - - - True - Slot _8 - True - - - - - - True - - - - - True - To _File... - True - - - - - - - - - - True - - - - - Save SPC... - True - True - image4 - False - - - - - - True - - - - - Show ROM _Info... - True - True - image5 - False - - - - - - True - - - - - _Quit - True - True - image18 - False - - - - - - - - - - True - _Emulation - True - - - - - Run / _Continue - True - True - image6 - False - - - - - - _Pause - True - True - image7 - False - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - Load _Movie... - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - image8 - False - - - - - - R_ecord Movie... - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - image19 - False - - - - - - _Stop Recording - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - image9 - False - - - - - - _Jump to Frame... - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - image10 - False - - - - - - True - - - - - Sy_nc Clients - True - True - image11 - False - - - - - - True - - - - - Reset - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - image12 - False - - - - - - Soft _Reset - True - True - image13 - False - - - - - - - - - - True - _View - True - - - - - - _Hide Menu - True - True - image14 - False - - - - - - True - _Status Bar - True - - - - - - True - - - - - _Change Size - True - True - image17 - False - - - True - - - True - False - Exact Pixels - True - - - - - True - _1x - True - - - - - - True - _2x - True - - - - - - True - _3x - True - - - - - - True - _4x - True - - - - - - True - _5x - True - - - - - - True - - - - - True - False - Correct Aspect - True - - - - - True - 1x - True - - - - - - True - 2x - True - - - - - - True - 3x - True - - - - - - True - 4x - True - - - - - - True - 5x - True - - - - - - - - - - True - - - - - _Fullscreen - True - True - image15 - False - - - - - - - - - - True - _Options - True - - - - - True - Controller Ports - True - - - - - True - SNES Port 1 - True - - - - - - True - Joypad - True - - - - - - True - Mouse - True - joypad1 - - - - - - True - Superscope - True - True - joypad1 - - - - - - - - - - True - SNES Port 2 - True - - - - - - True - Joypad - True - - - - - - True - Mouse - True - joypad2 - - - - - - True - Multitap - True - joypad2 - - - - - - True - Superscope - True - True - joypad2 - - - - - - - - - - - - - - True - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Cheats... - True - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - _Preferences... - True - True - image16 - False - - - - - - - - - - False - 0 - - - - - 256 - 224 - True - True - GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK | GDK_SUBSTRUCTURE_MASK - - - - - - - - 1 - - - - - True - - - False - 2 - - - - - - - GDK_KEY_PRESS_MASK - Snes9x Preferences - center - 480 - dialog + + 560 + 448 + False + About Snes9x + normal True - - - + True + False + 2 - + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + 5 - + True - True - left - 0 - 1 - 0 - + False + 5 - + True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - never - automatic - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - queue - none - - - True - 5 - - - True - 0 - none - - - True - 5 - 5 - 12 - - - True - 5 - - - Use fullscreen on ROM open - True - True - False - Go to fullscreen mode immediately after opening a ROM - True - True - - - False - False - 0 - - - - - Show frame rate - True - True - False - True - True - - - False - False - 1 - - - - - Use overscanned height - True - True - False - Use SNES extended height. Will probably cause letterboxing - True - True - - - False - False - 2 - - - - - True - 12 - - - Change fullscreen resolution: - True - True - False - Changes the screen resolution when running Snes9x in fullscreen mode - True - True - - - False - False - 0 - - - - - True - liststore14 - - - - 0 - - - - - 1 - - - - - False - False - 3 - - - - - - - - - True - <b>Basic Settings</b> - True - - - - - False - 0 - - - - - True - 0 - none - - - True - 5 - 5 - 12 - - - True - 5 - - - Scale image to fit window - True - True - False - Scales the image so no black bars are present - True - True - - - False - False - 0 - - - - - True - 12 - - - Maintain aspect-ratio: - True - True - False - Scales the image as large as possible without distortion - True - True - - - False - False - 0 - - - - - True - liststore13 - - - - 0 - - - - - False - 1 - - - - - 1 - - - - - True - 5 - - - Use - True - True - False - Allows scaling and filtering to use multiple processors - True - True - - - False - False - 0 - - - - - True - True - adjustment17 - True - True - - - False - 1 - - - - - True - threads for filtering and scaling - - - False - 2 - - - - - 2 - - - - - True - 12 - - - True - High-resolution effect: - - - False - 0 - - - - - True - liststore15 - - - - 0 - - - - - False - 1 - - - - - 3 - - - - - True - 12 - - - True - 0 - Apply scaling filter: - - - False - 0 - - - - - True - liststore12 - - - - - 0 - - - - - False - 1 - - - - - False - False - 4 - - - - - - - - - True - <b>Image Adjustments</b> - True - - - - - False - 1 - - - - - True - 0 - none - - - True - 5 - 5 - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Video preset: - - - False - 0 - - - - - True - - - Composite - True - True - True - - - - False - 0 - - - - - S-Video - True - True - True - - - - False - 1 - - - - - RGB - True - True - True - - - - False - 2 - - - - - Monochrome - True - True - True - - - - False - 3 - - - - - False - 1 - - - - - 0 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 11 - 2 - 12 - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Artifacts: - - - 6 - 7 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Sharpness: - - - 4 - 5 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Brightness: - - - 3 - 4 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Contrast: - - - 2 - 3 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Saturation: - - - 1 - 2 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Hue: - - - GTK_FILL - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment16 - False - -1 - 2 - left - - - 1 - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment15 - False - -1 - 2 - left - - - 1 - 2 - 1 - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment14 - False - -1 - 2 - left - - - 1 - 2 - 2 - 3 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment13 - False - -1 - 2 - left - - - 1 - 2 - 3 - 4 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment12 - False - -1 - 2 - left - - - 1 - 2 - 4 - 5 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment11 - False - -1 - 2 - left - - - 1 - 2 - 6 - 7 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment10 - False - -1 - 2 - left - - - 1 - 2 - 7 - 8 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment9 - False - -1 - 2 - left - - - 1 - 2 - 8 - 9 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment8 - False - -1 - 2 - left - - - 1 - 2 - 9 - 10 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment7 - False - -1 - 2 - left - - - 1 - 2 - 10 - 11 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Gamma: - - - 7 - 8 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Fringing: - - - 8 - 9 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Bleed: - - - 9 - 10 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Resolution: - - - 10 - 11 - GTK_FILL - - - - - True - - - 2 - 5 - 6 - - - - - 1 - - - - - Merge odd and even fields - True - True - False - True - - - 2 - - - - - True - 12 - - - True - 0 - Scanline intensity: - - - False - 0 - - - - - True - liststore11 - - - - 0 - - - - - False - 1 - - - - - 3 - - - - - - - - - True - <b>NTSC Filter</b> - True - - - - - False - 2 - - - - - True - 0 - none - - - True - 5 - 5 - 12 - - - True - 12 - - - True - 0 - Scanline intensity: - - - False - 0 - - - - - True - liststore10 - - - - 0 - - - - - False - 1 - - - - - - - - - True - <b>Scanline Filter</b> - True - - - - - False - 3 - - - - - True - 0 - none - - - True - 5 - 5 - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - liststore9 - - - - - 0 - - - - - 0 - - - - - Bilinear-filter output - True - True - False - True - True - - - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - Sync to vertical blank - True - True - False - Sync the image to the vertical retrace to stop tearing - True - True - - - False - False - 0 - - - - - Reduce input lag - True - True - False - Sync the program with the video output after every displayed frame to reduce input latency - True - - - 1 - - - - - Allow non-power-of-two textures - True - True - False - Prevents edge artifacts, but can slow performance - True - - - 2 - - - - - Use pixel-buffer objects - True - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Can be faster or slower depending on drivers - True - - - 3 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Different formats can yield highly different performance - 10 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Pixel-buffer format: - - - False - 0 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - liststore8 - - - - 0 - - - - - False - 1 - - - - - - - 4 - - - - - True - 5 - - - Use GLSL shader: - True - True - False - 0 - True - - - False - 0 - - - - - True - True - - True - - - 1 - - - - - Browse... - True - True - True - - - - False - 2 - - - - - 5 - - - - - 2 - - - - - True - - - Force an inverted byte-ordering - True - True - False - Forces a swapped byte-ordering for cases where the system's endian is used instead of the video card - True - - - 0 - - - - - 3 - - - - - - - - - True - <b>Hardware Acceleration</b> - True - - - - - False - 4 - - - - - - + False + gtk-missing-image - - - True - - - True - video-display - - - 0 - - - - - True - Display - True - - - False - False - 1 - - - - - False - - + + + False + True + 0 + + + + + True + False + 0 + 10 + 10 + label106 + True + center + True + + + False + True + 1 + + + + + True + False + queue - - True - True - never - automatic - - - True - queue - none - - - True - 5 - 0 - none - - - True - 12 - - - True - 5 - 5 - - - True - 12 - - - True - Sound driver: - - - False - False - 0 - - - - - True - liststore7 - - - - 0 - - - - - False - False - 1 - - - - - False - False - 0 - - - - - Synchronize with sound - True - True - False - Base emulation speed on the rate sound is output - True - - - False - False - 1 - - - - - Mute sound output - True - True - False - Disables output of sound - True - True - - - False - False - 2 - - - - - Stereo - True - True - False - Output two channels, left and right - True - True - - - False - False - 3 - - - - - True - 4 - 2 - 10 - 5 - - - True - 0 - Playback rate: - - - GTK_FILL - - - - - - True - 5 - - - True - True - adjustment6 - True - True - - - False - 0 - - - - - True - milliseconds - - - False - 1 - - - - - 1 - 2 - 3 - 4 - GTK_FILL - GTK_FILL - - - - - True - 0 - Buffer size: - - - 3 - 4 - GTK_FILL - GTK_FILL - - - - - True - 0 - Input rate: - - - 1 - 2 - GTK_FILL - - - - - True - True - Adjust to produce more or less data. Decrease the rate if experiencing crackling. Increase the rate if experiencing frame-rate stuttering. Best used with the "Synchronize with sound" option - adjustment5 - False - 0 - left - - - 1 - 2 - 1 - 2 - - - - - True - - - True - liststore6 - - - - 0 - - - - - False - False - 0 - - - - - 1 - 2 - GTK_FILL - - - - - True - 0 - Video rate: - - - 2 - 3 - GTK_FILL - - - - - True - label - - - 1 - 2 - 2 - 3 - - - - - False - 4 - - - - - - - - - True - <b>Sound Settings</b> - True - - - - - - - - - 1 - - - - - True - - - True - audio-x-generic - - - 0 - - - - - True - Sound - True - - - False - False - 1 - - - - - 1 - False - - - - + True True automatic - automatic - - True - queue - none - - - True - - - True - 5 - 0 - none - - - True - 12 - - - True - 5 - 5 - - - True - 10 - - - True - Frameskip: - - - False - False - 0 - - - - - True - liststore5 - - - - 0 - - - - - False - False - 1 - - - - - False - 0 - - - - - Block invalid VRAM access - True - True - False - True - - - 1 - - - - - Allow opposing dpad directions - True - True - False - Let left and right or up and down be pressed at the same time - True - - - 2 - - - - - - - - - True - <b>Accuracy</b> - True - - - - - False - 0 - - - - - True - 5 - 0 - none - - - True - 12 - - - True - 5 - 5 - - - Pause emulation when switching away from Snes9x - True - True - False - True - - - 0 - - - - - True - 12 - - - True - The ESC key should: - - - False - 0 - - - - - True - liststore4 - - - - 0 - - - - - False - 1 - - - - - 1 - - - - - - - - - True - <b>Window Switching</b> - True - - - - - False - 1 - - - - - True - 5 - 0 - none - - - True - 12 - - - True - 5 - - - Prevent the screensaver from activating - True - True - False - True - - - 0 - - - - - - - - - True - <b>Screensaver</b> - True - - - - - False - 2 - - - - - - - - - 2 - - - - - True - - - True - utilities-terminal - - - 0 - - - - - True - Emulation - True - - - False - False - 1 - - - - - 2 - False - - - - - True - 5 - - - True - 5 - 0 - none - - - True - 12 - - - True - 5 - - - True - 5 - 3 - 5 - 5 - - - True - True - False - - gtk-clear - - - - - 1 - 2 - - - - - True - True - False - - gtk-clear - - - - - 1 - 2 - 1 - 2 - - - - - True - True - False - - gtk-clear - - - - - 1 - 2 - 2 - 3 - - - - - True - True - False - - gtk-clear - - - - - 1 - 2 - 3 - 4 - - - - - True - True - False - - gtk-clear - - - - - 1 - 2 - 4 - 5 - - - - - Browse... - True - True - True - - - - 2 - 3 - GTK_FILL - - - - - - Browse... - True - True - True - - - - 2 - 3 - 1 - 2 - GTK_FILL - - - - - - Browse... - True - True - True - - - - 2 - 3 - 2 - 3 - GTK_FILL - - - - - - Browse... - True - True - True - - - - 2 - 3 - 3 - 4 - GTK_FILL - - - - - - Browse... - True - True - True - - - - 2 - 3 - 4 - 5 - GTK_FILL - - - - - - True - 0 - SRAM: - - - GTK_FILL - - - - - True - 0 - Save states: - - - 1 - 2 - GTK_FILL - - - - - True - 0 - Cheats: - - - 2 - 3 - GTK_FILL - - - - - True - 0 - Patches: - - - 3 - 4 - GTK_FILL - - - - - True - 0 - Exports: - - - 4 - 5 - GTK_FILL - - - - - False - 0 - - - - - - - - - True - <b>Game Data Locations</b> - True - - - - - False - 0 - - - - - True - 0 - none - - - True - 5 - 12 - - - True - 5 - - - True - Save SRAM: - - - False - 0 - - - - - True - True - Automatically save the game's SRAM at this interval. Setting this to 0 will only save when quitting or changing ROMs - - 5 - 1 - - - False - 1 - - - - - True - seconds after change - - - False - 2 - - - - - - - - - True - <b>Automatic Saving</b> - True - - - - - False - 1 - - - - - 3 - - - - - True - - - True - folder - - - 0 - - - - - True - Files - True - - - False - False - 1 - - - - - 3 - False - - - - - True - 5 - 5 - - - True - 5 - - - True - 5 - <b>Joypad:</b> - True - - - False - False - 0 - - - - - True - liststore3 - - - - - 0 - - - - - False - 1 - - - - - True - - - False - 2 - - - - - _Reset - True - True - True - True - - - - False - False - 3 - - - - - True - - - False - 4 - - - - - True - Swap with: - - - False - 5 - - - - - True - liststore2 - - - - 0 - - - - - False - 6 - - - - - _Swap - True - True - True - True - - - - False - 7 - - - - - False - 0 - - - - - Use modifier keys (CTRL, SHIFT, ALT) directly + True True - False - Allow using modifier keys as independent keys instead of modifiers - True - True + False + False + textbuffer1 - - False - False - 1 - - - - - True - True - - - - True - 10 - 12 - - - True - 6 - 2 - 10 - 5 - - - True - 0 - Up - - - GTK_FILL - - - - - - True - 0 - Down - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - Left - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Right - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - Start - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - Select - - - 5 - 6 - GTK_FILL - - - - - - 50 - True - True - False - - - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - 0 - - - - - True - 6 - 2 - 10 - 5 - - - True - 0 - A - - - GTK_FILL - - - - - - True - 0 - B - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - X - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Y - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - L - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - R - - - 5 - 6 - GTK_FILL - - - - - - 50 - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - GTK_FILL - - - - - 1 - - - - - - - True - Buttons - - - False - - - - - True - 5 - 2 - 2 - 5 - - - True - 5 - 6 - 2 - 10 - 5 - - - True - 0 - A - - - GTK_FILL - - - - - - True - 0 - B - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - X - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Y - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - L - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - R - - - 5 - 6 - GTK_FILL - - - - - - 50 - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - GTK_FILL - - - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - 5 - 6 - 2 - 10 - 5 - - - True - 0 - A - - - GTK_FILL - - - - - - True - 0 - B - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - X - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Y - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - L - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - R - - - 5 - 6 - GTK_FILL - - - - - - 50 - True - True - False - - - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - 1 - 2 - GTK_FILL - - - - - True - 0 - <b>Sticky</b> - True - center - - - 1 - 2 - - - - - - - True - 0 - <b>Turbo</b> - True - center - - - - - - - - - 1 - False - - - - - True - Turbo / Sticky Buttons - - - 1 - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 0 - none - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - 5 - 5 - - - True - Set new axis bindings at: - - - False - False - 0 - - - - - True - True - Changes the amount a joystick should be tilted to register a button press - adjustment4 - 1 - True - - - False - False - 1 - - - - - True - percent - - - False - False - 2 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Joystick Axis Threshold</b> - True - - - - - False - 0 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Center all axes on all joysticks and press Calibrate. - - - False - False - 0 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - Cali_brate - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - False - False - 0 - - - - - - - - False - False - 1 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Calibration</b> - True - - - - - 1 - - - - - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Joystick Options - - - 2 - False - - - - - 2 - - - - - True - <small>Click an entry and then press the desired keys or joystick button -<i>Escape</i>: Move to next<i> Shift-Escape</i>: Clear selected</small> - True - fill - True - - - False - 3 - - - 4 - - - - - True - - - True - input-gaming - - - 0 - - - - - True - Joypads - True - - - False - False - 1 - - - - - 4 - False - - - - - True - 5 - 5 - - - True - 0 - 5 - <b>Snes9x Emulator Shortcut Keys</b> - True - - - False - False - 0 - - - - - True - - - False - False - 1 - - - - - True - True - - - - True - True - never - automatic - - - True - queue - none - - - True - 10 - 11 - 2 - 10 - 5 - - - True - 0 - Soft reset - - - 9 - 10 - GTK_FILL - - - - - - True - 0 - Hardware reset - - - 8 - 9 - GTK_FILL - - - - - - True - 0 - Increase frame time - - - 7 - 8 - GTK_FILL - - - - - - True - 0 - Decrease frame time - - - 6 - 7 - GTK_FILL - - - - - - True - 0 - Increase frame rate - - - 5 - 6 - GTK_FILL - - - - - - True - 0 - Decrease frame rate - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - Pause - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - Toggle turbo - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Enable turbo - - - 1 - 2 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Open ROM - - - GTK_FILL - - - - - - True - 0 - Quit Snes9x - - - 10 - 11 - GTK_FILL - GTK_FILL - - - - - True - True - False - - - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 6 - 7 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 7 - 8 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 8 - 9 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 9 - 10 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 10 - 11 - GTK_FILL - - - - - - - - - - - True - Emulation - - - False - - - - - True - True - never - automatic - - - True - queue - none - - - True - 10 - 8 - 2 - 10 - 5 - - - True - 0 - Toggle BG layer 0 - - - GTK_FILL - - - - - - True - 0 - Toggle BG layer 1 - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - Toggle BG layer 2 - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Toggle BG layer 3 - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - Toggle sprites - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - BG layering hack - - - 5 - 6 - GTK_FILL - - - - - - True - 0 - Screenshot - - - 6 - 7 - GTK_FILL - - - - - - True - 0 - Toggle fullscreen - - - 7 - 8 - GTK_FILL - - - - - - True - True - False - - - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 6 - 7 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 7 - 8 - GTK_FILL - - - - - - - - - 1 - - - - - True - Graphics - - - 1 - False - - - - - True - True - never - automatic - - - True - queue - none - - - True - 10 - 10 - 4 - 10 - 5 - - - True - 0 - <b>Quick save state</b> - True - center - - - 2 - - - - - - - True - 0 - <b>Quick load state</b> - True - - - 2 - 4 - - - - - - - True - 0 - Slot 1 - - - 2 - 3 - - - - - - - True - 0 - Slot 0 - - - 1 - 2 - - - - - - - True - 0 - Slot 2 - - - 3 - 4 - - - - - - - True - 0 - Slot 3 - - - 4 - 5 - - - - - - - True - 0 - Slot 4 - - - 5 - 6 - - - - - - - True - 0 - Slot 5 - - - 6 - 7 - - - - - - - True - 0 - Slot 6 - - - 7 - 8 - - - - - - - True - 0 - Slot 7 - - - 8 - 9 - - - - - - - True - 0 - Slot 0 - - - 2 - 3 - 1 - 2 - - - - - - - True - 0 - Slot 1 - - - 2 - 3 - 2 - 3 - - - - - - - True - 0 - Slot 2 - - - 2 - 3 - 3 - 4 - - - - - - - True - 0 - Slot 3 - - - 2 - 3 - 4 - 5 - - - - - - - True - 0 - Slot 4 - - - 2 - 3 - 5 - 6 - - - - - - - True - 0 - Slot 5 - - - 2 - 3 - 6 - 7 - - - - - - - True - 0 - Slot 6 - - - 2 - 3 - 7 - 8 - - - - - - - True - 0 - Slot 7 - - - 2 - 3 - 8 - 9 - - - - - - - True - 0 - Slot 8 - - - 2 - 3 - 9 - 10 - - - - - - - True - 0 - Slot 8 - - - 9 - 10 - - - - - - - 50 - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 6 - 7 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 7 - 8 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 8 - 9 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 9 - 10 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 3 - 4 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 2 - 3 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 4 - 5 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 5 - 6 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 9 - 10 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 7 - 8 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 6 - 7 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 8 - 9 - GTK_FILL - - - - - - - - - 2 - - - - - True - Save States - - - 2 - False - - - - - True - True - never - automatic - - - True - queue - none - - - True - 10 - 9 - 2 - 10 - 5 - - - True - 0 - Toggle sound channel 0 - - - GTK_FILL - - - - - - True - 0 - Toggle sound channel 1 - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - Toggle sound channel 2 - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Toggle sound channel 3 - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - Toggle sound channel 4 - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - Toggle sound channel 5 - - - 5 - 6 - GTK_FILL - - - - - - True - 0 - Toggle sound channel 6 - - - 6 - 7 - GTK_FILL - - - - - - True - 0 - Toggle sound channel 7 - - - 7 - 8 - GTK_FILL - - - - - - True - 0 - Toggle all sound channels - - - 8 - 9 - GTK_FILL - - - - - - True - True - False - - - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 6 - 7 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 7 - 8 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 8 - 9 - GTK_FILL - - - - - - - - - 3 - - - - - True - Sound - - - 3 - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - 6 - 2 - 10 - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Seek to frame - - - 4 - 5 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Load Movie - - - 3 - 4 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Stop movie recording - - - 2 - 3 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Begin movie recording - - - 1 - 2 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Save SPC - - - GTK_FILL - - - - - - True - True - False - - - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - True - 0 - Swap controllers 1 & 2 - - - 5 - 6 - GTK_FILL - - - - - - True - True - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - 4 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Misc - - - 4 - False - - - - - 2 - - - - - True - <small>Click an entry and then press the desired keys or joystick button -<i>Escape</i>: Move to next<i> Shift-Escape</i>: Clear selected</small> - True - fill - True - - - False - False - 3 - - - - - 5 - - - - - True - - - True - input-keyboard - - - 0 - - - - - True - Shortcuts - True - - - False - False - 1 - - - - - 5 - False - + + True + True + 2 + - 2 + True + True + 0 - + True + False end - - gtk-cancel + + gtk-close True True - True - False + True + False True @@ -5825,70 +111,132 @@ 0 - - - gtk-apply - True - True - True - False - True - - - - False - False - 1 - - - - - gtk-ok - True - True - True - False - True - - - False - False - 2 - - - - - gtk-about - True - True - True - True - - - - False - False - 3 - True - - False + True end - 0 + 1 - cancel_button - ok_button - button1 - button8 + button15 + + 1 + 60 + 1 + 1 + 1 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 1.0408340855860843e-17 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + 2 + 8 + 2 + 1 + 1 + + + 1 + 9999 + 6096 + 1 + 1 + + + 1 + 9999 + 6096 + 1 + 1 + + + 1 + 100 + 50 + 1 + 10 + + + 31500 + 32500 + 31990 + 1 + 10 + + + 2 + 256 + 2 + 1 + 1 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 5 Advance to Frame @@ -5898,67 +246,13 @@ True + False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 10 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - The current frame in the movie is - True - - - 0 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Fast-forward to frame - - - 0 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - 1 - - - - - 1 - - - - - False - 1 - - True + False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK end @@ -5968,6 +262,7 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False True @@ -5985,6 +280,7 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False True @@ -5996,10 +292,84 @@ False + True end 0 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 10 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + The current frame in the movie is + True + + + True + True + 0 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Fast-forward to frame + + + True + True + 0 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + False + False + True + True + + + True + True + 1 + + + + + True + True + 1 + + + + + False + True + 1 + + @@ -6007,6 +377,114 @@ button2 + + True + False + gtk-media-next + 1 + + + True + False + gtk-revert-to-saved + 1 + + + True + False + gtk-redo + 1 + + + True + False + gtk-refresh + 1 + + + True + False + gtk-leave-fullscreen + 1 + + + True + False + gtk-fullscreen + 1 + + + True + False + gtk-preferences + 1 + + + True + False + gtk-zoom-in + 1 + + + True + False + gtk-quit + 1 + + + True + False + gtk-media-record + 1 + + + True + False + gtk-open + 1 + + + True + False + gtk-network + 1 + + + True + False + gtk-save + 1 + + + True + False + gtk-dialog-info + 1 + + + True + False + gtk-go-forward + 1 + + + True + False + gtk-media-pause + 1 + + + True + False + gtk-open + 1 + + + True + False + gtk-media-stop + 1 + @@ -6024,6 +502,104 @@ + + + + + + + + 12.5% + + + 25% + + + 50% + + + 100% + + + + + + + + + + + 0% + + + 12.5% + + + 25% + + + 50% + + + 100% + + + + + + + + + + + None + + + SuperEagle + + + 2xSaI + + + Super2xSaI + + + EPX + + + EPX Smooth + + + Blargg's NTSC + + + Scanlines + + + Simple2x + + + Simple3x + + + Simple4x + + + + + + + + + + + 8:7 Square pixels + + + 4:3 SNES correct aspect + + + @@ -6219,103 +795,202 @@ - - - - - - - - 12.5% - - - 25% - - - 50% - - - 100% - - - - - - - - - - - 0% - - - 12.5% - - - 25% - - - 50% - - - 100% - - - - - - - - - - - None - - - SuperEagle - - - 2xSaI - - - Super2xSaI - - - EPX - - - EPX Smooth - - - Blargg's NTSC - - - Scanlines - - - Simple2x - - - Simple3x - - - Simple4x - - - - - - - - - - - 8:7 Square pixels - - - 4:3 SNES correct aspect - - + + 512 + 350 + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Snes9x Cheats + center-on-parent + dialog + True + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + end + + + gtk-close + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + + + False + False + 0 + + + + + False + True + end + 0 + + + + + True + False + 5 + + + True + False + 0 + in + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + + + + True + True + 0 + + + + + True + False + 5 + 5 + + + True + False + 0 + Code: + + + False + True + 0 + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + False + False + True + True + + + False + True + 1 + + + + + True + False + 0 + Description: + + + False + True + 2 + + + + + True + True + 21 + True + False + False + True + True + + + False + True + 3 + + + + + gtk-add + True + True + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + + + + False + False + 4 + + + + + gtk-remove + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + + + + False + False + 5 + + + + + False + False + 1 + + + + + True + True + 1 + + + + + + button7 + @@ -6340,153 +1015,977 @@ - - 512 - 350 - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - Snes9x Cheats - center-on-parent - dialog - True - - + + False + GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_SUBSTRUCTURE_MASK + Snes9x + + + + + + + + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 + False - + True - 5 + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - + True - 0 - in - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + False + _File + True + + + False + + + _Open ROM Image... + True + False + False + True + image2 + False + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + Open Recent + True + + + + + True + False + + + + + Open with _NetPlay... + True + False + Open a ROM to use with NetPlay + False + True + image3 + False + + + + + + True + False + False + Open _MultiCart... + True + + + + + + True + False + + + + + True + False + False + _Load State + True + + + + False + + + True + False + False + Slot _0 + True + + + + + + True + False + False + Slot _1 + True + + + + + + True + False + False + Slot _2 + True + + + + + + True + False + False + Slot _3 + True + + + + + + True + False + False + Slot _4 + True + + + + + + True + False + False + Slot _5 + True + + + + + + True + False + False + Slot _6 + True + + + + + + True + False + False + Slot _7 + True + + + + + + True + False + False + Slot _8 + True + + + + + + True + False + + + + + True + False + False + From _File... + True + + + + + + + + + + True + False + False + _Save State + True + + + + False + + + True + False + False + Slot _0 + True + + + + + + True + False + False + Slot _1 + True + + + + + + True + False + False + Slot _2 + True + + + + + + True + False + False + Slot _3 + True + + + + + + True + False + False + Slot _4 + True + + + + + + True + False + False + Slot _5 + True + + + + + + True + False + False + Slot _6 + True + + + + + + True + False + False + Slot _7 + True + + + + + + True + False + False + Slot _8 + True + + + + + + True + False + + + + + True + False + False + To _File... + True + + + + + + + + + + True + False + + + + + Save SPC... + True + False + False + True + image4 + False + + + + + + True + False + + + + + Show ROM _Info... + True + False + False + True + image5 + False + + + + + + True + False + + + + + _Quit + True + False + False + True + image18 + False + + + - - - - - 0 - - + True - 5 - 5 - - - True - 0 - Code: + False + False + _Emulation + True + + + False + + + Run / _Continue + True + False + False + True + image6 + False + + + + + + _Pause + True + False + False + True + image7 + False + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + Load _Movie... + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + image8 + False + + + + + + R_ecord Movie... + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + image19 + False + + + + + + _Stop Recording + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + image9 + False + + + + + + _Jump to Frame... + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + image10 + False + + + + + + True + False + + + + + Sy_nc Clients + True + False + False + True + image11 + False + + + + + + True + False + + + + + Reset + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + image12 + False + + + + + + Soft _Reset + True + False + False + True + image13 + False + + + + + + + + + + True + False + False + _View + True + + + + False + + + _Hide Menu + True + False + False + True + image14 + False + + + + + + True + False + False + _Status Bar + True + + + + + + True + False + + + + + _Change Size + True + False + False + True + image17 + False + + + True + False + + + True + False + False + False + Exact Pixels + True + + + + + True + False + False + _1x + True + + + + + + True + False + False + _2x + True + + + + + + True + False + False + _3x + True + + + + + + True + False + False + _4x + True + + + + + + True + False + False + _5x + True + + + + + + True + False + + + + + True + False + False + False + Correct Aspect + True + + + + + True + False + False + 1x + True + + + + + + True + False + False + 2x + True + + + + + + True + False + False + 3x + True + + + + + + True + False + False + 4x + True + + + + + + True + False + False + 5x + True + + + + + + + + + + True + False + + + + + _Fullscreen + True + False + False + True + image15 + False + + + + + + + + + + True + False + False + _Options + True + + + False + + + True + False + False + Controller Ports + True + + + False + + + True + False + False + SNES Port 1 + True + + + + False + + + True + False + False + Joypad + True + + + + + + True + False + False + Mouse + True + joypad1 + + + + + + True + False + False + Superscope + True + True + joypad1 + + + + + + + + + + True + False + False + SNES Port 2 + True + + + + False + + + True + False + False + Joypad + True + + + + + + True + False + False + Mouse + True + joypad2 + + + + + + True + False + False + Multitap + True + joypad2 + + + + + + True + False + False + Superscope + True + True + joypad2 + + + + + + + + + + + + + + True + False + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + _Cheats... + True + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + _Preferences... + True + False + False + True + image16 + False + + + - - False - 0 - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - False - 1 - - - - - True - 0 - Description: - - - False - 2 - - - - - True - True - 21 - True - - - False - 3 - - - - - gtk-add - True - True - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - False - False - 4 - - - - - gtk-remove - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - False - False - 5 - - - False - False - 1 - + False + True + 0 + + + + + 256 + 224 + True + True + False + GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK | GDK_SUBSTRUCTURE_MASK + + + + + + + + True + True 1 - - + + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + + + False + True + 2 + + + + + + + False + 5 + Open Multiple ROM Images (MultiCart) + center-on-parent + 320 + dialog + + + True + False + + + True + False end - - gtk-close + + gtk-cancel True True True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False True @@ -6495,20 +1994,122 @@ 0 + + + gtk-ok + True + True + True + False + True + + + False + False + 1 + + False + True end 0 + + + True + False + 5 + + + True + False + 12 + + + True + False + Slot A: + + + False + True + 0 + + + + + True + False + Select an Image for Slot A + + + True + True + 1 + + + + + False + True + 0 + + + + + True + False + 12 + + + True + False + Slot B: + + + False + True + 0 + + + + + True + False + Select an Image for Slot B + + + True + True + 1 + + + + + False + True + 1 + + + + + True + True + 1 + + - button7 + button14 + button13 + False 5 Snes9x NetPlay center-on-parent @@ -6516,344 +2117,12 @@ True + False 2 - - - True - 5 - 5 - - - True - 0 - none - - - True - 12 - - - True - 5 - 5 - - - True - True - The game chosen will be loaded before connecting. This field can be blank if the server will send the ROM image - False - - - 0 - - - - - Browse... - True - True - True - - - - False - 1 - - - - - True - True - True - - - - True - Clear entry - gtk-clear - 1 - - - - - False - 2 - - - - - - - - - True - <b>ROM Image</b> - True - - - - - False - 0 - - - - - True - 0 - none - - - True - 5 - 12 - - - True - - - Connect to another computer - True - True - False - Connect to another computer that is running Snes9x NetPlay as a server - True - True - - - 0 - - - - - True - 5 - 5 - - - True - Name or IP address: - - - False - 0 - - - - - True - True - Domain name or internet protocol address of a remote computer - - - 1 - - - - - True - Port: - - - False - 2 - - - - - True - True - Connect to specified TCP port on remote computer - adjustment3 - True - True - - - False - 3 - - - - - 1 - - - - - Act as a server - True - True - False - Host a game on this computer as Player 1, requiring extra throughput to support multitple users - True - True - connect_radio - - - - 2 - - - - - - - - - True - <b>Server</b> - True - - - - - False - 1 - - - - - True - 0 - none - - - True - 12 - - - True - 5 - 5 - - - Sync using reset - True - True - False - Reset the game when players join instead of transferring potentially unreliable freeze states - True - - - False - 0 - - - - - Send ROM image to clients - True - True - False - Send the running game image to players instead of requiring them to have their own copies - True - - - False - 1 - - - - - True - 5 - - - True - Default port: - - - False - 0 - - - - - True - True - TCP port used as a connection point for remote clients - adjustment2 - True - True - - - False - 1 - - - - - False - 2 - - - - - True - 5 - - - True - Ask server to pause when - - - False - 0 - - - - - True - True - adjustment1 - True - True - - - False - 1 - - - - - True - frames behind - - - False - 2 - - - - - False - 3 - - - - - - - - - True - <b>Settings</b> - True - - - - - 2 - - - - - 1 - - True + False end @@ -6861,6 +2130,7 @@ True True True + False True @@ -6876,6 +2146,7 @@ True True True + False True @@ -6887,10 +2158,423 @@ False + True end 0 + + + True + False + 5 + 5 + + + True + False + 0 + none + + + True + False + 12 + + + True + False + 5 + 5 + + + True + True + The game chosen will be loaded before connecting. This field can be blank if the server will send the ROM image + False + False + False + True + True + + + True + True + 0 + + + + + Browse... + True + True + True + False + + + + False + True + 1 + + + + + True + True + True + False + + + + True + False + Clear entry + gtk-clear + 1 + + + + + False + True + 2 + + + + + + + + + True + False + <b>ROM Image</b> + True + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 5 + 12 + + + True + False + + + Connect to another computer + True + True + False + Connect to another computer that is running Snes9x NetPlay as a server + False + True + True + + + True + True + 0 + + + + + True + False + 5 + 5 + + + True + False + Name or IP address: + + + False + True + 0 + + + + + True + True + Domain name or internet protocol address of a remote computer + False + False + True + True + + + True + True + 1 + + + + + True + False + Port: + + + False + True + 2 + + + + + True + True + Connect to specified TCP port on remote computer + False + False + True + True + adjustment3 + True + True + + + False + True + 3 + + + + + True + True + 1 + + + + + Act as a server + True + True + False + Host a game on this computer as Player 1, requiring extra throughput to support multitple users + False + True + True + connect_radio + + + + True + True + 2 + + + + + + + + + True + False + <b>Server</b> + True + + + + + False + True + 1 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + 5 + 5 + + + Sync using reset + True + True + False + Reset the game when players join instead of transferring potentially unreliable freeze states + False + True + + + False + True + 0 + + + + + Send ROM image to clients + True + True + False + Send the running game image to players instead of requiring them to have their own copies + False + True + + + False + True + 1 + + + + + True + False + 5 + + + True + False + Default port: + + + False + True + 0 + + + + + True + True + TCP port used as a connection point for remote clients + False + False + True + True + adjustment2 + True + True + + + False + True + 1 + + + + + False + True + 2 + + + + + True + False + 5 + + + True + False + Ask server to pause when + + + False + True + 0 + + + + + True + True + False + False + True + True + adjustment1 + True + True + + + False + True + 1 + + + + + True + False + frames behind + + + False + True + 2 + + + + + False + True + 3 + + + + + + + + + True + False + <b>Settings</b> + True + + + + + True + True + 2 + + + + + True + True + 1 + + @@ -6898,92 +2582,33 @@ button10 - - 5 - Open Multiple ROM Images (MultiCart) - center-on-parent - 320 + + False + GDK_KEY_PRESS_MASK + Snes9x Preferences + center + 480 dialog + True + + - + True - - - True - 5 - - - True - 12 - - - True - Slot A: - - - False - 0 - - - - - True - Select an Image for Slot A - - - 1 - - - - - False - 0 - - - - - True - 12 - - - True - Slot B: - - - False - 0 - - - - - True - Select an Image for Slot B - - - 1 - - - - - False - 1 - - - - - 1 - - + False - + True + False end - + gtk-cancel True True - True + True + False + False True @@ -6993,12 +2618,15 @@ - - gtk-ok + + gtk-apply True True - True + True + False + False True + False @@ -7006,220 +2634,5841 @@ 1 + + + gtk-ok + True + True + True + False + False + True + + + False + False + 2 + + + + + gtk-about + True + True + True + False + True + + + + False + False + 3 + True + + False + True end 0 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + True + left + 0 + 1 + 0 + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + never + automatic + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + queue + none + + + True + False + 5 + + + True + False + 0 + none + + + True + False + 5 + 5 + 12 + + + True + False + 5 + + + Use fullscreen on ROM open + True + True + False + Go to fullscreen mode immediately after opening a ROM + False + True + True + + + False + False + 0 + + + + + Show frame rate + True + True + False + False + True + True + + + False + False + 1 + + + + + Use overscanned height + True + True + False + Use SNES extended height. Will probably cause letterboxing + False + True + True + + + False + False + 2 + + + + + True + False + 12 + + + Change fullscreen resolution: + True + True + False + Changes the screen resolution when running Snes9x in fullscreen mode + False + True + True + + + False + False + 0 + + + + + True + False + liststore14 + + + + 0 + + + + + True + True + 1 + + + + + False + False + 3 + + + + + + + + + True + False + <b>Basic Settings</b> + True + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 5 + 5 + 12 + + + True + False + 5 + + + Scale image to fit window + True + True + False + Scales the image so no black bars are present + False + True + True + + + False + False + 0 + + + + + True + False + 12 + + + Maintain aspect-ratio: + True + True + False + Scales the image as large as possible without distortion + False + True + True + + + False + False + 0 + + + + + True + False + liststore13 + + + + 0 + + + + + False + True + 1 + + + + + True + True + 1 + + + + + True + False + 5 + + + Use + True + True + False + Allows scaling and filtering to use multiple processors + False + True + True + + + False + False + 0 + + + + + True + True + False + False + True + True + adjustment17 + True + True + + + False + True + 1 + + + + + True + False + threads for filtering and scaling + + + False + True + 2 + + + + + True + True + 2 + + + + + True + False + 12 + + + True + False + High-resolution effect: + + + False + True + 0 + + + + + True + False + liststore15 + + + + 0 + + + + + False + True + 1 + + + + + True + True + 3 + + + + + True + False + 12 + + + True + False + 0 + Apply scaling filter: + + + False + True + 0 + + + + + True + False + liststore12 + + + + + 0 + + + + + False + True + 1 + + + + + False + False + 4 + + + + + + + + + True + False + <b>Image Adjustments</b> + True + + + + + False + True + 1 + + + + + True + False + 0 + none + + + True + False + 5 + 5 + 12 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 12 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Video preset: + + + False + True + 0 + + + + + True + False + + + Composite + True + True + True + False + + + + False + True + 0 + + + + + S-Video + True + True + True + False + + + + False + True + 1 + + + + + RGB + True + True + True + False + + + + False + True + 2 + + + + + Monochrome + True + True + True + False + + + + False + True + 3 + + + + + False + True + 1 + + + + + True + True + 0 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 11 + 2 + 12 + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Artifacts: + + + 6 + 7 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Sharpness: + + + 4 + 5 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Brightness: + + + 3 + 4 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Contrast: + + + 2 + 3 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Saturation: + + + 1 + 2 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Hue: + + + GTK_FILL + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment16 + False + -1 + 2 + left + + + 1 + 2 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment15 + False + -1 + 2 + left + + + 1 + 2 + 1 + 2 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment14 + False + -1 + 2 + left + + + 1 + 2 + 2 + 3 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment13 + False + -1 + 2 + left + + + 1 + 2 + 3 + 4 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment12 + False + -1 + 2 + left + + + 1 + 2 + 4 + 5 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment11 + False + -1 + 2 + left + + + 1 + 2 + 6 + 7 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment10 + False + -1 + 2 + left + + + 1 + 2 + 7 + 8 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment9 + False + -1 + 2 + left + + + 1 + 2 + 8 + 9 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment8 + False + -1 + 2 + left + + + 1 + 2 + 9 + 10 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment7 + False + -1 + 2 + left + + + 1 + 2 + 10 + 11 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Gamma: + + + 7 + 8 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Fringing: + + + 8 + 9 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Bleed: + + + 9 + 10 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Resolution: + + + 10 + 11 + GTK_FILL + + + + + True + False + + + 2 + 5 + 6 + + + + + True + True + 1 + + + + + Merge odd and even fields + True + True + False + False + True + + + True + True + 2 + + + + + True + False + 12 + + + True + False + 0 + Scanline intensity: + + + False + True + 0 + + + + + True + False + liststore11 + + + + 0 + + + + + False + True + 1 + + + + + True + True + 3 + + + + + + + + + True + False + <b>NTSC Filter</b> + True + + + + + False + True + 2 + + + + + True + False + 0 + none + + + True + False + 5 + 5 + 12 + + + True + False + 12 + + + True + False + 0 + Scanline intensity: + + + False + True + 0 + + + + + True + False + liststore10 + + + + 0 + + + + + False + True + 1 + + + + + + + + + True + False + <b>Scanline Filter</b> + True + + + + + False + True + 3 + + + + + True + False + 0 + none + + + True + False + 5 + 5 + 12 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + liststore9 + + + + + 0 + + + + + True + True + 0 + + + + + Bilinear-filter output + True + True + False + False + True + True + + + True + True + 1 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + Sync to vertical blank + True + True + False + Sync the image to the vertical retrace to stop tearing + False + True + True + + + False + False + 0 + + + + + Reduce input lag + True + True + False + Sync the program with the video output after every displayed frame to reduce input latency + False + True + + + True + True + 1 + + + + + Allow non-power-of-two textures + True + True + False + Prevents edge artifacts, but can slow performance + False + True + + + True + True + 2 + + + + + Use pixel-buffer objects + True + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Can be faster or slower depending on drivers + False + True + + + True + True + 3 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Different formats can yield highly different performance + 10 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Pixel-buffer format: + + + False + True + 0 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + liststore8 + + + + 0 + + + + + False + True + 1 + + + + + + + True + True + 4 + + + + + True + False + 5 + + + Use GLSL shader: + True + True + False + False + 0 + True + + + False + True + 0 + + + + + True + True + • + True + False + False + True + True + + + True + True + 1 + + + + + Browse... + True + True + True + False + + + + False + True + 2 + + + + + True + True + 5 + + + + + True + True + 2 + + + + + True + False + + + Force an inverted byte-ordering + True + True + False + Forces a swapped byte-ordering for cases where the system's endian is used instead of the video card + False + True + + + True + True + 0 + + + + + True + True + 3 + + + + + + + + + True + False + <b>Hardware Acceleration</b> + True + + + + + False + True + 4 + + + + + + + + + + + True + False + + + True + False + video-display + + + True + True + 0 + + + + + True + False + Display + True + + + False + False + 1 + + + + + False + + + + + True + True + never + automatic + + + True + False + queue + none + + + True + False + 5 + 0 + none + + + True + False + 12 + + + True + False + 5 + 5 + + + True + False + 12 + + + True + False + Sound driver: + + + False + False + 0 + + + + + True + False + liststore7 + + + + 0 + + + + + False + False + 1 + + + + + False + False + 0 + + + + + Synchronize with sound + True + True + False + Base emulation speed on the rate sound is output + False + True + + + False + False + 1 + + + + + Mute sound output + True + True + False + Disables output of sound + False + True + True + + + False + False + 2 + + + + + Stereo + True + True + False + Output two channels, left and right + False + True + True + + + False + False + 3 + + + + + True + False + 4 + 2 + 10 + 5 + + + True + False + 0 + Playback rate: + + + GTK_FILL + + + + + + True + False + 5 + + + True + True + False + False + True + True + adjustment6 + True + True + + + False + True + 0 + + + + + True + False + milliseconds + + + False + True + 1 + + + + + 1 + 2 + 3 + 4 + GTK_FILL + GTK_FILL + + + + + True + False + 0 + Buffer size: + + + 3 + 4 + GTK_FILL + GTK_FILL + + + + + True + False + 0 + Input rate: + + + 1 + 2 + GTK_FILL + + + + + True + True + Adjust to produce more or less data. Decrease the rate if experiencing crackling. Increase the rate if experiencing frame-rate stuttering. Best used with the "Synchronize with sound" option + adjustment5 + False + 0 + left + + + 1 + 2 + 1 + 2 + + + + + True + False + + + True + False + liststore6 + + + + 0 + + + + + False + False + 0 + + + + + 1 + 2 + GTK_FILL + + + + + True + False + 0 + Video rate: + + + 2 + 3 + GTK_FILL + + + + + True + False + label + + + 1 + 2 + 2 + 3 + + + + + False + True + 4 + + + + + + + + + True + False + <b>Sound Settings</b> + True + + + + + + + + + 1 + + + + + True + False + + + True + False + audio-x-generic + + + True + True + 0 + + + + + True + False + Sound + True + + + False + False + 1 + + + + + 1 + False + + + + + True + True + automatic + automatic + + + True + False + queue + none + + + True + False + + + True + False + 5 + 0 + none + + + True + False + 12 + + + True + False + 5 + 5 + + + True + False + 10 + + + True + False + Frameskip: + + + False + False + 0 + + + + + True + False + liststore5 + + + + 0 + + + + + False + False + 1 + + + + + False + True + 0 + + + + + Block invalid VRAM access + True + True + False + False + True + + + True + True + 1 + + + + + Allow opposing dpad directions + True + True + False + Let left and right or up and down be pressed at the same time + False + True + + + True + True + 2 + + + + + + + + + True + False + <b>Accuracy</b> + True + + + + + False + True + 0 + + + + + True + False + 5 + 0 + none + + + True + False + 12 + + + True + False + 5 + 5 + + + Pause emulation when switching away from Snes9x + True + True + False + False + True + + + True + True + 0 + + + + + True + False + 12 + + + True + False + The ESC key should: + + + False + True + 0 + + + + + True + False + liststore4 + + + + 0 + + + + + False + True + 1 + + + + + True + True + 1 + + + + + + + + + True + False + <b>Window Switching</b> + True + + + + + False + True + 1 + + + + + True + False + 5 + 0 + none + + + True + False + 12 + + + True + False + 5 + + + Prevent the screensaver from activating + True + True + False + False + True + + + True + True + 0 + + + + + + + + + True + False + <b>Screensaver</b> + True + + + + + False + True + 2 + + + + + + + + + 2 + + + + + True + False + + + True + False + utilities-terminal + + + True + True + 0 + + + + + True + False + Emulation + True + + + False + False + 1 + + + + + 2 + False + + + + + True + False + 5 + + + True + False + 5 + 0 + none + + + True + False + 12 + + + True + False + 5 + + + True + False + 5 + 3 + 5 + 5 + + + True + True + False + • + gtk-clear + False + False + True + True + + + + + 1 + 2 + + + + + True + True + False + • + gtk-clear + False + False + True + True + + + + + 1 + 2 + 1 + 2 + + + + + True + True + False + • + gtk-clear + False + False + True + True + + + + + 1 + 2 + 2 + 3 + + + + + True + True + False + • + gtk-clear + False + False + True + True + + + + + 1 + 2 + 3 + 4 + + + + + True + True + False + • + gtk-clear + False + False + True + True + + + + + 1 + 2 + 4 + 5 + + + + + Browse... + True + True + True + False + + + + 2 + 3 + GTK_FILL + + + + + + Browse... + True + True + True + False + + + + 2 + 3 + 1 + 2 + GTK_FILL + + + + + + Browse... + True + True + True + False + + + + 2 + 3 + 2 + 3 + GTK_FILL + + + + + + Browse... + True + True + True + False + + + + 2 + 3 + 3 + 4 + GTK_FILL + + + + + + Browse... + True + True + True + False + + + + 2 + 3 + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + SRAM: + + + GTK_FILL + + + + + True + False + 0 + Save states: + + + 1 + 2 + GTK_FILL + + + + + True + False + 0 + Cheats: + + + 2 + 3 + GTK_FILL + + + + + True + False + 0 + Patches: + + + 3 + 4 + GTK_FILL + + + + + True + False + 0 + Exports: + + + 4 + 5 + GTK_FILL + + + + + False + True + 0 + + + + + + + + + True + False + <b>Game Data Locations</b> + True + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 5 + 12 + + + True + False + 5 + + + True + False + Save SRAM: + + + False + True + 0 + + + + + True + True + Automatically save the game's SRAM at this interval. Setting this to 0 will only save when quitting or changing ROMs + • + 5 + 1 + False + False + True + True + + + False + True + 1 + + + + + True + False + seconds after change + + + False + True + 2 + + + + + + + + + True + False + <b>Automatic Saving</b> + True + + + + + False + True + 1 + + + + + 3 + + + + + True + False + + + True + False + folder + + + True + True + 0 + + + + + True + False + Files + True + + + False + False + 1 + + + + + 3 + False + + + + + True + False + 5 + 5 + + + True + False + 5 + + + True + False + 5 + <b>Joypad:</b> + True + + + False + False + 0 + + + + + True + False + liststore3 + + + + + 0 + + + + + False + True + 1 + + + + + True + False + + + False + True + 2 + + + + + _Reset + True + True + True + False + True + + + + False + False + 3 + + + + + True + False + + + False + True + 4 + + + + + True + False + Swap with: + + + False + True + 5 + + + + + True + False + liststore2 + + + + 0 + + + + + False + True + 6 + + + + + _Swap + True + True + True + False + True + + + + False + True + 7 + + + + + False + True + 0 + + + + + Use modifier keys (CTRL, SHIFT, ALT) directly + True + True + False + Allow using modifier keys as independent keys instead of modifiers + False + True + True + + + False + False + 1 + + + + + True + True + + + + True + False + 10 + 12 + + + True + False + 6 + 2 + 10 + 5 + + + True + False + 0 + Up + + + GTK_FILL + + + + + + True + False + 0 + Down + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + Left + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Right + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + Start + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + Select + + + 5 + 6 + GTK_FILL + + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + True + True + 0 + + + + + True + False + 6 + 2 + 10 + 5 + + + True + False + 0 + A + + + GTK_FILL + + + + + + True + False + 0 + B + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + X + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Y + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + L + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + R + + + 5 + 6 + GTK_FILL + + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + True + True + 1 + + + + + + + True + False + Buttons + + + False + + + + + True + False + 5 + 2 + 2 + 5 + + + True + False + 5 + 6 + 2 + 10 + 5 + + + True + False + 0 + A + + + GTK_FILL + + + + + + True + False + 0 + B + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + X + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Y + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + L + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + R + + + 5 + 6 + GTK_FILL + + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + False + 5 + 6 + 2 + 10 + 5 + + + True + False + 0 + A + + + GTK_FILL + + + + + + True + False + 0 + B + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + X + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Y + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + L + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + R + + + 5 + 6 + GTK_FILL + + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 1 + 2 + GTK_FILL + + + + + True + False + 0 + <b>Sticky</b> + True + center + + + 1 + 2 + + + + + + + True + False + 0 + <b>Turbo</b> + True + center + + + + + + + + + 1 + False + + + + + True + False + Turbo / Sticky Buttons + + + 1 + False + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 0 + none + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 12 + + + True + False + 5 + 5 + + + True + False + Set new axis bindings at: + + + False + False + 0 + + + + + True + True + Changes the amount a joystick should be tilted to register a button press + False + False + True + True + adjustment4 + 1 + True + + + False + False + 1 + + + + + True + False + percent + + + False + False + 2 + + + + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Joystick Axis Threshold</b> + True + + + + + False + True + 0 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + none + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 12 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Center all axes on all joysticks and press Calibrate. + + + False + False + 0 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + Cali_brate + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + + + + False + False + 0 + + + + + + + + False + False + 1 + + + + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Calibration</b> + True + + + + + True + True + 1 + + + + + 2 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Joystick Options + + + 2 + False + + + + + True + True + 2 + + + + + True + False + <small>Click an entry and then press the desired keys or joystick button +<i>Escape</i>: Move to next<i> Shift-Escape</i>: Clear selected</small> + True + fill + True + + + False + True + 3 + + + + + 4 + + + + + True + False + + + True + False + input-gaming + + + True + True + 0 + + + + + True + False + Joypads + True + + + False + False + 1 + + + + + 4 + False + + + + + True + False + 5 + 5 + + + True + False + 0 + 5 + <b>Snes9x Emulator Shortcut Keys</b> + True + + + False + False + 0 + + + + + True + False + + + False + False + 1 + + + + + True + True + + + + True + True + never + automatic + + + True + False + queue + none + + + True + False + 10 + 11 + 2 + 10 + 5 + + + True + False + 0 + Soft reset + + + 9 + 10 + GTK_FILL + + + + + + True + False + 0 + Hardware reset + + + 8 + 9 + GTK_FILL + + + + + + True + False + 0 + Increase frame time + + + 7 + 8 + GTK_FILL + + + + + + True + False + 0 + Decrease frame time + + + 6 + 7 + GTK_FILL + + + + + + True + False + 0 + Increase frame rate + + + 5 + 6 + GTK_FILL + + + + + + True + False + 0 + Decrease frame rate + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + Pause + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + Toggle turbo + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Enable turbo + + + 1 + 2 + GTK_FILL + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Open ROM + + + GTK_FILL + + + + + + True + False + 0 + Quit Snes9x + + + 10 + 11 + GTK_FILL + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 6 + 7 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 7 + 8 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 8 + 9 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 9 + 10 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 10 + 11 + GTK_FILL + + + + + + + + + + + True + False + Emulation + + + False + + + + + True + True + never + automatic + + + True + False + queue + none + + + True + False + 10 + 8 + 2 + 10 + 5 + + + True + False + 0 + Toggle BG layer 0 + + + GTK_FILL + + + + + + True + False + 0 + Toggle BG layer 1 + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + Toggle BG layer 2 + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Toggle BG layer 3 + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + Toggle sprites + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + BG layering hack + + + 5 + 6 + GTK_FILL + + + + + + True + False + 0 + Screenshot + + + 6 + 7 + GTK_FILL + + + + + + True + False + 0 + Toggle fullscreen + + + 7 + 8 + GTK_FILL + + + + + + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 6 + 7 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 7 + 8 + GTK_FILL + + + + + + + + + 1 + + + + + True + False + Graphics + + + 1 + False + + + + + True + True + never + automatic + + + True + False + queue + none + + + True + False + 10 + 10 + 4 + 10 + 5 + + + True + False + 0 + <b>Quick save state</b> + True + center + + + 2 + + + + + + + True + False + 0 + <b>Quick load state</b> + True + + + 2 + 4 + + + + + + + True + False + 0 + Slot 1 + + + 2 + 3 + + + + + + + True + False + 0 + Slot 0 + + + 1 + 2 + + + + + + + True + False + 0 + Slot 2 + + + 3 + 4 + + + + + + + True + False + 0 + Slot 3 + + + 4 + 5 + + + + + + + True + False + 0 + Slot 4 + + + 5 + 6 + + + + + + + True + False + 0 + Slot 5 + + + 6 + 7 + + + + + + + True + False + 0 + Slot 6 + + + 7 + 8 + + + + + + + True + False + 0 + Slot 7 + + + 8 + 9 + + + + + + + True + False + 0 + Slot 0 + + + 2 + 3 + 1 + 2 + + + + + + + True + False + 0 + Slot 1 + + + 2 + 3 + 2 + 3 + + + + + + + True + False + 0 + Slot 2 + + + 2 + 3 + 3 + 4 + + + + + + + True + False + 0 + Slot 3 + + + 2 + 3 + 4 + 5 + + + + + + + True + False + 0 + Slot 4 + + + 2 + 3 + 5 + 6 + + + + + + + True + False + 0 + Slot 5 + + + 2 + 3 + 6 + 7 + + + + + + + True + False + 0 + Slot 6 + + + 2 + 3 + 7 + 8 + + + + + + + True + False + 0 + Slot 7 + + + 2 + 3 + 8 + 9 + + + + + + + True + False + 0 + Slot 8 + + + 2 + 3 + 9 + 10 + + + + + + + True + False + 0 + Slot 8 + + + 9 + 10 + + + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 6 + 7 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 7 + 8 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 8 + 9 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 9 + 10 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 5 + 6 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 9 + 10 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 7 + 8 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 6 + 7 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 8 + 9 + GTK_FILL + + + + + + + + + 2 + + + + + True + False + Save States + + + 2 + False + + + + + True + True + never + automatic + + + True + False + queue + none + + + True + False + 10 + 9 + 2 + 10 + 5 + + + True + False + 0 + Toggle sound channel 0 + + + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 1 + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 2 + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 3 + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 4 + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 5 + + + 5 + 6 + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 6 + + + 6 + 7 + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 7 + + + 7 + 8 + GTK_FILL + + + + + + True + False + 0 + Toggle all sound channels + + + 8 + 9 + GTK_FILL + + + + + + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 6 + 7 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 7 + 8 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 8 + 9 + GTK_FILL + + + + + + + + + 3 + + + + + True + False + Sound + + + 3 + False + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + 6 + 2 + 10 + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Seek to frame + + + 4 + 5 + GTK_FILL + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Load Movie + + + 3 + 4 + GTK_FILL + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Stop movie recording + + + 2 + 3 + GTK_FILL + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Begin movie recording + + + 1 + 2 + GTK_FILL + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Save SPC + + + GTK_FILL + + + + + + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + True + False + 0 + Swap controllers 1 & 2 + + + 5 + 6 + GTK_FILL + + + + + + True + True + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 4 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Misc + + + 4 + False + + + + + True + True + 2 + + + + + True + False + <small>Click an entry and then press the desired keys or joystick button +<i>Escape</i>: Move to next<i> Shift-Escape</i>: Clear selected</small> + True + fill + True + + + False + False + 3 + + + + + 5 + + + + + True + False + + + True + False + input-keyboard + + + True + True + 0 + + + + + True + False + Shortcuts + True + + + False + False + 1 + + + + + 5 + False + + + + + + + True + True + 2 + + - button14 - button13 + cancel_button + ok_button + button1 + button8 - - True - gtk-open - 1 - - - True - gtk-network - 1 - - - True - gtk-save - 1 - - - True - gtk-dialog-info - 1 - - - True - gtk-quit - 1 - - - True - gtk-go-forward - 1 - - - True - gtk-media-pause - 1 - - - True - gtk-open - 1 - - - True - gtk-media-record - 1 - - - True - gtk-media-stop - 1 - - - True - gtk-media-next - 1 - - - True - gtk-revert-to-saved - 1 - - - True - gtk-redo - 1 - - - True - gtk-refresh - 1 - - - True - gtk-leave-fullscreen - 1 - - - True - gtk-zoom-in - 1 - - - True - gtk-fullscreen - 1 - - - True - gtk-preferences - 1 - - - 1 - 1 - 60 - 1 - 1 - - - 6096 - 1 - 9999 - 1 - 1 - - - 6096 - 1 - 9999 - 1 - 1 - - - 50 - 1 - 100 - 1 - 10 - - - 31990 - 31500 - 32500 - 1 - 10 - - - 2 - 2 - 256 - 1 - 1 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - 1.0408340855860843e-17 - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - 2 - 2 - 8 - 1 - 1 - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. @@ -7396,111 +8645,4 @@ Super NES and Super Nintendo Entertainment System are trademarks of Nintendo Co., Limited and its subsidiary companies. - - 560 - 448 - About Snes9x - normal - True - - - True - 2 - - - True - 5 - - - True - 5 - - - True - gtk-missing-image - - - - - False - 0 - - - - - True - 0 - 10 - 10 - label106 - True - center - True - - - False - 1 - - - - - True - queue - - - True - True - automatic - - - True - True - False - False - textbuffer1 - - - - - - - 2 - - - - - 0 - - - - - True - end - - - gtk-close - True - True - True - True - - - False - False - 0 - - - - - False - end - 1 - - - - - - button15 - - From 1af39f384549a8464b28c052ea3cacf49fdaf757 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Thu, 23 Jun 2011 05:24:13 -0500 Subject: [PATCH 04/33] Clean things up slightly. Switch CYCLE_ACCURATE off, since things seem to work fine without it. --- apu/apu.cpp | 16 ++++------------ apu/bapu/smp/core.cpp | 4 ++-- apu/bapu/smp/smp.cpp | 10 +++++++--- apu/bapu/smp/smp.hpp | 4 ++-- apu/bapu/snes/snes.hpp | 25 +++++++++++++++---------- memmap.cpp | 25 ++++++------------------- snapshot.cpp | 2 +- 7 files changed, 37 insertions(+), 49 deletions(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index 65df1b59..604478d6 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -464,8 +464,7 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms) void S9xSetSoundControl (uint8 voice_switch) { - /* - spc_core->dsp_set_stereo_switch(voice_switch << 8 | voice_switch); */ + SNES::dsp.spc_dsp.set_stereo_switch (voice_switch << 8 | voice_switch); } void S9xSetSoundMute (bool8 mute) @@ -477,7 +476,7 @@ void S9xSetSoundMute (bool8 mute) void S9xDumpSPCSnapshot (void) { -/* No SPC dumping ATM in byuu SMP */ +/* TODO: SPC dumping */ /* spc_core->dsp_dump_spc_snapshot(); */ } @@ -578,14 +577,6 @@ void S9xAPUTimingSetSpeedup (int ticks) UpdatePlaybackRate(); } -void S9xAPUAllowTimeOverflow (bool allow) -{ - if (allow) - printf("APU time overflow allowed\n"); - - /* spc_core->spc_allow_time_overflow(allow); */ -} - void S9xResetAPU (void) { spc::reference_time = 0; @@ -614,6 +605,7 @@ void S9xSoftResetAPU (void) void S9xAPUSaveState (uint8 *block) { +// TODO: Save states /* uint8 *ptr = block; spc_core->copy_state(&ptr, from_apu_to_state); @@ -625,7 +617,7 @@ void S9xAPUSaveState (uint8 *block) void S9xAPULoadState (uint8 *block) { - /*uint8 *ptr = block; +/* uint8 *ptr = block; S9xResetAPU(); diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp index eb03b46e..01f265a5 100755 --- a/apu/bapu/smp/core.cpp +++ b/apu/bapu/smp/core.cpp @@ -3,7 +3,7 @@ void SMP::tick() { timer1.tick(); timer2.tick(); -#ifdef BSNES +#ifndef SNES9X clock += cycle_step_cpu; #else clock++; @@ -75,7 +75,7 @@ void SMP::op_step() { timer1.tick(cycle_count_table[opcode]); timer2.tick(cycle_count_table[opcode]); -#ifdef BSNES +#ifndef SNES9X clock += cycle_table_cpu[opcode]; #else clock += cycle_count_table[opcode]; diff --git a/apu/bapu/smp/smp.cpp b/apu/bapu/smp/smp.cpp index 7a1b2e25..49556f3f 100755 --- a/apu/bapu/smp/smp.cpp +++ b/apu/bapu/smp/smp.cpp @@ -1,4 +1,8 @@ +#ifndef SNES9X #define CYCLE_ACCURATE +#else +#undef CYCLE_ACCURATE +#endif #include @@ -20,7 +24,7 @@ namespace SNES { #include "timing.cpp" void SMP::synchronize_cpu() { -#ifdef BSNES +#ifndef SNES9X if(CPU::Threaded == true) { //if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); } else { @@ -42,7 +46,7 @@ void SMP::enter() { } void SMP::power() { -#ifdef BSNES +#ifndef SNES9X Processor::frequency = system.apu_frequency(); #endif @@ -92,7 +96,7 @@ void SMP::reset() { timer0.stage3_ticks = timer1.stage3_ticks = timer2.stage3_ticks = 0; } -#ifdef BSNES +#ifndef SNES9X void SMP::serialize(serializer &s) { Processor::serialize(s); diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp index be52f77a..5d2c3d64 100755 --- a/apu/bapu/smp/smp.hpp +++ b/apu/bapu/smp/smp.hpp @@ -17,7 +17,7 @@ public: void power(); void reset(); -#ifdef BSNES +#ifndef SNES9X void serialize(serializer&); #endif SMP(); @@ -35,7 +35,7 @@ public: alwaysinline unsigned operator=(unsigned data) { n = data & 0x80; v = data & 0x40; p = data & 0x20; b = data & 0x10; h = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01; - return *this; + return data; } alwaysinline unsigned operator|=(unsigned data) { return operator=(operator unsigned() | data); } diff --git a/apu/bapu/snes/snes.hpp b/apu/bapu/snes/snes.hpp index 30845973..be7e73f1 100755 --- a/apu/bapu/snes/snes.hpp +++ b/apu/bapu/snes/snes.hpp @@ -1,11 +1,21 @@ #ifndef __SNES_HPP #define __SNES_HPP -#define CYCLE_ACCURATE - #include "snes9x.h" -#define alwaysinline inline +#define SNES9X + +#if defined(__GNUC__) + #define inline inline + #define alwaysinline inline __attribute__((always_inline)) +#elif defined(_MSC_VER) + #define inline inline + #define alwaysinline inline __forceinline +#else + #define inline inline + #define alwaysinline inline +#endif + #define debugvirtual namespace SNES @@ -27,22 +37,17 @@ public: int frequency; uint8 registers[4]; - inline void enter () - { - return; - } - inline void reset () { registers[0] = registers[1] = registers[2] = registers[3] = 0; } - inline void port_write (uint8 port, uint8 data) + alwaysinline void port_write (uint8 port, uint8 data) { registers[port & 3] = data; } - inline uint8 port_read (uint8 port) + alwaysinline uint8 port_read (uint8 port) { // printf ("APU Read %2x from port %d\n", registers[port & 3], port & 3); return registers[port & 3]; diff --git a/memmap.cpp b/memmap.cpp index 81edf082..7bf9bf6e 100644 --- a/memmap.cpp +++ b/memmap.cpp @@ -1502,7 +1502,7 @@ bool8 CMemory::LoadROM (const char *filename) ZeroMemory(ROM, MAX_ROM_SIZE); ZeroMemory(&Multi, sizeof(Multi)); - + again: Settings.DisplayColor = BUILD_PIXEL(31, 31, 31); SET_UI_COLOR(255, 255, 255); @@ -2254,7 +2254,7 @@ void CMemory::InitROM (void) Settings.SETA = 0; Settings.SRTC = FALSE; Settings.BS = FALSE; - + SuperFX.nRomBanks = CalculatedSize >> 15; //// Parse ROM header and read ROM informatoin @@ -3204,7 +3204,7 @@ void CMemory::Map_SPC7110HiROMMap (void) map_System(); map_index(0x00, 0x00, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); - map_hirom(0x00, 0x0f, 0x8000, 0xffff, CalculatedSize); + map_hirom(0x00, 0x0f, 0x8000, 0xffff, CalculatedSize); map_index(0x30, 0x30, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); map_index(0x50, 0x50, 0x0000, 0xffff, MAP_SPC7110_DRAM, MAP_TYPE_ROM); map_hirom(0x80, 0x8f, 0x8000, 0xffff, CalculatedSize); @@ -3499,14 +3499,13 @@ void CMemory::ApplyROMFixes (void) //// APU timing hacks :( Timings.APUSpeedup = 0; - Timings.APUAllowTimeOverflow = FALSE; if (!Settings.DisableGameSpecificHacks) { if (match_id("AVCJ")) // Rendering Ranger R2 - Timings.APUSpeedup = 4; + Timings.APUSpeedup = 2; - if (match_na("GAIA GENSOUKI 1 JPN") || // Gaia Gensouki +/* if (match_na("GAIA GENSOUKI 1 JPN") || // Gaia Gensouki match_id("JG ") || // Illusion of Gaia match_id("CQ ") || // Stunt Race FX match_na("SOULBLADER - 1") || // Soul Blader @@ -3540,22 +3539,10 @@ void CMemory::ApplyROMFixes (void) match_nn("Parlor") || // Parlor mini/2/3/4/5/6/7, Parlor Parlor!/2/3/4/5 match_na("HEIWA Parlor!Mini8") || // Parlor mini 8 match_nn("SANKYO Fever! \xCC\xA8\xB0\xCA\xDE\xB0!")) // SANKYO Fever! Fever! - Timings.APUSpeedup = 1; - - if (match_na ("EARTHWORM JIM 2") || // Earthworm Jim 2 - match_na ("NBA Hangtime") || // NBA Hang Time - match_na ("MSPACMAN") || // Ms Pacman - match_na ("THE MASK") || // The Mask - match_na ("PRIMAL RAGE") || // Primal Rage - match_na ("PORKY PIGS HAUNTED") || // Porky Pig's Haunted Holiday - match_na ("Big Sky Trooper") || // Big Sky Trooper - match_id ("A35") || // Mechwarrior 3050 / Battle Tech 3050 - match_na ("DOOM TROOPERS")) // Doom Troopers - Timings.APUAllowTimeOverflow = TRUE; + Timings.APUSpeedup = 1; */ } S9xAPUTimingSetSpeedup(Timings.APUSpeedup); - S9xAPUAllowTimeOverflow(Timings.APUAllowTimeOverflow); //// Other timing hacks :( diff --git a/snapshot.cpp b/snapshot.cpp index e2163de6..55823b4e 100644 --- a/snapshot.cpp +++ b/snapshot.cpp @@ -2278,7 +2278,7 @@ static void UnfreezeStructFromCopy (void *sbase, FreezeData *fields, int num_fie bool8 S9xSPCDump (const char *filename) { - /* No SPC dumping in byuu SMP */ + /* TODO: No SPC dumping in byuu SMP */ /* FILE *fs; uint8 buf[SNES_SPC::spc_file_size]; From 196d1ed2c78a023bd22dfb034089ca25bf80d502 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Thu, 23 Jun 2011 05:26:15 -0500 Subject: [PATCH 05/33] Remove debugging line. --- apu/bapu/snes/snes.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apu/bapu/snes/snes.hpp b/apu/bapu/snes/snes.hpp index be7e73f1..17e6305a 100755 --- a/apu/bapu/snes/snes.hpp +++ b/apu/bapu/snes/snes.hpp @@ -49,7 +49,6 @@ public: alwaysinline uint8 port_read (uint8 port) { - // printf ("APU Read %2x from port %d\n", registers[port & 3], port & 3); return registers[port & 3]; } }; From ebc9b7086028ff686e5c9bf3d2a8d737806bb5cc Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Thu, 23 Jun 2011 05:29:04 -0500 Subject: [PATCH 06/33] Fix permissions. --- apu/bapu/dsp/SPC_DSP.cpp | 0 apu/bapu/dsp/SPC_DSP.h | 0 apu/bapu/dsp/blargg_common.h | 0 apu/bapu/dsp/blargg_config.h | 0 apu/bapu/dsp/blargg_endian.h | 0 apu/bapu/dsp/blargg_source.h | 0 apu/bapu/dsp/dsp.cpp | 0 apu/bapu/dsp/dsp.hpp | 0 apu/bapu/dsp/serialization.cpp | 0 apu/bapu/smp/algorithms.cpp | 0 apu/bapu/smp/core.cpp | 0 apu/bapu/smp/core/generate.cpp | 0 apu/bapu/smp/core/op_misc.b | 0 apu/bapu/smp/core/op_misc.cpp | 0 apu/bapu/smp/core/op_mov.b | 0 apu/bapu/smp/core/op_mov.cpp | 0 apu/bapu/smp/core/op_pc.b | 0 apu/bapu/smp/core/op_pc.cpp | 0 apu/bapu/smp/core/op_read.b | 0 apu/bapu/smp/core/op_read.cpp | 0 apu/bapu/smp/core/op_rmw.b | 0 apu/bapu/smp/core/op_rmw.cpp | 0 apu/bapu/smp/core/opcycle_misc.cpp | 0 apu/bapu/smp/core/opcycle_mov.cpp | 0 apu/bapu/smp/core/opcycle_pc.cpp | 0 apu/bapu/smp/core/opcycle_read.cpp | 0 apu/bapu/smp/core/opcycle_rmw.cpp | 0 apu/bapu/smp/debugger/debugger.cpp | 0 apu/bapu/smp/debugger/debugger.hpp | 0 apu/bapu/smp/debugger/disassembler.cpp | 0 apu/bapu/smp/iplrom.cpp | 0 apu/bapu/smp/memory.cpp | 0 apu/bapu/smp/smp.cpp | 0 apu/bapu/smp/smp.hpp | 0 apu/bapu/smp/timing.cpp | 0 apu/bapu/snes/snes.hpp | 0 36 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 apu/bapu/dsp/SPC_DSP.cpp mode change 100755 => 100644 apu/bapu/dsp/SPC_DSP.h mode change 100755 => 100644 apu/bapu/dsp/blargg_common.h mode change 100755 => 100644 apu/bapu/dsp/blargg_config.h mode change 100755 => 100644 apu/bapu/dsp/blargg_endian.h mode change 100755 => 100644 apu/bapu/dsp/blargg_source.h mode change 100755 => 100644 apu/bapu/dsp/dsp.cpp mode change 100755 => 100644 apu/bapu/dsp/dsp.hpp mode change 100755 => 100644 apu/bapu/dsp/serialization.cpp mode change 100755 => 100644 apu/bapu/smp/algorithms.cpp mode change 100755 => 100644 apu/bapu/smp/core.cpp mode change 100755 => 100644 apu/bapu/smp/core/generate.cpp mode change 100755 => 100644 apu/bapu/smp/core/op_misc.b mode change 100755 => 100644 apu/bapu/smp/core/op_misc.cpp mode change 100755 => 100644 apu/bapu/smp/core/op_mov.b mode change 100755 => 100644 apu/bapu/smp/core/op_mov.cpp mode change 100755 => 100644 apu/bapu/smp/core/op_pc.b mode change 100755 => 100644 apu/bapu/smp/core/op_pc.cpp mode change 100755 => 100644 apu/bapu/smp/core/op_read.b mode change 100755 => 100644 apu/bapu/smp/core/op_read.cpp mode change 100755 => 100644 apu/bapu/smp/core/op_rmw.b mode change 100755 => 100644 apu/bapu/smp/core/op_rmw.cpp mode change 100755 => 100644 apu/bapu/smp/core/opcycle_misc.cpp mode change 100755 => 100644 apu/bapu/smp/core/opcycle_mov.cpp mode change 100755 => 100644 apu/bapu/smp/core/opcycle_pc.cpp mode change 100755 => 100644 apu/bapu/smp/core/opcycle_read.cpp mode change 100755 => 100644 apu/bapu/smp/core/opcycle_rmw.cpp mode change 100755 => 100644 apu/bapu/smp/debugger/debugger.cpp mode change 100755 => 100644 apu/bapu/smp/debugger/debugger.hpp mode change 100755 => 100644 apu/bapu/smp/debugger/disassembler.cpp mode change 100755 => 100644 apu/bapu/smp/iplrom.cpp mode change 100755 => 100644 apu/bapu/smp/memory.cpp mode change 100755 => 100644 apu/bapu/smp/smp.cpp mode change 100755 => 100644 apu/bapu/smp/smp.hpp mode change 100755 => 100644 apu/bapu/smp/timing.cpp mode change 100755 => 100644 apu/bapu/snes/snes.hpp diff --git a/apu/bapu/dsp/SPC_DSP.cpp b/apu/bapu/dsp/SPC_DSP.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/dsp/SPC_DSP.h b/apu/bapu/dsp/SPC_DSP.h old mode 100755 new mode 100644 diff --git a/apu/bapu/dsp/blargg_common.h b/apu/bapu/dsp/blargg_common.h old mode 100755 new mode 100644 diff --git a/apu/bapu/dsp/blargg_config.h b/apu/bapu/dsp/blargg_config.h old mode 100755 new mode 100644 diff --git a/apu/bapu/dsp/blargg_endian.h b/apu/bapu/dsp/blargg_endian.h old mode 100755 new mode 100644 diff --git a/apu/bapu/dsp/blargg_source.h b/apu/bapu/dsp/blargg_source.h old mode 100755 new mode 100644 diff --git a/apu/bapu/dsp/dsp.cpp b/apu/bapu/dsp/dsp.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/dsp/dsp.hpp b/apu/bapu/dsp/dsp.hpp old mode 100755 new mode 100644 diff --git a/apu/bapu/dsp/serialization.cpp b/apu/bapu/dsp/serialization.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/algorithms.cpp b/apu/bapu/smp/algorithms.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/generate.cpp b/apu/bapu/smp/core/generate.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_misc.b b/apu/bapu/smp/core/op_misc.b old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_misc.cpp b/apu/bapu/smp/core/op_misc.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_mov.b b/apu/bapu/smp/core/op_mov.b old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_mov.cpp b/apu/bapu/smp/core/op_mov.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_pc.b b/apu/bapu/smp/core/op_pc.b old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_pc.cpp b/apu/bapu/smp/core/op_pc.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_read.b b/apu/bapu/smp/core/op_read.b old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_read.cpp b/apu/bapu/smp/core/op_read.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_rmw.b b/apu/bapu/smp/core/op_rmw.b old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_rmw.cpp b/apu/bapu/smp/core/op_rmw.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/opcycle_misc.cpp b/apu/bapu/smp/core/opcycle_misc.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/opcycle_mov.cpp b/apu/bapu/smp/core/opcycle_mov.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/opcycle_pc.cpp b/apu/bapu/smp/core/opcycle_pc.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/opcycle_read.cpp b/apu/bapu/smp/core/opcycle_read.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/opcycle_rmw.cpp b/apu/bapu/smp/core/opcycle_rmw.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/debugger/debugger.cpp b/apu/bapu/smp/debugger/debugger.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/debugger/debugger.hpp b/apu/bapu/smp/debugger/debugger.hpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/debugger/disassembler.cpp b/apu/bapu/smp/debugger/disassembler.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/iplrom.cpp b/apu/bapu/smp/iplrom.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/memory.cpp b/apu/bapu/smp/memory.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/smp.cpp b/apu/bapu/smp/smp.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/timing.cpp b/apu/bapu/smp/timing.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/snes/snes.hpp b/apu/bapu/snes/snes.hpp old mode 100755 new mode 100644 From 08f5601c5f1615ac22c193f487c519978d5179c3 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Thu, 23 Jun 2011 06:14:14 -0500 Subject: [PATCH 07/33] Reduce the sync footprint slightly with less indirection. --- apu/bapu/dsp/dsp.cpp | 13 ------------- apu/bapu/dsp/dsp.hpp | 2 -- apu/bapu/smp/core.cpp | 15 +++++++++------ apu/bapu/smp/smp.cpp | 2 ++ 4 files changed, 11 insertions(+), 21 deletions(-) diff --git a/apu/bapu/dsp/dsp.cpp b/apu/bapu/dsp/dsp.cpp index c0a2a9c8..0a6137c4 100644 --- a/apu/bapu/dsp/dsp.cpp +++ b/apu/bapu/dsp/dsp.cpp @@ -7,19 +7,6 @@ DSP dsp; #include "SPC_DSP.cpp" -void DSP::step(unsigned clocks) { - clock += clocks; -} - -void DSP::synchronize_smp() { - while(clock >= 0) smp.enter(); -} - -void DSP::enter() { - spc_dsp.run(1); - step(24); -} - uint8 DSP::read(uint8 addr) { return spc_dsp.read(addr); } diff --git a/apu/bapu/dsp/dsp.hpp b/apu/bapu/dsp/dsp.hpp index ef2dc7c7..1109bda8 100644 --- a/apu/bapu/dsp/dsp.hpp +++ b/apu/bapu/dsp/dsp.hpp @@ -3,13 +3,11 @@ class DSP : public Processor { public: enum { Threaded = false }; - alwaysinline void step(unsigned clocks); alwaysinline void synchronize_smp(); uint8 read(uint8 addr); void write(uint8 addr, uint8 data); - void enter(); void power(); void reset(); diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp index 01f265a5..df4076c1 100644 --- a/apu/bapu/smp/core.cpp +++ b/apu/bapu/smp/core.cpp @@ -5,11 +5,12 @@ void SMP::tick() { #ifndef SNES9X clock += cycle_step_cpu; -#else - clock++; -#endif dsp.clock -= 24; synchronize_dsp(); +#else + clock++; + dsp.spc_dsp.run(1); +#endif } void SMP::op_io() { @@ -77,11 +78,13 @@ void SMP::op_step() { #ifndef SNES9X clock += cycle_table_cpu[opcode]; -#else - clock += cycle_count_table[opcode]; -#endif dsp.clock -= cycle_table_dsp[opcode]; synchronize_dsp(); +#else + clock += cycle_count_table[opcode]; + dsp.spc_dsp.run(cycle_count_table[opcode]); +#endif + #endif } diff --git a/apu/bapu/smp/smp.cpp b/apu/bapu/smp/smp.cpp index 49556f3f..e0bb9019 100644 --- a/apu/bapu/smp/smp.cpp +++ b/apu/bapu/smp/smp.cpp @@ -34,11 +34,13 @@ void SMP::synchronize_cpu() { } void SMP::synchronize_dsp() { +#ifndef SNES9X if(DSP::Threaded == true) { //if(dsp.clock < 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(dsp.thread); } else { while(dsp.clock < 0) dsp.enter(); } +#endif } void SMP::enter() { From 7c468e51c017ed8692b656bb5ef7739a33b259d4 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Thu, 23 Jun 2011 06:28:34 -0500 Subject: [PATCH 08/33] Remove parts of DSP wrapper we don't need. --- apu/bapu/dsp/dsp.cpp | 18 ------------------ apu/bapu/dsp/dsp.hpp | 15 ++++++--------- 2 files changed, 6 insertions(+), 27 deletions(-) diff --git a/apu/bapu/dsp/dsp.cpp b/apu/bapu/dsp/dsp.cpp index 0a6137c4..dc2027cb 100644 --- a/apu/bapu/dsp/dsp.cpp +++ b/apu/bapu/dsp/dsp.cpp @@ -7,14 +7,6 @@ DSP dsp; #include "SPC_DSP.cpp" -uint8 DSP::read(uint8 addr) { - return spc_dsp.read(addr); -} - -void DSP::write(uint8 addr, uint8 data) { - spc_dsp.write(addr, data); -} - void DSP::power() { spc_dsp.init(smp.apuram); spc_dsp.reset(); @@ -24,17 +16,7 @@ void DSP::reset() { spc_dsp.soft_reset(); } -void DSP::channel_enable(unsigned channel, bool enable) { - channel_enabled[channel & 7] = enable; - unsigned mask = 0; - for(unsigned i = 0; i < 8; i++) { - if(channel_enabled[i] == false) mask |= 1 << i; - } - spc_dsp.mute_voices(mask); -} - DSP::DSP() { - for(unsigned i = 0; i < 8; i++) channel_enabled[i] = true; } } diff --git a/apu/bapu/dsp/dsp.hpp b/apu/bapu/dsp/dsp.hpp index 1109bda8..ae965f3d 100644 --- a/apu/bapu/dsp/dsp.hpp +++ b/apu/bapu/dsp/dsp.hpp @@ -2,23 +2,20 @@ class DSP : public Processor { public: - enum { Threaded = false }; - alwaysinline void synchronize_smp(); + inline uint8 read(uint8 addr) { + return spc_dsp.read(addr); + } - uint8 read(uint8 addr); - void write(uint8 addr, uint8 data); + inline void write(uint8 addr, uint8 data) { + spc_dsp.write(addr, data); + } void power(); void reset(); - void channel_enable(unsigned channel, bool enable); - DSP(); SPC_DSP spc_dsp; - -private: - bool channel_enabled[8]; }; extern DSP dsp; From 39add9b47e06425adc075b7c5df2581c7d84cce8 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Fri, 24 Jun 2011 06:42:04 -0500 Subject: [PATCH 09/33] Save states support for new APU. --- apu/apu.cpp | 27 +++++---- apu/apu.h | 2 +- apu/bapu/dsp/dsp.cpp | 31 +++++++++- apu/bapu/dsp/dsp.hpp | 3 + apu/bapu/smp/smp.hpp | 3 + apu/bapu/smp/smp_state.cpp | 119 +++++++++++++++++++++++++++++++++++++ apu/bapu/snes/snes.hpp | 2 +- gtk/Makefile.am | 4 +- snapshot.cpp | 10 ++-- 9 files changed, 178 insertions(+), 23 deletions(-) create mode 100644 apu/bapu/smp/smp_state.cpp diff --git a/apu/apu.cpp b/apu/apu.cpp index 604478d6..80f1ed4c 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -194,6 +194,8 @@ namespace SNES { +#include "dsp/blargg_endian.h" + CPU cpu; } @@ -229,8 +231,6 @@ static void EightBitize (uint8 *, int); static void DeStereo (uint8 *, int); static void ReverseStereo (uint8 *, int); static void UpdatePlaybackRate (void); -static void from_apu_to_state (uint8 **, void *, size_t); -static void to_apu_from_state (uint8 **, void *, size_t); static void SPCSnapshotCallback (void); static inline int S9xAPUGetClock (int32); static inline int S9xAPUGetClockRemainder (int32); @@ -605,25 +605,30 @@ void S9xSoftResetAPU (void) void S9xAPUSaveState (uint8 *block) { -// TODO: Save states -/* uint8 *ptr = block; + uint8 *ptr = block; - spc_core->copy_state(&ptr, from_apu_to_state); + SNES::smp.save_state (&ptr); + SNES::dsp.save_state (&ptr); - SET_LE32(ptr, spc::reference_time); + SNES::set_le32(ptr, spc::reference_time); ptr += sizeof(int32); - SET_LE32(ptr, spc::remainder); */ + SNES::set_le32(ptr, spc::remainder); + ptr += sizeof(int32); + memcpy (ptr, SNES::cpu.registers, 4); } void S9xAPULoadState (uint8 *block) { -/* uint8 *ptr = block; + uint8 *ptr = block; S9xResetAPU(); - spc_core->copy_state(&ptr, to_apu_from_state); + SNES::smp.load_state (&ptr); + SNES::dsp.load_state (&ptr); - spc::reference_time = GET_LE32(ptr); + spc::reference_time = SNES::get_le32(ptr); ptr += sizeof(int32); - spc::remainder = GET_LE32(ptr); */ + spc::remainder = SNES::get_le32(ptr); + ptr += sizeof(int32); + memcpy (SNES::cpu.registers, ptr, 4); } diff --git a/apu/apu.h b/apu/apu.h index c0967caa..77cc4bfd 100644 --- a/apu/apu.h +++ b/apu/apu.h @@ -183,7 +183,7 @@ typedef void (*apu_callback) (void *); -#define SPC_SAVE_STATE_BLOCK_SIZE (SNES_SPC::state_size + 8) +#define SPC_SAVE_STATE_BLOCK_SIZE (1024 * 65) bool8 S9xInitAPU (void); void S9xDeinitAPU (void); diff --git a/apu/bapu/dsp/dsp.cpp b/apu/bapu/dsp/dsp.cpp index dc2027cb..ef2c48da 100644 --- a/apu/bapu/dsp/dsp.cpp +++ b/apu/bapu/dsp/dsp.cpp @@ -7,16 +7,41 @@ DSP dsp; #include "SPC_DSP.cpp" -void DSP::power() { +void DSP::power() +{ spc_dsp.init(smp.apuram); spc_dsp.reset(); } -void DSP::reset() { +void DSP::reset() +{ spc_dsp.soft_reset(); } -DSP::DSP() { +static void from_dsp_to_state (uint8 **buf, void *var, size_t size) +{ + memcpy(*buf, var, size); + *buf += size; +} + +static void to_dsp_from_state (uint8 **buf, void *var, size_t size) +{ + memcpy(var, *buf, size); + *buf += size; +} + +void DSP::save_state (uint8 **ptr) +{ + spc_dsp.copy_state(ptr, from_dsp_to_state); +} + +void DSP::load_state (uint8 **ptr) +{ + spc_dsp.copy_state(ptr, to_dsp_from_state); +} + +DSP::DSP() +{ } } diff --git a/apu/bapu/dsp/dsp.hpp b/apu/bapu/dsp/dsp.hpp index ae965f3d..83d51eb5 100644 --- a/apu/bapu/dsp/dsp.hpp +++ b/apu/bapu/dsp/dsp.hpp @@ -10,6 +10,9 @@ public: spc_dsp.write(addr, data); } + void save_state(uint8 **); + void load_state(uint8 **); + void power(); void reset(); diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp index 5d2c3d64..b50bb631 100644 --- a/apu/bapu/smp/smp.hpp +++ b/apu/bapu/smp/smp.hpp @@ -19,6 +19,9 @@ public: #ifndef SNES9X void serialize(serializer&); +#else + void load_state(uint8 **); + void save_state(uint8 **); #endif SMP(); ~SMP(); diff --git a/apu/bapu/smp/smp_state.cpp b/apu/bapu/smp/smp_state.cpp new file mode 100644 index 00000000..2e590e69 --- /dev/null +++ b/apu/bapu/smp/smp_state.cpp @@ -0,0 +1,119 @@ +#include "snes/snes.hpp" + +namespace SNES { + +#include "dsp/blargg_endian.h" + +void SMP::save_state(uint8 **block) { + uint8 *ptr = *block; + memcpy(ptr, apuram, 64 * 1024); + ptr += 64 * 1024; + +#undef INT32 +#define INT32(i) set_le32(ptr, (i)); ptr += sizeof(int32) + INT32(clock); + + INT32(opcode_number); + INT32(opcode_cycle); + + INT32(regs.pc); + INT32(regs.sp); + INT32(regs.a); + INT32(regs.x); + INT32(regs.y); + + INT32(regs.p.n); + INT32(regs.p.v); + INT32(regs.p.p); + INT32(regs.p.b); + INT32(regs.p.h); + INT32(regs.p.i); + INT32(regs.p.z); + INT32(regs.p.c); + + INT32(status.iplrom_enable); + + INT32(status.dsp_addr); + + INT32(status.ram00f8); + INT32(status.ram00f9); + + INT32(timer0.enable); + INT32(timer0.target); + INT32(timer0.stage1_ticks); + INT32(timer0.stage2_ticks); + INT32(timer0.stage3_ticks); + + INT32(timer1.enable); + INT32(timer1.target); + INT32(timer1.stage1_ticks); + INT32(timer1.stage2_ticks); + INT32(timer1.stage3_ticks); + + INT32(timer2.enable); + INT32(timer2.target); + + INT32(timer2.stage1_ticks); + INT32(timer2.stage2_ticks); + INT32(timer2.stage3_ticks); + + *block = ptr; +} + +void SMP::load_state(uint8 **block) { + uint8 *ptr = *block; + memcpy(apuram, ptr, 64 * 1024); + ptr += 64 * 1024; + +#undef INT32 +#define INT32(i) i = get_le32(ptr); ptr += sizeof(int32) + INT32(clock); + + INT32(opcode_number); + INT32(opcode_cycle); + + INT32(regs.pc); + INT32(regs.sp); + INT32(regs.a); + INT32(regs.x); + INT32(regs.y); + + INT32(regs.p.n); + INT32(regs.p.v); + INT32(regs.p.p); + INT32(regs.p.b); + INT32(regs.p.h); + INT32(regs.p.i); + INT32(regs.p.z); + INT32(regs.p.c); + + INT32(status.iplrom_enable); + + INT32(status.dsp_addr); + + INT32(status.ram00f8); + INT32(status.ram00f9); + + INT32(timer0.enable); + INT32(timer0.target); + INT32(timer0.stage1_ticks); + INT32(timer0.stage2_ticks); + INT32(timer0.stage3_ticks); + + INT32(timer1.enable); + INT32(timer1.target); + INT32(timer1.stage1_ticks); + INT32(timer1.stage2_ticks); + INT32(timer1.stage3_ticks); + + INT32(timer2.enable); + INT32(timer2.target); + + INT32(timer2.stage1_ticks); + INT32(timer2.stage2_ticks); + INT32(timer2.stage3_ticks); + + *block = ptr; +} + +} diff --git a/apu/bapu/snes/snes.hpp b/apu/bapu/snes/snes.hpp index 17e6305a..58a2d8a0 100644 --- a/apu/bapu/snes/snes.hpp +++ b/apu/bapu/snes/snes.hpp @@ -24,7 +24,7 @@ namespace SNES struct Processor { unsigned frequency; - int clock; + int32 clock; }; #include "smp/smp.hpp" diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 607d70bb..85ee9055 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -124,9 +124,9 @@ snes9x_gtk_SOURCES += \ # Byuu's APU snes9x_gtk_SOURCES += \ ../apu/bapu/dsp/dsp.cpp \ - ../apu/bapu/dsp/serialization.cpp \ ../apu/bapu/dsp/SPC_DSP.cpp \ - ../apu/bapu/smp/smp.cpp + ../apu/bapu/smp/smp.cpp \ + ../apu/bapu/smp/smp_state.cpp # DSP snes9x_gtk_SOURCES += \ diff --git a/snapshot.cpp b/snapshot.cpp index 55823b4e..d07c430b 100644 --- a/snapshot.cpp +++ b/snapshot.cpp @@ -1269,7 +1269,7 @@ bool8 S9xUnfreezeGame (const char *filename) void S9xFreezeToStream (STREAM stream) { char buffer[1024]; - //uint8 *soundsnapshot = new uint8[SPC_SAVE_STATE_BLOCK_SIZE]; + uint8 *soundsnapshot = new uint8[SPC_SAVE_STATE_BLOCK_SIZE]; S9xSetSoundMute(TRUE); @@ -1298,8 +1298,8 @@ void S9xFreezeToStream (STREAM stream) FreezeBlock (stream, "FIL", Memory.FillRAM, 0x8000); - //S9xAPUSaveState(soundsnapshot); - //FreezeBlock (stream, "SND", soundsnapshot, SPC_SAVE_STATE_BLOCK_SIZE); + S9xAPUSaveState(soundsnapshot); + FreezeBlock (stream, "SND", soundsnapshot, SPC_SAVE_STATE_BLOCK_SIZE); struct SControlSnapshot ctl_snap; S9xControlPreSaveState(&ctl_snap); @@ -1410,7 +1410,7 @@ void S9xFreezeToStream (STREAM stream) S9xSetSoundMute(FALSE); - //delete [] soundsnapshot; + delete [] soundsnapshot; } int S9xUnfreezeFromStream (STREAM stream) @@ -1496,7 +1496,7 @@ int S9xUnfreezeFromStream (STREAM stream) if (result != SUCCESS) break; - // result = UnfreezeBlockCopy (stream, "SND", &local_apu_sound, SPC_SAVE_STATE_BLOCK_SIZE); + result = UnfreezeBlockCopy (stream, "SND", &local_apu_sound, SPC_SAVE_STATE_BLOCK_SIZE); if (result != SUCCESS) break; From 7963d0e66ba4707ef8d4aee800c63291249e12af Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Fri, 24 Jun 2011 18:09:08 -0500 Subject: [PATCH 10/33] Remove serialization.cpp. --- apu/bapu/dsp/serialization.cpp | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 apu/bapu/dsp/serialization.cpp diff --git a/apu/bapu/dsp/serialization.cpp b/apu/bapu/dsp/serialization.cpp deleted file mode 100644 index 0565a1b5..00000000 --- a/apu/bapu/dsp/serialization.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#ifdef DSP_CPP - -static void dsp_state_save(unsigned char **out, void *in, size_t size) { - memcpy(*out, in, size); - *out += size; -} - -static void dsp_state_load(unsigned char **in, void *out, size_t size) { - memcpy(out, *in, size); - *in += size; -} - -void DSP::serialize(serializer &s) { - Processor::serialize(s); - s.array(samplebuffer); - - unsigned char state[SPC_DSP::state_size]; - unsigned char *p = state; - memset(&state, 0, SPC_DSP::state_size); - if(s.mode() == serializer::Save) { - spc_dsp.copy_state(&p, dsp_state_save); - s.array(state); - } else if(s.mode() == serializer::Load) { - s.array(state); - spc_dsp.copy_state(&p, dsp_state_load); - } else { - s.array(state); - } -} - -#endif From 2e94b98e904dcc1441087007b46f290c5dc08225 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Sat, 25 Jun 2011 03:10:42 -0500 Subject: [PATCH 11/33] Clear up CYCLE_ACCURATE confusion. Rename dsp.* to sdsp.*. --- apu/bapu/dsp/{dsp.cpp => sdsp.cpp} | 0 apu/bapu/dsp/{dsp.hpp => sdsp.hpp} | 0 apu/bapu/smp/smp.cpp | 4 ---- apu/bapu/snes/snes.hpp | 2 +- gtk/Makefile.am | 2 +- 5 files changed, 2 insertions(+), 6 deletions(-) rename apu/bapu/dsp/{dsp.cpp => sdsp.cpp} (100%) rename apu/bapu/dsp/{dsp.hpp => sdsp.hpp} (100%) diff --git a/apu/bapu/dsp/dsp.cpp b/apu/bapu/dsp/sdsp.cpp similarity index 100% rename from apu/bapu/dsp/dsp.cpp rename to apu/bapu/dsp/sdsp.cpp diff --git a/apu/bapu/dsp/dsp.hpp b/apu/bapu/dsp/sdsp.hpp similarity index 100% rename from apu/bapu/dsp/dsp.hpp rename to apu/bapu/dsp/sdsp.hpp diff --git a/apu/bapu/smp/smp.cpp b/apu/bapu/smp/smp.cpp index e0bb9019..a8092fcb 100644 --- a/apu/bapu/smp/smp.cpp +++ b/apu/bapu/smp/smp.cpp @@ -1,8 +1,4 @@ -#ifndef SNES9X #define CYCLE_ACCURATE -#else -#undef CYCLE_ACCURATE -#endif #include diff --git a/apu/bapu/snes/snes.hpp b/apu/bapu/snes/snes.hpp index 58a2d8a0..3e8cd2b3 100644 --- a/apu/bapu/snes/snes.hpp +++ b/apu/bapu/snes/snes.hpp @@ -28,7 +28,7 @@ struct Processor }; #include "smp/smp.hpp" -#include "dsp/dsp.hpp" +#include "dsp/sdsp.hpp" class CPU { diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 85ee9055..9f380914 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -123,7 +123,7 @@ snes9x_gtk_SOURCES += \ # Byuu's APU snes9x_gtk_SOURCES += \ - ../apu/bapu/dsp/dsp.cpp \ + ../apu/bapu/dsp/sdsp.cpp \ ../apu/bapu/dsp/SPC_DSP.cpp \ ../apu/bapu/smp/smp.cpp \ ../apu/bapu/smp/smp_state.cpp From ebc9e721f6f4374ac23ac419b2ebfd0c96c694c3 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Sun, 26 Jun 2011 05:33:14 -0500 Subject: [PATCH 12/33] Add SPC dumping support. --- apu/apu.cpp | 29 ++++++- apu/apu.h | 4 +- apu/bapu/dsp/SPC_DSP.cpp | 161 +++++++++++++++++++------------------ apu/bapu/smp/smp.hpp | 1 + apu/bapu/smp/smp_state.cpp | 68 +++++++++++++++- snapshot.cpp | 26 ------ snapshot.h | 1 - 7 files changed, 179 insertions(+), 111 deletions(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index 80f1ed4c..11bb5c7d 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -476,8 +476,8 @@ void S9xSetSoundMute (bool8 mute) void S9xDumpSPCSnapshot (void) { -/* TODO: SPC dumping */ -/* spc_core->dsp_dump_spc_snapshot(); */ + SNES::dsp.spc_dsp.dump_spc_snapshot(); + } static void SPCSnapshotCallback (void) @@ -492,6 +492,8 @@ bool8 S9xInitAPU (void) spc::shrink_buffer = NULL; spc::resampler = NULL; + SNES::dsp.spc_dsp.set_spc_snapshot_callback(SPCSnapshotCallback); + return (TRUE); } @@ -632,3 +634,26 @@ void S9xAPULoadState (uint8 *block) ptr += sizeof(int32); memcpy (SNES::cpu.registers, ptr, 4); } + +bool8 S9xSPCDump (const char *filename) +{ + FILE *fs; + uint8 buf[SPC_FILE_SIZE]; + size_t ignore; + + fs = fopen(filename, "wb"); + if (!fs) + return (FALSE); + + S9xSetSoundMute(TRUE); + + SNES::smp.save_spc (buf); + + ignore = fwrite(buf, SPC_FILE_SIZE, 1, fs); + + fclose(fs); + + S9xSetSoundMute(FALSE); + + return (TRUE); +} diff --git a/apu/apu.h b/apu/apu.h index 77cc4bfd..44b183a8 100644 --- a/apu/apu.h +++ b/apu/apu.h @@ -183,7 +183,8 @@ typedef void (*apu_callback) (void *); -#define SPC_SAVE_STATE_BLOCK_SIZE (1024 * 65) +#define SPC_SAVE_STATE_BLOCK_SIZE (1024 * 65) +#define SPC_FILE_SIZE (66048) bool8 S9xInitAPU (void); void S9xDeinitAPU (void); @@ -199,6 +200,7 @@ void S9xAPUAllowTimeOverflow (bool); void S9xAPULoadState (uint8 *); void S9xAPUSaveState (uint8 *); void S9xDumpSPCSnapshot (void); +bool8 S9xSPCDump (const char *); bool8 S9xInitSound (int, int); bool8 S9xOpenSoundDevice (void); diff --git a/apu/bapu/dsp/SPC_DSP.cpp b/apu/bapu/dsp/SPC_DSP.cpp index e6ba49ed..e3719203 100644 --- a/apu/bapu/dsp/SPC_DSP.cpp +++ b/apu/bapu/dsp/SPC_DSP.cpp @@ -132,7 +132,7 @@ inline int SPC_DSP::interpolate( voice_t const* v ) int offset = v->interp_pos >> 4 & 0xFF; short const* fwd = gauss + 255 - offset; short const* rev = gauss + offset; // mirror left half of gaussian - + int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; int out; out = (fwd [ 0] * in [0]) >> 11; @@ -140,7 +140,7 @@ inline int SPC_DSP::interpolate( voice_t const* v ) out += (rev [256] * in [2]) >> 11; out = (int16_t) out; out += (rev [ 0] * in [3]) >> 11; - + CLAMP16( out ); out &= ~1; return out; @@ -262,13 +262,13 @@ inline void SPC_DSP::run_envelope( voice_t* const v ) } } } - + // Sustain level if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay ) v->env_mode = env_sustain; - + v->hidden_env = env; - + // unsigned cast because linear decrease going negative also triggers this if ( (unsigned) env > 0x7FF ) { @@ -276,7 +276,7 @@ inline void SPC_DSP::run_envelope( voice_t* const v ) if ( v->env_mode == env_attack ) v->env_mode = env_decay; } - + if ( !read_counter( rate ) ) v->env = env; // nothing else is controlled by the counter } @@ -289,27 +289,27 @@ inline void SPC_DSP::decode_brr( voice_t* v ) { // Arrange the four input nybbles in 0xABCD order for easy decoding int nybbles = m.t_brr_byte * 0x100 + m.ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF]; - + int const header = m.t_brr_header; - + // Write to next four samples in circular buffer int* pos = &v->buf [v->buf_pos]; int* end; if ( (v->buf_pos += 4) >= brr_buf_size ) v->buf_pos = 0; - + // Decode four samples for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 ) { // Extract nybble and sign-extend int s = (int16_t) nybbles >> 12; - + // Shift sample based on header int const shift = header >> 4; s = (s << shift) >> 1; if ( shift >= 0xD ) // handle invalid range s = (s >> 25) << 11; // same as: s = (s < 0 ? -0x800 : 0) - + // Apply IIR filter (8 is the most commonly used) int const filter = header & 0x0C; int const p1 = pos [brr_buf_size - 1]; @@ -334,7 +334,7 @@ inline void SPC_DSP::decode_brr( voice_t* v ) s += p1 >> 1; s += (-p1) >> 5; } - + // Adjust and write sample CLAMP16( s ); s = (int16_t) (s * 2); @@ -367,11 +367,11 @@ MISC_CLOCK( 30 ) if ( m.every_other_sample ) { m.kon = m.new_kon; - m.t_koff = REG(koff) | m.mute_mask; + m.t_koff = REG(koff) | m.mute_mask; } - + run_counters(); - + // Noise if ( !read_counter( REG(flg) & 0x1F ) ) { @@ -397,9 +397,9 @@ inline VOICE_CLOCK( V2 ) if ( !v->kon_delay ) entry += 2; m.t_brr_next_addr = GET_LE16A( entry ); - + m.t_adsr0 = VREG(v->regs,adsr0); - + // Read pitch, spread over two clocks m.t_pitch = VREG(v->regs,pitchl); } @@ -418,7 +418,7 @@ VOICE_CLOCK( V3c ) // Pitch modulation using previous voice's output if ( m.t_pmon & v->vbit ) m.t_pitch += ((m.t_output >> 5) * m.t_pitch) >> 10; - + if ( v->kon_delay ) { // Get ready to start BRR decoding on next sample @@ -437,46 +437,46 @@ VOICE_CLOCK( V3c ) spc_snapshot_callback(); } } - + // Envelope is never run during KON v->env = 0; v->hidden_env = 0; - + // Disable BRR decoding until last three samples v->interp_pos = 0; if ( --v->kon_delay & 3 ) v->interp_pos = 0x4000; - + // Pitch is never added during KON m.t_pitch = 0; } - + // Gaussian interpolation { int output = interpolate( v ); - + // Noise if ( m.t_non & v->vbit ) output = (int16_t) (m.noise * 2); - + // Apply envelope m.t_output = (output * v->env) >> 11 & ~1; v->t_envx_out = (uint8_t) (v->env >> 4); } - + // Immediate silence due to end of sample or soft reset if ( REG(flg) & 0x80 || (m.t_brr_header & 3) == 1 ) { v->env_mode = env_release; v->env = 0; } - + if ( m.every_other_sample ) { // KOFF if ( m.t_koff & v->vbit ) v->env_mode = env_release; - + // KON if ( m.kon & v->vbit ) { @@ -484,7 +484,7 @@ VOICE_CLOCK( V3c ) v->env_mode = env_attack; } } - + // Run envelope for next sample if ( !v->kon_delay ) run_envelope( v ); @@ -499,7 +499,7 @@ inline void SPC_DSP::voice_output( voice_t const* v, int ch ) // Add to output total m.t_main_out [ch] += amp; CLAMP16( m.t_main_out [ch] ); - + // Optionally add to echo total if ( m.t_eon & v->vbit ) { @@ -514,7 +514,7 @@ VOICE_CLOCK( V4 ) if ( v->interp_pos >= 0x4000 ) { decode_brr( v ); - + if ( (v->brr_offset += 2) >= brr_block_size ) { // Start decoding next BRR block @@ -528,14 +528,14 @@ VOICE_CLOCK( V4 ) v->brr_offset = 1; } } - + // Apply pitch v->interp_pos = (v->interp_pos & 0x3FFF) + m.t_pitch; - + // Keep from getting too far ahead (when using pitch modulation) if ( v->interp_pos > 0x7FFF ) v->interp_pos = 0x7FFF; - + // Output left voice_output( v, 0 ); } @@ -543,10 +543,10 @@ inline VOICE_CLOCK( V5 ) { // Output right voice_output( v, 1 ); - + // ENDX, OUTX, and ENVX won't update if you wrote to them 1-2 clocks earlier int endx_buf = REG(endx) | m.t_looped; - + // Clear bit in ENDX if KON just began if ( v->kon_delay == 5 ) endx_buf &= ~v->vbit; @@ -561,7 +561,7 @@ inline VOICE_CLOCK( V7 ) { // Update ENDX REG(endx) = m.endx_buf; - + m.envx_buf = v->t_envx_out; } inline VOICE_CLOCK( V8 ) @@ -619,14 +619,14 @@ ECHO_CLOCK( 22 ) // History if ( ++m.echo_hist_pos >= &m.echo_hist [echo_hist_size] ) m.echo_hist_pos = m.echo_hist; - + m.t_echo_ptr = (m.t_esa * 0x100 + m.echo_offset) & 0xFFFF; echo_read( 0 ); - + // FIR (using l and r temporaries below helps compiler optimize) int l = CALC_FIR( 0, 0 ); int r = CALC_FIR( 0, 1 ); - + m.t_echo_in [0] = l; m.t_echo_in [1] = r; } @@ -634,17 +634,17 @@ ECHO_CLOCK( 23 ) { int l = CALC_FIR( 1, 0 ) + CALC_FIR( 2, 0 ); int r = CALC_FIR( 1, 1 ) + CALC_FIR( 2, 1 ); - + m.t_echo_in [0] += l; m.t_echo_in [1] += r; - + echo_read( 1 ); } ECHO_CLOCK( 24 ) { int l = CALC_FIR( 3, 0 ) + CALC_FIR( 4, 0 ) + CALC_FIR( 5, 0 ); int r = CALC_FIR( 3, 1 ) + CALC_FIR( 4, 1 ) + CALC_FIR( 5, 1 ); - + m.t_echo_in [0] += l; m.t_echo_in [1] += r; } @@ -652,16 +652,16 @@ ECHO_CLOCK( 25 ) { int l = m.t_echo_in [0] + CALC_FIR( 6, 0 ); int r = m.t_echo_in [1] + CALC_FIR( 6, 1 ); - + l = (int16_t) l; r = (int16_t) r; - + l += (int16_t) CALC_FIR( 7, 0 ); r += (int16_t) CALC_FIR( 7, 1 ); - + CLAMP16( l ); CLAMP16( r ); - + m.t_echo_in [0] = l & ~1; m.t_echo_in [1] = r & ~1; } @@ -677,14 +677,14 @@ ECHO_CLOCK( 26 ) // Left output volumes // (save sample for next clock so we can output both together) m.t_main_out [0] = echo_output( 0 ); - + // Echo feedback int l = m.t_echo_out [0] + (int16_t) ((m.t_echo_in [0] * (int8_t) REG(efb)) >> 7); int r = m.t_echo_out [1] + (int16_t) ((m.t_echo_in [1] * (int8_t) REG(efb)) >> 7); - + CLAMP16( l ); CLAMP16( r ); - + m.t_echo_out [0] = l & ~1; m.t_echo_out [1] = r & ~1; } @@ -695,7 +695,7 @@ ECHO_CLOCK( 27 ) int r = echo_output( 1 ); m.t_main_out [0] = 0; m.t_main_out [1] = 0; - + // TODO: global muting isn't this simple (turns DAC on and off // or something, causing small ~37-sample pulse when first muted) if ( REG(flg) & 0x40 ) @@ -703,7 +703,7 @@ ECHO_CLOCK( 27 ) l = 0; r = 0; } - + // Output sample to DAC #ifdef SPC_DSP_OUT_HOOK SPC_DSP_OUT_HOOK( l, r ); @@ -732,17 +732,17 @@ inline void SPC_DSP::echo_write( int ch ) ECHO_CLOCK( 29 ) { m.t_esa = REG(esa); - + if ( !m.echo_offset ) m.echo_length = (REG(edl) & 0x0F) * 0x800; - + m.echo_offset += 4; if ( m.echo_offset >= m.echo_length ) m.echo_offset = 0; - + // Write left echo echo_write( 0 ); - + m.t_echo_enabled = REG(flg); } ECHO_CLOCK( 30 ) @@ -805,17 +805,17 @@ PHASE(31) V(V4,0) V(V1,2)\ void SPC_DSP::run( int clocks_remain ) { require( clocks_remain > 0 ); - + int const phase = m.phase; m.phase = (phase + clocks_remain) & 31; switch ( phase ) { loop: - + #define PHASE( n ) if ( n && !--clocks_remain ) break; case n: GEN_DSP_TIMING #undef PHASE - + if ( --clocks_remain ) goto loop; } @@ -837,19 +837,20 @@ void SPC_DSP::init( void* ram_64k ) stereo_switch = 0xffff; take_spc_snapshot = 0; spc_snapshot_callback = 0; + rom_enabled = 0; #ifndef NDEBUG // be sure this sign-extends assert( (int16_t) 0x8000 == -0x8000 ); - + // be sure right shift preserves sign assert( (-1 >> 1) == -1 ); - + // check clamp macro int i; i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF ); i = -0x8001; CLAMP16( i ); assert( i == -0x8000 ); - + blargg_verify_byte_order(); #endif } @@ -857,13 +858,13 @@ void SPC_DSP::init( void* ram_64k ) void SPC_DSP::soft_reset_common() { require( m.ram ); // init() must have been called already - + m.noise = 0x4000; m.echo_hist_pos = m.echo_hist; m.every_other_sample = 1; m.echo_offset = 0; m.phase = 0; - + init_counter(); for (int i = 0; i < voice_count; i++) @@ -880,7 +881,7 @@ void SPC_DSP::load( uint8_t const regs [register_count] ) { memcpy( m.regs, regs, sizeof m.regs ); memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count ); - + // Internal state for ( int i = voice_count; --i >= 0; ) { @@ -892,7 +893,7 @@ void SPC_DSP::load( uint8_t const regs [register_count] ) m.new_kon = REG(kon); m.t_dir = REG(dir); m.t_esa = REG(esa); - + soft_reset_common(); } @@ -945,18 +946,18 @@ void SPC_State_Copier::extra() void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy ) { SPC_State_Copier copier( io, copy ); - + // DSP registers copier.copy( m.regs, register_count ); - + // Internal state - + // Voices int i; for ( i = 0; i < voice_count; i++ ) { voice_t* v = &m.voices [i]; - + // BRR buffer int i; for ( i = 0; i < brr_buf_size; i++ ) @@ -965,7 +966,7 @@ void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy ) SPC_COPY( int16_t, s ); v->buf [i] = v->buf [i + brr_buf_size] = s; } - + SPC_COPY( uint16_t, v->interp_pos ); SPC_COPY( uint16_t, v->brr_addr ); SPC_COPY( uint16_t, v->env ); @@ -979,10 +980,10 @@ void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy ) v->env_mode = (enum env_mode_t) m; } SPC_COPY( uint8_t, v->t_envx_out ); - + copier.extra(); } - + // Echo history for ( i = 0; i < echo_hist_size; i++ ) { @@ -996,28 +997,28 @@ void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy ) } m.echo_hist_pos = m.echo_hist; memcpy( &m.echo_hist [echo_hist_size], m.echo_hist, echo_hist_size * sizeof m.echo_hist [0] ); - + // Misc SPC_COPY( uint8_t, m.every_other_sample ); SPC_COPY( uint8_t, m.kon ); - + SPC_COPY( uint16_t, m.noise ); SPC_COPY( uint16_t, m.counter ); SPC_COPY( uint16_t, m.echo_offset ); SPC_COPY( uint16_t, m.echo_length ); SPC_COPY( uint8_t, m.phase ); - + SPC_COPY( uint8_t, m.new_kon ); SPC_COPY( uint8_t, m.endx_buf ); SPC_COPY( uint8_t, m.envx_buf ); SPC_COPY( uint8_t, m.outx_buf ); - + SPC_COPY( uint8_t, m.t_pmon ); SPC_COPY( uint8_t, m.t_non ); SPC_COPY( uint8_t, m.t_eon ); SPC_COPY( uint8_t, m.t_dir ); SPC_COPY( uint8_t, m.t_koff ); - + SPC_COPY( uint16_t, m.t_brr_next_addr ); SPC_COPY( uint8_t, m.t_adsr0 ); SPC_COPY( uint8_t, m.t_brr_header ); @@ -1025,20 +1026,20 @@ void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy ) SPC_COPY( uint8_t, m.t_srcn ); SPC_COPY( uint8_t, m.t_esa ); SPC_COPY( uint8_t, m.t_echo_enabled ); - + SPC_COPY( int16_t, m.t_main_out [0] ); SPC_COPY( int16_t, m.t_main_out [1] ); SPC_COPY( int16_t, m.t_echo_out [0] ); SPC_COPY( int16_t, m.t_echo_out [1] ); SPC_COPY( int16_t, m.t_echo_in [0] ); SPC_COPY( int16_t, m.t_echo_in [1] ); - + SPC_COPY( uint16_t, m.t_dir_addr ); SPC_COPY( uint16_t, m.t_pitch ); SPC_COPY( int16_t, m.t_output ); SPC_COPY( uint16_t, m.t_echo_ptr ); SPC_COPY( uint8_t, m.t_looped ); - + copier.extra(); } #endif diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp index b50bb631..638c400d 100644 --- a/apu/bapu/smp/smp.hpp +++ b/apu/bapu/smp/smp.hpp @@ -22,6 +22,7 @@ public: #else void load_state(uint8 **); void save_state(uint8 **); + void save_spc (uint8 *); #endif SMP(); ~SMP(); diff --git a/apu/bapu/smp/smp_state.cpp b/apu/bapu/smp/smp_state.cpp index 2e590e69..7c5179c4 100644 --- a/apu/bapu/smp/smp_state.cpp +++ b/apu/bapu/smp/smp_state.cpp @@ -1,9 +1,75 @@ #include "snes/snes.hpp" +#include + +typedef struct spc_file { + uint8 header[33]; + uint8 idtag[3]; + uint8 version_minor; + + uint8 pc_low; + uint8 pc_high; + uint8 a; + uint8 x; + uint8 y; + uint8 psw; + uint8 sp; + uint8 unused_a[2]; + + uint8 id666[210]; + + uint8 apuram[65536]; + uint8 dsp_registers[128]; + uint8 unused_b[64]; + uint8 iplrom[64]; +} spc_file; namespace SNES { #include "dsp/blargg_endian.h" +void SMP::save_spc (uint8 *block) { + spc_file out; + + const char *header = "SNES-SPC700 Sound File Data v0.30"; + memcpy (out.header, header, 33); + out.idtag[0] = out.idtag[1] = 26; + out.idtag[2] = 27; + out.version_minor = 30; + + out.pc_low = regs.pc & 0xff; + out.pc_high = (regs.pc >> 8) & 0xff; + out.a = regs.a; + out.x = regs.x; + out.y = regs.y; + out.psw = (uint8) ((unsigned) regs.p); + out.sp = regs.sp; + out.unused_a[0] = out.unused_a[1] = 0; + + memset (out.id666, 0, 210); + memcpy (out.apuram, apuram, 65536); + + for (int i = 0xf2; i <= 0xf7; i++) + { + out.apuram[i] = mmio_read (i); + } + + for (int i = 0xfd; i <= 0xff; i++) + { + out.apuram[i] = mmio_read (i); + } + + for (int i = 0; i < 128; i++) + { + out.dsp_registers[i] = dsp.read (i); + } + + memset (out.unused_b, 0, 64); + memcpy (out.iplrom, iplrom, 64); + + memcpy (block, &out, 66048); +} + + void SMP::save_state(uint8 **block) { uint8 *ptr = *block; memcpy(ptr, apuram, 64 * 1024); @@ -116,4 +182,4 @@ void SMP::load_state(uint8 **block) { *block = ptr; } -} +} /* namespace SNES */ diff --git a/snapshot.cpp b/snapshot.cpp index d07c430b..e6cd879a 100644 --- a/snapshot.cpp +++ b/snapshot.cpp @@ -2275,29 +2275,3 @@ static void UnfreezeStructFromCopy (void *sbase, FreezeData *fields, int num_fie } } } - -bool8 S9xSPCDump (const char *filename) -{ - /* TODO: No SPC dumping in byuu SMP */ - /* - FILE *fs; - uint8 buf[SNES_SPC::spc_file_size]; - size_t ignore; - - fs = fopen(filename, "wb"); - if (!fs) - return (FALSE); - - S9xSetSoundMute(TRUE); - - spc_core->init_header(buf); - spc_core->save_spc(buf); - - ignore = fwrite(buf, SNES_SPC::spc_file_size, 1, fs); - - fclose(fs); - - S9xSetSoundMute(FALSE); - */ - return (TRUE); -} diff --git a/snapshot.h b/snapshot.h index d55b8b7e..1cb4bd8c 100644 --- a/snapshot.h +++ b/snapshot.h @@ -195,6 +195,5 @@ bool8 S9xFreezeGame (const char *); bool8 S9xUnfreezeGame (const char *); void S9xFreezeToStream (STREAM); int S9xUnfreezeFromStream (STREAM); -bool8 S9xSPCDump (const char *); #endif From 7be597615970032662c95fbc3c2ed1806d058b05 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 27 Jun 2011 10:23:58 -0500 Subject: [PATCH 13/33] Remove unneeded echo buffer hacks. --- apu/bapu/dsp/SPC_DSP.cpp | 14 ++--------- apu/bapu/dsp/SPC_DSP.h | 52 +++++++++++++++++++--------------------- 2 files changed, 27 insertions(+), 39 deletions(-) diff --git a/apu/bapu/dsp/SPC_DSP.cpp b/apu/bapu/dsp/SPC_DSP.cpp index e3719203..aa036c09 100644 --- a/apu/bapu/dsp/SPC_DSP.cpp +++ b/apu/bapu/dsp/SPC_DSP.cpp @@ -605,11 +605,7 @@ VOICE_CLOCK(V9_V6_V3) { voice_V9(v); voice_V6(v+1); voice_V3(v+2); } inline void SPC_DSP::echo_read( int ch ) { - int s; - if ( m.t_echo_ptr >= 0xffc0 && rom_enabled ) - s = GET_LE16SA( &hi_ram [m.t_echo_ptr + ch * 2 - 0xffc0] ); - else - s = GET_LE16SA( ECHO_PTR( ch ) ); + int s = GET_LE16SA( ECHO_PTR( ch ) ); // second copy simplifies wrap-around handling ECHO_FIR( 0 ) [ch] = ECHO_FIR( 8 ) [ch] = s >> 1; } @@ -720,12 +716,7 @@ ECHO_CLOCK( 28 ) inline void SPC_DSP::echo_write( int ch ) { if ( !(m.t_echo_enabled & 0x20) ) - { - if ( m.t_echo_ptr >= 0xffc0 && rom_enabled ) - SET_LE16A( &hi_ram [m.t_echo_ptr + ch * 2 - 0xffc0], m.t_echo_out [ch] ); - else - SET_LE16A( ECHO_PTR( ch ), m.t_echo_out [ch] ); - } + SET_LE16A( ECHO_PTR( ch ), m.t_echo_out [ch] ); m.t_echo_out [ch] = 0; } @@ -837,7 +828,6 @@ void SPC_DSP::init( void* ram_64k ) stereo_switch = 0xffff; take_spc_snapshot = 0; spc_snapshot_callback = 0; - rom_enabled = 0; #ifndef NDEBUG // be sure this sign-extends diff --git a/apu/bapu/dsp/SPC_DSP.h b/apu/bapu/dsp/SPC_DSP.h index 61d05ab5..ca61cc95 100644 --- a/apu/bapu/dsp/SPC_DSP.h +++ b/apu/bapu/dsp/SPC_DSP.h @@ -11,7 +11,7 @@ extern "C" { typedef void (*dsp_copy_func_t)( unsigned char** io, void* state, s class SPC_DSP { public: typedef BOOST::uint8_t uint8_t; - + // Setup // Initializes DSP and has it use the 64K RAM provided @@ -34,7 +34,7 @@ public: // Emulates pressing reset switch on SNES void soft_reset(); - + // Reads/writes DSP registers. For accuracy, you must first call run() // to catch the DSP up to present. int read ( int addr ) const; @@ -43,7 +43,7 @@ public: // Runs DSP for specified number of clocks (~1024000 per second). Every 32 clocks // a pair of samples is be generated. void run( int clock_count ); - + // Sound control // Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events). @@ -52,7 +52,7 @@ public: void mute_voices( int mask ); // State - + // Resets DSP and uses supplied values to initialize registers enum { register_count = 128 }; void load( uint8_t const regs [register_count] ); @@ -69,8 +69,6 @@ public: int stereo_switch; int take_spc_snapshot; - int rom_enabled; // mirror - uint8_t *rom, *hi_ram; // mirror void (*spc_snapshot_callback) (void); void set_spc_snapshot_callback( void (*callback) (void) ); @@ -110,12 +108,12 @@ public: void disable_surround( bool ) { } // not supported public: BLARGG_DISABLE_NOTHROW - + typedef BOOST::int8_t int8_t; typedef BOOST::int16_t int16_t; - + enum { echo_hist_size = 8 }; - + enum env_mode_t { env_release, env_attack, env_decay, env_sustain }; enum { brr_buf_size = 12 }; struct voice_t @@ -136,15 +134,15 @@ public: }; private: enum { brr_block_size = 9 }; - + struct state_t { uint8_t regs [register_count]; - + // Echo history keeps most recent 8 samples (twice the size to simplify wrap handling) int echo_hist [echo_hist_size * 2] [2]; int (*echo_hist_pos) [2]; // &echo_hist [0 to 7] - + int every_other_sample; // toggles every sample int kon; // KON value when last checked int noise; @@ -153,22 +151,22 @@ private: int echo_length; // number of bytes that echo_offset will stop at int phase; // next clock cycle to run (0-31) bool kon_check; // set when a new KON occurs - + // Hidden registers also written to when main register is written to int new_kon; uint8_t endx_buf; uint8_t envx_buf; uint8_t outx_buf; - + // Temporary state between clocks - + // read once per sample int t_pmon; int t_non; int t_eon; int t_dir; int t_koff; - + // read a few clocks ahead then used int t_brr_next_addr; int t_adsr0; @@ -177,21 +175,21 @@ private: int t_srcn; int t_esa; int t_echo_enabled; - + // internal state that is recalculated every sample int t_dir_addr; int t_pitch; int t_output; int t_looped; int t_echo_ptr; - + // left/right sums int t_main_out [2]; int t_echo_out [2]; int t_echo_in [2]; - + voice_t voices [voice_count]; - + // non-emulation state uint8_t* ram; // 64K shared RAM between DSP and SMP int mute_mask; @@ -201,11 +199,11 @@ private: sample_t extra [extra_size]; }; state_t m; - + void init_counter(); void run_counters(); unsigned read_counter( int rate ); - + int interpolate( voice_t const* v ); void run_envelope( voice_t* const v ); void decode_brr( voice_t* v ); @@ -244,7 +242,7 @@ private: void echo_28(); void echo_29(); void echo_30(); - + void soft_reset_common(); }; @@ -261,22 +259,22 @@ inline int SPC_DSP::read( int addr ) const inline void SPC_DSP::write( int addr, int data ) { assert( (unsigned) addr < register_count ); - + m.regs [addr] = (uint8_t) data; switch ( addr & 0x0F ) { case v_envx: m.envx_buf = (uint8_t) data; break; - + case v_outx: m.outx_buf = (uint8_t) data; break; - + case 0x0C: if ( addr == r_kon ) m.new_kon = (uint8_t) data; - + if ( addr == r_endx ) // always cleared, regardless of data written { m.endx_buf = 0; From 02a3b83c87f7b792371ce57cc56d74ee85382a45 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 27 Jun 2011 13:20:26 -0500 Subject: [PATCH 14/33] Fix landing buffer size claim. --- apu/apu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index 11bb5c7d..8072c19e 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -367,7 +367,7 @@ void S9xFinalizeSamples (void) else spc::sound_in_sync = FALSE; - SNES::dsp.spc_dsp.set_output((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + SNES::dsp.spc_dsp.set_output((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size); } void S9xLandSamples (void) @@ -453,7 +453,7 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms) else spc::resampler->resize(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)); - SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size); UpdatePlaybackRate(); From 91e69af029d2e8d213f92119ec986bb70d18468a Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 27 Jun 2011 15:41:17 -0500 Subject: [PATCH 15/33] Loosen SMP<->DSP synchronization. --- apu/apu.cpp | 1 + apu/bapu/dsp/sdsp.hpp | 10 ++++++++++ apu/bapu/smp/core.cpp | 4 ++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index 8072c19e..d9c214b9 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -560,6 +560,7 @@ void S9xAPUExecute (void) void S9xAPUEndScanline (void) { S9xAPUExecute(); + SNES::dsp.synchronize(); if (SNES::dsp.spc_dsp.sample_count() >= APU_MINIMUM_SAMPLE_BLOCK || !spc::sound_in_sync) S9xLandSamples(); diff --git a/apu/bapu/dsp/sdsp.hpp b/apu/bapu/dsp/sdsp.hpp index 83d51eb5..baf1e88b 100644 --- a/apu/bapu/dsp/sdsp.hpp +++ b/apu/bapu/dsp/sdsp.hpp @@ -1,12 +1,22 @@ #include "SPC_DSP.h" +#include class DSP : public Processor { public: inline uint8 read(uint8 addr) { + synchronize (); return spc_dsp.read(addr); } + inline void synchronize (void) { + if (clock) { + spc_dsp.run (clock); + clock = 0; + } + } + inline void write(uint8 addr, uint8 data) { + synchronize (); spc_dsp.write(addr, data); } diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp index df4076c1..b5266cec 100644 --- a/apu/bapu/smp/core.cpp +++ b/apu/bapu/smp/core.cpp @@ -9,7 +9,7 @@ void SMP::tick() { synchronize_dsp(); #else clock++; - dsp.spc_dsp.run(1); + dsp.clock++; #endif } @@ -82,7 +82,7 @@ void SMP::op_step() { synchronize_dsp(); #else clock += cycle_count_table[opcode]; - dsp.spc_dsp.run(cycle_count_table[opcode]); + dsp.clock += cycle_count_table[opcode]; #endif From e3788c39e49876fd639e83b5de6efef01c5b9588 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 27 Jun 2011 16:28:45 -0500 Subject: [PATCH 16/33] Zero clock at appropriate times. --- apu/bapu/dsp/sdsp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apu/bapu/dsp/sdsp.cpp b/apu/bapu/dsp/sdsp.cpp index ef2c48da..0fe01476 100644 --- a/apu/bapu/dsp/sdsp.cpp +++ b/apu/bapu/dsp/sdsp.cpp @@ -11,11 +11,13 @@ void DSP::power() { spc_dsp.init(smp.apuram); spc_dsp.reset(); + clock = 0; } void DSP::reset() { spc_dsp.soft_reset(); + clock = 0; } static void from_dsp_to_state (uint8 **buf, void *var, size_t size) @@ -42,6 +44,7 @@ void DSP::load_state (uint8 **ptr) DSP::DSP() { + clock = 0; } } From 63b0a6d45e58e87aaec62bf531ee0ef34f1d0ad7 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 4 Jul 2011 17:33:09 -0500 Subject: [PATCH 17/33] Add DSP clock remainder to save state. --- apu/apu.cpp | 4 ++++ apu/bapu/smp/smp.hpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index d9c214b9..aeb116e9 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -617,6 +617,8 @@ void S9xAPUSaveState (uint8 *block) ptr += sizeof(int32); SNES::set_le32(ptr, spc::remainder); ptr += sizeof(int32); + SNES::set_le32(ptr, SNES::dsp.clock); + ptr += sizeof(int32); memcpy (ptr, SNES::cpu.registers, 4); } @@ -633,6 +635,8 @@ void S9xAPULoadState (uint8 *block) ptr += sizeof(int32); spc::remainder = SNES::get_le32(ptr); ptr += sizeof(int32); + SNES::dsp.clock = SNES::get_le32(ptr); + ptr += sizeof(int32); memcpy (SNES::cpu.registers, ptr, 4); } diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp index 638c400d..1bf75129 100644 --- a/apu/bapu/smp/smp.hpp +++ b/apu/bapu/smp/smp.hpp @@ -93,7 +93,7 @@ public: Timer<128> timer1; Timer< 16> timer2; - void tick(); + alwaysinline void tick(); alwaysinline void op_io(); debugvirtual alwaysinline uint8 op_read(uint16 addr); debugvirtual alwaysinline void op_write(uint16 addr, uint8 data); From 2b5a54b401668d46d20fd69411800c5790a1f892 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Tue, 5 Jul 2011 06:23:24 -0500 Subject: [PATCH 18/33] Inline ticks. This should fix speed issues. --- apu/bapu/smp/smp.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp index 1bf75129..cb57f334 100644 --- a/apu/bapu/smp/smp.hpp +++ b/apu/bapu/smp/smp.hpp @@ -85,15 +85,15 @@ public: uint8 stage2_ticks; uint8 stage3_ticks; - void tick(); - void tick(unsigned clocks); + inline void tick(); + inline void tick(unsigned clocks); }; Timer<128> timer0; Timer<128> timer1; Timer< 16> timer2; - alwaysinline void tick(); + inline void tick(); alwaysinline void op_io(); debugvirtual alwaysinline uint8 op_read(uint16 addr); debugvirtual alwaysinline void op_write(uint16 addr, uint8 data); From baa4de371356b57d87cc3fafcf9c615022ad1a62 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Tue, 5 Jul 2011 14:05:36 -0500 Subject: [PATCH 19/33] Save a few more mmapped registers to SPC files. Fix key-on trigger. --- apu/apu.cpp | 3 +-- apu/bapu/smp/smp_state.cpp | 2 +- gtk/src/gtk_file.cpp | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index aeb116e9..c41634c8 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -492,8 +492,6 @@ bool8 S9xInitAPU (void) spc::shrink_buffer = NULL; spc::resampler = NULL; - SNES::dsp.spc_dsp.set_spc_snapshot_callback(SPCSnapshotCallback); - return (TRUE); } @@ -590,6 +588,7 @@ void S9xResetAPU (void) SNES::smp.power (); SNES::dsp.power (); SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + SNES::dsp.spc_dsp.set_spc_snapshot_callback(SPCSnapshotCallback); spc::resampler->clear(); } diff --git a/apu/bapu/smp/smp_state.cpp b/apu/bapu/smp/smp_state.cpp index 7c5179c4..e3b9d446 100644 --- a/apu/bapu/smp/smp_state.cpp +++ b/apu/bapu/smp/smp_state.cpp @@ -48,7 +48,7 @@ void SMP::save_spc (uint8 *block) { memset (out.id666, 0, 210); memcpy (out.apuram, apuram, 65536); - for (int i = 0xf2; i <= 0xf7; i++) + for (int i = 0xf2; i <= 0xf9; i++) { out.apuram[i] = mmio_read (i); } diff --git a/gtk/src/gtk_file.cpp b/gtk/src/gtk_file.cpp index 0610d439..2182e39e 100644 --- a/gtk/src/gtk_file.cpp +++ b/gtk/src/gtk_file.cpp @@ -157,6 +157,7 @@ S9xGetDirectory (enum s9x_getdirtype dirtype) case SCREENSHOT_DIR: case SPC_DIR: sprintf (path, "%s", gui_config->export_directory); + break; default: path[0] = '\0'; From 4fdc7af7da2712d4ef7280d56d39207f6a67fd5f Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 6 Jul 2011 09:20:31 -0500 Subject: [PATCH 20/33] Set the output buffer after loading state so the first set of samples isn't excluded. --- apu/apu.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apu/apu.cpp b/apu/apu.cpp index c41634c8..795dd2f7 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -630,6 +630,8 @@ void S9xAPULoadState (uint8 *block) SNES::smp.load_state (&ptr); SNES::dsp.load_state (&ptr); + SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + spc::reference_time = SNES::get_le32(ptr); ptr += sizeof(int32); spc::remainder = SNES::get_le32(ptr); From 4668ae585004a312aeb3a4e0ad953d4c5f9058ee Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 7 Sep 2011 11:46:52 -0500 Subject: [PATCH 21/33] Fix save state error. --- apu/apu.cpp | 7 ++----- apu/bapu/smp/core.cpp | 1 - apu/bapu/smp/smp.hpp | 2 ++ apu/bapu/smp/smp_state.cpp | 16 ++++++++++++++-- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index 795dd2f7..237f3939 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -625,13 +625,9 @@ void S9xAPULoadState (uint8 *block) { uint8 *ptr = block; - S9xResetAPU(); - SNES::smp.load_state (&ptr); SNES::dsp.load_state (&ptr); - SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); - spc::reference_time = SNES::get_le32(ptr); ptr += sizeof(int32); spc::remainder = SNES::get_le32(ptr); @@ -655,7 +651,8 @@ bool8 S9xSPCDump (const char *filename) SNES::smp.save_spc (buf); - ignore = fwrite(buf, SPC_FILE_SIZE, 1, fs); + if ((ignore = fwrite(buf, SPC_FILE_SIZE, 1, fs)) <= 0) + fprintf (stderr, "Couldn't write file %s.\n", filename); fclose(fs); diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp index b5266cec..5664da36 100644 --- a/apu/bapu/smp/core.cpp +++ b/apu/bapu/smp/core.cpp @@ -44,7 +44,6 @@ void SMP::op_step() { #define op_writeaddr(addr, data) op_write(addr, data) #define op_readstack() op_read(0x0100 | ++regs.sp) #define op_writestack(data) op_write(0x0100 | regs.sp--, data) - static unsigned rd, wr, dp, sp, ya, bit; #if defined(CYCLE_ACCURATE) diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp index cb57f334..9d7a9ea7 100644 --- a/apu/bapu/smp/smp.hpp +++ b/apu/bapu/smp/smp.hpp @@ -50,6 +50,8 @@ public: unsigned opcode_number; unsigned opcode_cycle; + unsigned rd, wr, dp, sp, ya, bit; + struct Regs { uint16 pc; uint8 sp; diff --git a/apu/bapu/smp/smp_state.cpp b/apu/bapu/smp/smp_state.cpp index e3b9d446..adefdacb 100644 --- a/apu/bapu/smp/smp_state.cpp +++ b/apu/bapu/smp/smp_state.cpp @@ -118,11 +118,17 @@ void SMP::save_state(uint8 **block) { INT32(timer2.enable); INT32(timer2.target); - INT32(timer2.stage1_ticks); INT32(timer2.stage2_ticks); INT32(timer2.stage3_ticks); + INT32(rd); + INT32(wr); + INT32(dp); + INT32(sp); + INT32(ya); + INT32(bit); + *block = ptr; } @@ -174,11 +180,17 @@ void SMP::load_state(uint8 **block) { INT32(timer2.enable); INT32(timer2.target); - INT32(timer2.stage1_ticks); INT32(timer2.stage2_ticks); INT32(timer2.stage3_ticks); + INT32(rd); + INT32(wr); + INT32(dp); + INT32(sp); + INT32(ya); + INT32(bit); + *block = ptr; } From a19395ee3c2ffd2e742952e37f4624017036c19e Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 14 Sep 2011 12:54:51 -0500 Subject: [PATCH 22/33] Start converting some opcodes to cycle-based. --- apu/bapu/smp/core.cpp | 13 + apu/bapu/smp/core/opcycle_misc.cpp | 420 ++++++++--------------------- apu/bapu/smp/core/opcycle_rmw.cpp | 90 ++----- apu/bapu/smp/smp.hpp | 2 + 4 files changed, 147 insertions(+), 378 deletions(-) diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp index 5664da36..7e9c4a95 100644 --- a/apu/bapu/smp/core.cpp +++ b/apu/bapu/smp/core.cpp @@ -13,12 +13,25 @@ void SMP::tick() { #endif } +void SMP::tick(unsigned clocks) { + timer0.tick(clocks); + timer1.tick(clocks); + timer2.tick(clocks); + + clock += clocks; + dsp.clock += clocks; +} + void SMP::op_io() { #if defined(CYCLE_ACCURATE) tick(); #endif } +void SMP::op_io(unsigned clocks) { + tick(clocks); +} + uint8 SMP::op_read(uint16 addr) { #if defined(CYCLE_ACCURATE) tick(); diff --git a/apu/bapu/smp/core/opcycle_misc.cpp b/apu/bapu/smp/core/opcycle_misc.cpp index 963f9fc2..5fe164f1 100644 --- a/apu/bapu/smp/core/opcycle_misc.cpp +++ b/apu/bapu/smp/core/opcycle_misc.cpp @@ -1,188 +1,109 @@ case 0x00: { - switch(opcode_cycle++) { - case 1: - op_io(); - opcode_cycle = 0; - break; - } + op_io(); + opcode_cycle = 0; break; } case 0xef: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - regs.pc--; - opcode_cycle = 0; - break; - } + op_io(2); + regs.pc--; + opcode_cycle = 0; break; } case 0xff: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - regs.pc--; - opcode_cycle = 0; - break; - } + op_io(2); + regs.pc--; + opcode_cycle = 0; break; } case 0x9f: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_io(); - break; - case 4: - op_io(); - regs.a = (regs.a >> 4) | (regs.a << 4); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } + op_io(4); + regs.a = (regs.a >> 4) | (regs.a << 4); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; break; } case 0xdf: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - if(regs.p.c || (regs.a) > 0x99) { - regs.a += 0x60; - regs.p.c = 1; - } - if(regs.p.h || (regs.a & 15) > 0x09) { - regs.a += 0x06; - } - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; + op_io(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); + opcode_cycle = 0; break; } case 0xbe: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - if(!regs.p.c || (regs.a) > 0x99) { - regs.a -= 0x60; - regs.p.c = 0; - } - if(!regs.p.h || (regs.a & 15) > 0x09) { - regs.a -= 0x06; - } - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; + op_io(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); + opcode_cycle = 0; break; } case 0x60: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.p.c = 0; - opcode_cycle = 0; - break; - } + op_io(); + regs.p.c = 0; + opcode_cycle = 0; break; } case 0x20: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.p.p = 0; - opcode_cycle = 0; - break; - } + op_io(); + regs.p.p = 0; + opcode_cycle = 0; break; } case 0x80: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.p.c = 1; - opcode_cycle = 0; - break; - } + op_io(); + regs.p.c = 1; + opcode_cycle = 0; break; } case 0x40: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.p.p = 1; - opcode_cycle = 0; - break; - } + op_io(); + regs.p.p = 1; + opcode_cycle = 0; break; } case 0xe0: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.p.v = 0; - regs.p.h = 0; - opcode_cycle = 0; - break; - } + op_io(); + regs.p.v = 0; + regs.p.h = 0; + opcode_cycle = 0; break; } case 0xed: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - regs.p.c = !regs.p.c; - opcode_cycle = 0; - break; - } + op_io(2); + regs.p.c = !regs.p.c; + opcode_cycle = 0; break; } case 0xa0: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - regs.p.i = 1; - opcode_cycle = 0; - break; - } + op_io(2); + regs.p.i = 1; + opcode_cycle = 0; break; } @@ -473,224 +394,93 @@ case 0xf2: { } case 0x2d: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_writestack(regs.a); - opcode_cycle = 0; - break; - } + op_io(2); + op_writestack(regs.a); + opcode_cycle = 0; break; } case 0x4d: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_writestack(regs.x); - opcode_cycle = 0; - break; - } + op_io(2); + op_writestack(regs.x); + opcode_cycle = 0; break; } case 0x6d: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_writestack(regs.y); - opcode_cycle = 0; - break; - } + op_io(2); + op_writestack(regs.y); + opcode_cycle = 0; break; } case 0x0d: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_writestack(regs.p); - opcode_cycle = 0; - break; - } + op_io(2); + op_writestack(regs.p); + opcode_cycle = 0; break; } case 0xae: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - regs.a = op_readstack(); - opcode_cycle = 0; - break; - } + op_io(2); + regs.a = op_readstack(); + opcode_cycle = 0; break; } case 0xce: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - regs.x = op_readstack(); - opcode_cycle = 0; - break; - } + op_io(2); + regs.x = op_readstack(); + opcode_cycle = 0; break; } case 0xee: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - regs.y = op_readstack(); - opcode_cycle = 0; - break; - } + op_io(2); + regs.y = op_readstack(); + opcode_cycle = 0; break; } case 0x8e: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - regs.p = op_readstack(); - opcode_cycle = 0; - break; - } + op_io(2); + regs.p = op_readstack(); + opcode_cycle = 0; break; } case 0xcf: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_io(); - break; - case 7: - op_io(); - break; - case 8: - op_io(); - ya = regs.y * regs.a; - regs.a = ya; - regs.y = ya >> 8; - //result is set based on y (high-byte) only - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); - opcode_cycle = 0; - break; - } + op_io(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); + opcode_cycle = 0; break; } case 0x9e: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_io(); - break; - case 7: - op_io(); - break; - case 8: - op_io(); - break; - case 9: - op_io(); - break; - case 10: - op_io(); - break; - case 11: - op_io(); - ya = regs.ya; - //overflow set if quotient >= 256 - regs.p.v = !!(regs.y >= regs.x); - regs.p.h = !!((regs.y & 15) >= (regs.x & 15)); - if(regs.y < (regs.x << 1)) { - //if quotient is <= 511 (will fit into 9-bit result) - regs.a = ya / regs.x; - regs.y = ya % regs.x; - } else { - //otherwise, the quotient won't fit into regs.p.v + regs.a - //this emulates the odd behavior of the S-SMP 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); - opcode_cycle = 0; - break; + op_io(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 S-SMP 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); + opcode_cycle = 0; break; } diff --git a/apu/bapu/smp/core/opcycle_rmw.cpp b/apu/bapu/smp/core/opcycle_rmw.cpp index eca62f02..4677628e 100644 --- a/apu/bapu/smp/core/opcycle_rmw.cpp +++ b/apu/bapu/smp/core/opcycle_rmw.cpp @@ -1,99 +1,63 @@ case 0xbc: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = op_inc(regs.a); - opcode_cycle = 0; - break; - } + op_io(); + regs.a = op_inc(regs.a); + opcode_cycle = 0; break; } case 0x3d: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.x = op_inc(regs.x); - opcode_cycle = 0; - break; - } + op_io(); + regs.x = op_inc(regs.x); + opcode_cycle = 0; break; } case 0xfc: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.y = op_inc(regs.y); - opcode_cycle = 0; - break; - } + op_io(); + regs.y = op_inc(regs.y); + opcode_cycle = 0; break; } case 0x9c: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = op_dec(regs.a); - opcode_cycle = 0; - break; - } + op_io(); + regs.a = op_dec(regs.a); + opcode_cycle = 0; break; } case 0x1d: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.x = op_dec(regs.x); - opcode_cycle = 0; - break; - } + op_io(); + regs.x = op_dec(regs.x); + opcode_cycle = 0; break; } case 0xdc: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.y = op_dec(regs.y); - opcode_cycle = 0; - break; - } + op_io(); + regs.y = op_dec(regs.y); + opcode_cycle = 0; break; } case 0x1c: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = op_asl(regs.a); - opcode_cycle = 0; - break; - } + op_io(); + regs.a = op_asl(regs.a); + opcode_cycle = 0; break; } case 0x5c: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = op_lsr(regs.a); - opcode_cycle = 0; - break; - } + op_io(); + regs.a = op_lsr(regs.a); + opcode_cycle = 0; break; } case 0x3c: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = op_rol(regs.a); - opcode_cycle = 0; - break; - } + op_io(); + regs.a = op_rol(regs.a); + opcode_cycle = 0; break; } diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp index 9d7a9ea7..0a17cb8f 100644 --- a/apu/bapu/smp/smp.hpp +++ b/apu/bapu/smp/smp.hpp @@ -96,7 +96,9 @@ public: Timer< 16> timer2; inline void tick(); + inline void tick(unsigned clocks); alwaysinline void op_io(); + alwaysinline void op_io(unsigned clocks); debugvirtual alwaysinline uint8 op_read(uint16 addr); debugvirtual alwaysinline void op_write(uint16 addr, uint8 data); debugvirtual alwaysinline void op_step(); From a50f6989efce45a9401ef3c4a808fabd47f513e8 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 14 Sep 2011 15:45:18 -0500 Subject: [PATCH 23/33] Finish converting opcycle_misc/opcycle_rmw to pseudo-cycle. --- apu/bapu/smp/core/opcycle_misc.cpp | 301 +++++------------- apu/bapu/smp/core/opcycle_rmw.cpp | 488 ++++++++--------------------- 2 files changed, 219 insertions(+), 570 deletions(-) diff --git a/apu/bapu/smp/core/opcycle_misc.cpp b/apu/bapu/smp/core/opcycle_misc.cpp index 5fe164f1..43a72305 100644 --- a/apu/bapu/smp/core/opcycle_misc.cpp +++ b/apu/bapu/smp/core/opcycle_misc.cpp @@ -108,288 +108,153 @@ case 0xa0: { } case 0xc0: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - regs.p.i = 0; - opcode_cycle = 0; - break; - } + op_io(2); + regs.p.i = 0; + opcode_cycle = 0; break; } case 0x02: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x01; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x01; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x12: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x01; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x01; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x22: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x02; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x02; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x32: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x02; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x02; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x42: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x04; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x04; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x52: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x04; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x04; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x62: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x08; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x08; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x72: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x08; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x08; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x82: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x10; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x10; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x92: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x10; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x10; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0xa2: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x20; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x20; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0xb2: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x20; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x20; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0xc2: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x40; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x40; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0xd2: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x40; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x40; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0xe2: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x80; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x80; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0xf2: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x80; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x80; + op_writedp(dp, rd); + opcode_cycle = 0; break; } diff --git a/apu/bapu/smp/core/opcycle_rmw.cpp b/apu/bapu/smp/core/opcycle_rmw.cpp index 4677628e..fcacfc71 100644 --- a/apu/bapu/smp/core/opcycle_rmw.cpp +++ b/apu/bapu/smp/core/opcycle_rmw.cpp @@ -73,442 +73,226 @@ case 0x7c: { } case 0xab: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd = op_inc(rd); - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_inc(rd); + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x8b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd = op_dec(rd); - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_dec(rd); + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x0b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd = op_asl(rd); - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_asl(rd); + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x4b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd = op_lsr(rd); - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_lsr(rd); + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x2b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd = op_rol(rd); - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_rol(rd); + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x6b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd = op_ror(rd); - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_ror(rd); + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0xbb: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - break; - case 4: - rd = op_inc(rd); - op_writedp(dp + regs.x, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_inc(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; break; } case 0x9b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - break; - case 4: - rd = op_dec(rd); - op_writedp(dp + regs.x, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_dec(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; break; } case 0x1b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - break; - case 4: - rd = op_asl(rd); - op_writedp(dp + regs.x, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_asl(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; break; } case 0x5b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - break; - case 4: - rd = op_lsr(rd); - op_writedp(dp + regs.x, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_lsr(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; break; } case 0x3b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - break; - case 4: - rd = op_rol(rd); - op_writedp(dp + regs.x, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_rol(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; break; } case 0x7b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - break; - case 4: - rd = op_ror(rd); - op_writedp(dp + regs.x, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_ror(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; break; } case 0xac: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - break; - case 4: - rd = op_inc(rd); - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_inc(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; break; } case 0x8c: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - break; - case 4: - rd = op_dec(rd); - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_dec(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; break; } case 0x0c: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - break; - case 4: - rd = op_asl(rd); - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_asl(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; break; } case 0x4c: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - break; - case 4: - rd = op_lsr(rd); - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_lsr(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; break; } case 0x2c: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - break; - case 4: - rd = op_rol(rd); - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_rol(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; break; } case 0x6c: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - break; - case 4: - rd = op_ror(rd); - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_ror(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; break; } case 0x0e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.p.n = !!((regs.a - rd) & 0x80); - regs.p.z = ((regs.a - rd) == 0); - break; - case 4: - op_readaddr(dp); - break; - case 5: - op_writeaddr(dp, rd | regs.a); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + op_readaddr(dp); + op_writeaddr(dp, rd | regs.a); + opcode_cycle = 0; break; } case 0x4e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.p.n = !!((regs.a - rd) & 0x80); - regs.p.z = ((regs.a - rd) == 0); - break; - case 4: - op_readaddr(dp); - break; - case 5: - op_writeaddr(dp, rd &~ regs.a); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + op_readaddr(dp); + op_writeaddr(dp, rd &~ regs.a); + opcode_cycle = 0; break; } case 0x3a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - rd++; - break; - case 3: - op_writedp(dp++, rd); - break; - case 4: - rd += op_readdp(dp) << 8; - break; - case 5: - op_writedp(dp, rd >> 8); - regs.p.n = !!(rd & 0x8000); - regs.p.z = (rd == 0); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd++; + op_writedp(dp++, rd); + rd += op_readdp(dp) << 8; + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + opcode_cycle = 0; break; } case 0x1a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - rd--; - break; - case 3: - op_writedp(dp++, rd); - break; - case 4: - rd += op_readdp(dp) << 8; - break; - case 5: - op_writedp(dp, rd >> 8); - regs.p.n = !!(rd & 0x8000); - regs.p.z = (rd == 0); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd--; + op_writedp(dp++, rd); + rd += op_readdp(dp) << 8; + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + opcode_cycle = 0; break; } From d6e2f1c8e6c0916be016958dc8bd483e5be60e35 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 14 Sep 2011 16:20:14 -0500 Subject: [PATCH 24/33] More pseudo-cycle modifications. --- apu/bapu/smp/core/opcycle_pc.cpp | 1519 ++++++------------------ apu/bapu/smp/core/opcycle_read.cpp | 1734 ++++++++-------------------- 2 files changed, 863 insertions(+), 2390 deletions(-) diff --git a/apu/bapu/smp/core/opcycle_pc.cpp b/apu/bapu/smp/core/opcycle_pc.cpp index 1cdda647..ed808a6b 100644 --- a/apu/bapu/smp/core/opcycle_pc.cpp +++ b/apu/bapu/smp/core/opcycle_pc.cpp @@ -1,1347 +1,588 @@ case 0x2f: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(0){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + if(0){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xf0: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(!regs.p.z){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + if(!regs.p.z){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xd0: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(regs.p.z){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + if(regs.p.z){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xb0: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(!regs.p.c){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + if(!regs.p.c){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x90: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(regs.p.c){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + if(regs.p.c){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x70: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(!regs.p.v){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + if(!regs.p.v){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x50: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(regs.p.v){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + if(regs.p.v){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x30: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(!regs.p.n){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + if(!regs.p.n){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x10: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(regs.p.n){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + if(regs.p.n){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x03: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x01) != 0x01){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x01) != 0x01){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x13: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x01) == 0x01){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x01) == 0x01){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x23: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x02) != 0x02){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x02) != 0x02){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x33: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x02) == 0x02){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x02) == 0x02){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x43: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x04) != 0x04){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x04) != 0x04){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x53: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x04) == 0x04){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x04) == 0x04){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x63: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x08) != 0x08){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x08) != 0x08){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x73: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x08) == 0x08){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x08) == 0x08){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x83: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x10) != 0x10){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x10) != 0x10){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x93: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x10) == 0x10){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x10) == 0x10){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xa3: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x20) != 0x20){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x20) != 0x20){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xb3: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x20) == 0x20){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x20) == 0x20){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xc3: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x40) != 0x40){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x40) != 0x40){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xd3: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x40) == 0x40){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x40) == 0x40){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xe3: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x80) != 0x80){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x80) != 0x80){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xf3: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x80) == 0x80){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x80) == 0x80){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x2e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if(regs.a == sp){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if(regs.a == sp){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xde: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp + regs.x); - break; - case 4: - rd = op_readpc(); - break; - case 5: - op_io(); - if(regs.a == sp){ opcode_cycle = 0; break; } - break; - case 6: - op_io(); - break; - case 7: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + sp = op_readdp(dp + regs.x); + rd = op_readpc(); + op_io(); + if(regs.a == sp){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x6e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - wr = op_readdp(dp); - break; - case 3: - op_writedp(dp, --wr); - break; - case 4: - rd = op_readpc(); - if(wr == 0x00){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + wr = op_readdp(dp); + op_writedp(dp, --wr); + rd = op_readpc(); + if(wr == 0x00){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xfe: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - op_io(); - regs.y--; - break; - case 3: - op_io(); - if(regs.y == 0x00){ opcode_cycle = 0; break; } - break; - case 4: - op_io(); - break; - case 5: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + op_io(); + regs.y--; + op_io(); + if(regs.y == 0x00){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x5f: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - rd |= op_readpc() << 8; - regs.pc = rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + rd |= op_readpc() << 8; + regs.pc = rd; + opcode_cycle = 0; break; } case 0x1f: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - dp += regs.x; - break; - case 4: - rd = op_readaddr(dp); - break; - case 5: - rd |= op_readaddr(dp + 1) << 8; - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + dp += regs.x; + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + regs.pc = rd; + opcode_cycle = 0; break; } case 0x3f: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - rd |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + rd |= op_readpc() << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x4f: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - op_io(); - break; - case 4: - op_writestack(regs.pc >> 8); - break; - case 5: - op_writestack(regs.pc); - regs.pc = 0xff00 | rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + op_io(2); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = 0xff00 | rd; + opcode_cycle = 0; break; } case 0x01: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (0 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (0 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x11: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (1 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (1 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x21: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (2 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (2 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x31: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (3 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (3 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x41: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (4 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (4 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x51: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (5 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (5 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x61: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (6 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (6 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x71: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (7 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (7 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x81: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (8 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (8 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x91: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (9 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (9 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0xa1: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (10 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (10 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0xb1: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (11 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (11 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0xc1: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (12 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (12 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0xd1: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (13 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (13 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0xe1: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (14 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (14 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0xf1: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (15 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (15 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x0f: { - switch(opcode_cycle++) { - case 1: - rd = op_readaddr(0xffde); - break; - case 2: - rd |= op_readaddr(0xffdf) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_writestack(regs.pc >> 8); - break; - case 6: - op_writestack(regs.pc); - break; - case 7: - op_writestack(regs.p); - regs.pc = rd; - regs.p.b = 1; - regs.p.i = 0; - opcode_cycle = 0; - break; - } + rd = op_readaddr(0xffde); + rd |= op_readaddr(0xffdf) << 8; + op_io(2); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + op_writestack(regs.p); + regs.pc = rd; + regs.p.b = 1; + regs.p.i = 0; + opcode_cycle = 0; break; } case 0x6f: { - switch(opcode_cycle++) { - case 1: - rd = op_readstack(); - break; - case 2: - rd |= op_readstack() << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - regs.pc = rd; - opcode_cycle = 0; - break; - } + rd = op_readstack(); + rd |= op_readstack() << 8; + op_io(2); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x7f: { - switch(opcode_cycle++) { - case 1: - regs.p = op_readstack(); - break; - case 2: - rd = op_readstack(); - break; - case 3: - rd |= op_readstack() << 8; - break; - case 4: - op_io(); - break; - case 5: - op_io(); - regs.pc = rd; - opcode_cycle = 0; - break; - } + regs.p = op_readstack(); + rd = op_readstack(); + rd |= op_readstack() << 8; + op_io(2); + regs.pc = rd; + opcode_cycle = 0; break; } diff --git a/apu/bapu/smp/core/opcycle_read.cpp b/apu/bapu/smp/core/opcycle_read.cpp index 6c19f3a9..3eb1cd77 100644 --- a/apu/bapu/smp/core/opcycle_read.cpp +++ b/apu/bapu/smp/core/opcycle_read.cpp @@ -1,1599 +1,831 @@ case 0x88: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; break; } case 0x28: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; break; } case 0x68: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; break; } case 0xc8: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.x = op_cmp(regs.x, rd); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + regs.x = op_cmp(regs.x, rd); + opcode_cycle = 0; break; } case 0xad: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.y = op_cmp(regs.y, rd); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + regs.y = op_cmp(regs.y, rd); + opcode_cycle = 0; break; } case 0x48: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; break; } case 0x08: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; break; } case 0xa8: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; break; } case 0x86: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.x); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.x); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; break; } case 0x26: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.x); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.x); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; break; } case 0x66: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.x); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.x); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; break; } case 0x46: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.x); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.x); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; break; } case 0x06: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.x); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.x); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; break; } case 0xa6: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.x); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.x); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; break; } case 0x84: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; break; } case 0x24: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; break; } case 0x64: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; break; } case 0x3e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.x = op_cmp(regs.x, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + regs.x = op_cmp(regs.x, rd); + opcode_cycle = 0; break; } case 0x7e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.y = op_cmp(regs.y, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + regs.y = op_cmp(regs.y, rd); + opcode_cycle = 0; break; } case 0x44: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; break; } case 0x04: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; break; } case 0xa4: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; break; } case 0x94: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; break; } case 0x34: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; break; } case 0x74: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; break; } case 0x54: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; break; } case 0x14: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; break; } case 0xb4: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; break; } case 0x85: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; break; } case 0x25: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; break; } case 0x65: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; break; } case 0x1e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.x = op_cmp(regs.x, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.x = op_cmp(regs.x, rd); + opcode_cycle = 0; break; } case 0x5e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.y = op_cmp(regs.y, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.y = op_cmp(regs.y, rd); + opcode_cycle = 0; break; } case 0x45: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; break; } case 0x05: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; break; } case 0xa5: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; break; } case 0x95: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.x); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; break; } case 0x96: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.y); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; break; } case 0x35: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.x); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; break; } case 0x36: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.y); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; break; } case 0x75: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.x); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; break; } case 0x76: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.y); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; break; } case 0x55: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.x); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; break; } case 0x56: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.y); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; break; } case 0x15: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.x); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; break; } case 0x16: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.y); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; break; } case 0xb5: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.x); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; break; } case 0xb6: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.y); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; break; } case 0x87: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; break; } case 0x27: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; break; } case 0x67: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; break; } case 0x47: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; break; } case 0x07: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; break; } case 0xa7: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; break; } case 0x97: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp + regs.y); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; break; } case 0x37: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp + regs.y); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; break; } case 0x77: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp + regs.y); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; break; } case 0x57: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp + regs.y); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; break; } case 0x17: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp + regs.y); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; break; } case 0xb7: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp + regs.y); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; break; } case 0x99: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.y); - break; - case 3: - wr = op_readdp(regs.x); - wr = op_adc(wr, rd); - break; - case 4: - (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_adc(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; break; } case 0x39: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.y); - break; - case 3: - wr = op_readdp(regs.x); - wr = op_and(wr, rd); - break; - case 4: - (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_and(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; break; } case 0x79: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.y); - break; - case 3: - wr = op_readdp(regs.x); - wr = op_cmp(wr, rd); - break; - case 4: - (0) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_cmp(wr, rd); + (0) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; break; } case 0x59: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.y); - break; - case 3: - wr = op_readdp(regs.x); - wr = op_eor(wr, rd); - break; - case 4: - (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_eor(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; break; } case 0x19: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.y); - break; - case 3: - wr = op_readdp(regs.x); - wr = op_or(wr, rd); - break; - case 4: - (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_or(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; break; } case 0xb9: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.y); - break; - case 3: - wr = op_readdp(regs.x); - wr = op_sbc(wr, rd); - break; - case 4: - (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_sbc(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; break; } case 0x89: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - wr = op_readdp(dp); - break; - case 5: - wr = op_adc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x29: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - wr = op_readdp(dp); - break; - case 5: - wr = op_and(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x69: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - wr = op_readdp(dp); - break; - case 5: - wr = op_cmp(wr, rd); - (0) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x49: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - wr = op_readdp(dp); - break; - case 5: - wr = op_eor(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x09: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - wr = op_readdp(dp); - break; - case 5: - wr = op_or(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0xa9: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - wr = op_readdp(dp); - break; - case 5: - wr = op_sbc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x98: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - wr = op_readdp(dp); - break; - case 4: - wr = op_adc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x38: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - wr = op_readdp(dp); - break; - case 4: - wr = op_and(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x78: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - wr = op_readdp(dp); - break; - case 4: - wr = op_cmp(wr, rd); - (0) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x58: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - wr = op_readdp(dp); - break; - case 4: - wr = op_eor(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x18: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - wr = op_readdp(dp); - break; - case 4: - wr = op_or(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0xb8: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - wr = op_readdp(dp); - break; - case 4: - wr = op_sbc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x7a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - op_io(); - break; - case 4: - rd |= op_readdp(dp + 1) << 8; - regs.ya = op_addw(regs.ya, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + op_io(); + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_addw(regs.ya, rd); + opcode_cycle = 0; break; } case 0x9a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - op_io(); - break; - case 4: - rd |= op_readdp(dp + 1) << 8; - regs.ya = op_subw(regs.ya, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + op_io(); + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_subw(regs.ya, rd); + opcode_cycle = 0; break; } case 0x5a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= op_readdp(dp + 1) << 8; - op_cmpw(regs.ya, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd |= op_readdp(dp + 1) << 8; + op_cmpw(regs.ya, rd); + opcode_cycle = 0; break; } case 0x4a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - regs.p.c = regs.p.c & !!(rd & (1 << bit)); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !!(rd & (1 << bit)); + opcode_cycle = 0; break; } case 0x6a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - regs.p.c = regs.p.c & !(rd & (1 << bit)); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !(rd & (1 << bit)); + opcode_cycle = 0; break; } case 0x8a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - break; - case 4: - op_io(); - regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); + opcode_cycle = 0; break; } case 0xea: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - rd ^= (1 << bit); - break; - case 4: - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + rd ^= (1 << bit); + op_writeaddr(dp, rd); + opcode_cycle = 0; break; } case 0x0a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - break; - case 4: - op_io(); - regs.p.c = regs.p.c | !!(rd & (1 << bit)); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c | !!(rd & (1 << bit)); + opcode_cycle = 0; break; } case 0x2a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - break; - case 4: - op_io(); - regs.p.c = regs.p.c | !(rd & (1 << bit)); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c | !(rd & (1 << bit)); + opcode_cycle = 0; break; } From 6b9d6caf54d36b580ba832f0e53d862147e2a80e Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 14 Sep 2011 17:02:26 -0500 Subject: [PATCH 25/33] Remove extra case bracker from 2-cycle MOV opcodes. --- apu/bapu/smp/core/opcycle_mov.cpp | 116 +++++++++++------------------- 1 file changed, 40 insertions(+), 76 deletions(-) diff --git a/apu/bapu/smp/core/opcycle_mov.cpp b/apu/bapu/smp/core/opcycle_mov.cpp index 635c7ca5..9096bc25 100644 --- a/apu/bapu/smp/core/opcycle_mov.cpp +++ b/apu/bapu/smp/core/opcycle_mov.cpp @@ -1,112 +1,76 @@ case 0x7d: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = regs.x; - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } + op_io(); + regs.a = regs.x; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; break; } case 0xdd: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = regs.y; - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } + op_io(); + regs.a = regs.y; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; break; } case 0x5d: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.x = regs.a; - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); - opcode_cycle = 0; - break; - } + op_io(); + regs.x = regs.a; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; break; } case 0xfd: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.y = regs.a; - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); - opcode_cycle = 0; - break; - } + op_io(); + regs.y = regs.a; + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; break; } case 0x9d: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.x = regs.sp; - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); - opcode_cycle = 0; - break; - } + op_io(); + regs.x = regs.sp; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; break; } case 0xbd: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.sp = regs.x; - opcode_cycle = 0; - break; - } + op_io(); + regs.sp = regs.x; + opcode_cycle = 0; break; } case 0xe8: { - switch(opcode_cycle++) { - case 1: - regs.a = op_readpc(); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } + regs.a = op_readpc(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; break; } case 0xcd: { - switch(opcode_cycle++) { - case 1: - regs.x = op_readpc(); - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); - opcode_cycle = 0; - break; - } + regs.x = op_readpc(); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; break; } case 0x8d: { - switch(opcode_cycle++) { - case 1: - regs.y = op_readpc(); - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); - opcode_cycle = 0; - break; - } + regs.y = op_readpc(); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; break; } From b97e56d64d2e2dabf1829d256078a181563eb539 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 14 Sep 2011 17:12:03 -0500 Subject: [PATCH 26/33] Group some MOV opcode cycles together. --- apu/bapu/smp/core/opcycle_mov.cpp | 128 +++++++++--------------------- 1 file changed, 36 insertions(+), 92 deletions(-) diff --git a/apu/bapu/smp/core/opcycle_mov.cpp b/apu/bapu/smp/core/opcycle_mov.cpp index 9096bc25..b358b66c 100644 --- a/apu/bapu/smp/core/opcycle_mov.cpp +++ b/apu/bapu/smp/core/opcycle_mov.cpp @@ -96,8 +96,6 @@ case 0xbf: { break; case 2: regs.a = op_readdp(regs.x++); - break; - case 3: op_io(); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -156,11 +154,9 @@ case 0xf4: { switch(opcode_cycle++) { case 1: sp = op_readpc(); - break; - case 2: op_io(); break; - case 3: + case 2: regs.a = op_readdp(sp + regs.x); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -174,11 +170,9 @@ case 0xf9: { switch(opcode_cycle++) { case 1: sp = op_readpc(); - break; - case 2: op_io(); break; - case 3: + case 2: regs.x = op_readdp(sp + regs.y); regs.p.n = !!(regs.x & 0x80); regs.p.z = (regs.x == 0); @@ -192,11 +186,9 @@ case 0xfb: { switch(opcode_cycle++) { case 1: sp = op_readpc(); - break; - case 2: op_io(); break; - case 3: + case 2: regs.y = op_readdp(sp + regs.x); regs.p.n = !!(regs.y & 0x80); regs.p.z = (regs.y == 0); @@ -228,11 +220,9 @@ case 0xe9: { switch(opcode_cycle++) { case 1: sp = op_readpc(); - break; - case 2: sp |= op_readpc() << 8; break; - case 3: + case 2: regs.x = op_readaddr(sp); regs.p.n = !!(regs.x & 0x80); regs.p.z = (regs.x == 0); @@ -246,11 +236,9 @@ case 0xec: { switch(opcode_cycle++) { case 1: sp = op_readpc(); - break; - case 2: sp |= op_readpc() << 8; break; - case 3: + case 2: regs.y = op_readaddr(sp); regs.p.n = !!(regs.y & 0x80); regs.p.z = (regs.y == 0); @@ -264,14 +252,10 @@ case 0xf5: { switch(opcode_cycle++) { case 1: sp = op_readpc(); - break; - case 2: sp |= op_readpc() << 8; - break; - case 3: op_io(); break; - case 4: + case 2: regs.a = op_readaddr(sp + regs.x); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -285,14 +269,10 @@ case 0xf6: { switch(opcode_cycle++) { case 1: sp = op_readpc(); - break; - case 2: sp |= op_readpc() << 8; - break; - case 3: op_io(); break; - case 4: + case 2: regs.a = op_readaddr(sp + regs.y); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -306,17 +286,15 @@ case 0xe7: { switch(opcode_cycle++) { case 1: dp = op_readpc() + regs.x; - break; - case 2: op_io(); break; - case 3: + case 2: sp = op_readdp(dp); break; - case 4: + case 3: sp |= op_readdp(dp + 1) << 8; break; - case 5: + case 4: regs.a = op_readaddr(sp); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -330,17 +308,15 @@ case 0xf7: { switch(opcode_cycle++) { case 1: dp = op_readpc(); - break; - case 2: op_io(); break; - case 3: + case 2: sp = op_readdp(dp); break; - case 4: + case 3: sp |= op_readdp(dp + 1) << 8; break; - case 5: + case 4: regs.a = op_readaddr(sp + regs.y); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -373,14 +349,12 @@ case 0x8f: { switch(opcode_cycle++) { case 1: rd = op_readpc(); - break; - case 2: dp = op_readpc(); break; - case 3: + case 2: op_readdp(dp); break; - case 4: + case 3: op_writedp(dp, rd); opcode_cycle = 0; break; @@ -407,12 +381,8 @@ case 0xc6: { case 0xaf: { switch(opcode_cycle++) { case 1: - op_io(); - break; + op_io(2); case 2: - op_io(); - break; - case 3: op_writedp(regs.x++, regs.a); opcode_cycle = 0; break; @@ -472,15 +442,13 @@ case 0xd4: { switch(opcode_cycle++) { case 1: dp = op_readpc(); - break; - case 2: op_io(); dp += regs.x; break; - case 3: + case 2: op_readdp(dp); break; - case 4: + case 3: op_writedp(dp, regs.a); opcode_cycle = 0; break; @@ -492,15 +460,13 @@ case 0xd9: { switch(opcode_cycle++) { case 1: dp = op_readpc(); - break; - case 2: op_io(); dp += regs.y; break; - case 3: + case 2: op_readdp(dp); break; - case 4: + case 3: op_writedp(dp, regs.x); opcode_cycle = 0; break; @@ -512,15 +478,13 @@ case 0xdb: { switch(opcode_cycle++) { case 1: dp = op_readpc(); - break; - case 2: op_io(); dp += regs.x; break; - case 3: + case 2: op_readdp(dp); break; - case 4: + case 3: op_writedp(dp, regs.y); opcode_cycle = 0; break; @@ -589,18 +553,14 @@ case 0xd5: { switch(opcode_cycle++) { case 1: dp = op_readpc(); - break; - case 2: dp |= op_readpc() << 8; - break; - case 3: op_io(); dp += regs.x; break; - case 4: + case 2: op_readaddr(dp); break; - case 5: + case 3: op_writeaddr(dp, regs.a); opcode_cycle = 0; break; @@ -612,18 +572,14 @@ case 0xd6: { switch(opcode_cycle++) { case 1: dp = op_readpc(); - break; - case 2: dp |= op_readpc() << 8; - break; - case 3: op_io(); dp += regs.y; break; - case 4: + case 2: op_readaddr(dp); break; - case 5: + case 3: op_writeaddr(dp, regs.a); opcode_cycle = 0; break; @@ -635,21 +591,19 @@ case 0xc7: { switch(opcode_cycle++) { case 1: sp = op_readpc(); - break; - case 2: op_io(); sp += regs.x; break; - case 3: + case 2: dp = op_readdp(sp); break; - case 4: + case 3: dp |= op_readdp(sp + 1) << 8; break; - case 5: + case 4: op_readaddr(dp); break; - case 6: + case 5: op_writeaddr(dp, regs.a); opcode_cycle = 0; break; @@ -667,15 +621,13 @@ case 0xd7: { break; case 3: dp |= op_readdp(sp + 1) << 8; - break; - case 4: op_io(); dp += regs.y; break; - case 5: + case 4: op_readaddr(dp); break; - case 6: + case 5: op_writeaddr(dp, regs.a); opcode_cycle = 0; break; @@ -690,11 +642,9 @@ case 0xba: { break; case 2: regs.a = op_readdp(sp); - break; - case 3: op_io(); break; - case 4: + case 3: regs.y = op_readdp(sp + 1); regs.p.n = !!(regs.ya & 0x8000); regs.p.z = (regs.ya == 0); @@ -727,11 +677,9 @@ case 0xaa: { switch(opcode_cycle++) { case 1: sp = op_readpc(); - break; - case 2: sp |= op_readpc() << 8; break; - case 3: + case 2: bit = sp >> 13; sp &= 0x1fff; rd = op_readaddr(sp); @@ -746,21 +694,17 @@ case 0xca: { switch(opcode_cycle++) { case 1: dp = op_readpc(); - break; - case 2: dp |= op_readpc() << 8; break; - case 3: + case 2: bit = dp >> 13; dp &= 0x1fff; rd = op_readaddr(dp); if(regs.p.c)rd |= (1 << bit); else rd &= ~(1 << bit); - break; - case 4: op_io(); break; - case 5: + case 3: op_writeaddr(dp, rd); opcode_cycle = 0; break; From 70159fd93999b22b495d18c9f2f5ee8f39cbaecd Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 19 Sep 2011 15:15:19 -0500 Subject: [PATCH 27/33] Pair opcode read with first instruction cycle. Remove opcode_cycle switching from unneeded cases. --- apu/bapu/smp/core.cpp | 7 +- apu/bapu/smp/core/opcycle_misc.cpp | 40 ----------- apu/bapu/smp/core/opcycle_mov.cpp | 81 ++++++++++----------- apu/bapu/smp/core/opcycle_pc.cpp | 110 ++++++++--------------------- apu/bapu/smp/core/opcycle_read.cpp | 87 ----------------------- apu/bapu/smp/core/opcycle_rmw.cpp | 40 +---------- 6 files changed, 71 insertions(+), 294 deletions(-) diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp index 7e9c4a95..a7a70072 100644 --- a/apu/bapu/smp/core.cpp +++ b/apu/bapu/smp/core.cpp @@ -60,10 +60,11 @@ void SMP::op_step() { #if defined(CYCLE_ACCURATE) - if(opcode_cycle == 0) { + if(opcode_cycle == 0) opcode_number = op_readpc(); - opcode_cycle++; - } else switch(opcode_number) { +// opcode_cycle++; + + switch(opcode_number) { #include "core/opcycle_misc.cpp" #include "core/opcycle_mov.cpp" #include "core/opcycle_pc.cpp" diff --git a/apu/bapu/smp/core/opcycle_misc.cpp b/apu/bapu/smp/core/opcycle_misc.cpp index 43a72305..d266ef92 100644 --- a/apu/bapu/smp/core/opcycle_misc.cpp +++ b/apu/bapu/smp/core/opcycle_misc.cpp @@ -1,20 +1,17 @@ case 0x00: { op_io(); - opcode_cycle = 0; break; } case 0xef: { op_io(2); regs.pc--; - opcode_cycle = 0; break; } case 0xff: { op_io(2); regs.pc--; - opcode_cycle = 0; break; } @@ -23,7 +20,6 @@ case 0x9f: { regs.a = (regs.a >> 4) | (regs.a << 4); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); - opcode_cycle = 0; break; } @@ -38,7 +34,6 @@ case 0xdf: { } regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); - opcode_cycle = 0; break; } @@ -53,35 +48,30 @@ case 0xbe: { } regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); - opcode_cycle = 0; break; } case 0x60: { op_io(); regs.p.c = 0; - opcode_cycle = 0; break; } case 0x20: { op_io(); regs.p.p = 0; - opcode_cycle = 0; break; } case 0x80: { op_io(); regs.p.c = 1; - opcode_cycle = 0; break; } case 0x40: { op_io(); regs.p.p = 1; - opcode_cycle = 0; break; } @@ -89,28 +79,24 @@ case 0xe0: { op_io(); regs.p.v = 0; regs.p.h = 0; - opcode_cycle = 0; break; } case 0xed: { op_io(2); regs.p.c = !regs.p.c; - opcode_cycle = 0; break; } case 0xa0: { op_io(2); regs.p.i = 1; - opcode_cycle = 0; break; } case 0xc0: { op_io(2); regs.p.i = 0; - opcode_cycle = 0; break; } @@ -119,7 +105,6 @@ case 0x02: { rd = op_readdp(dp); rd |= 0x01; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -128,7 +113,6 @@ case 0x12: { rd = op_readdp(dp); rd &= ~0x01; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -137,7 +121,6 @@ case 0x22: { rd = op_readdp(dp); rd |= 0x02; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -146,7 +129,6 @@ case 0x32: { rd = op_readdp(dp); rd &= ~0x02; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -155,7 +137,6 @@ case 0x42: { rd = op_readdp(dp); rd |= 0x04; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -164,7 +145,6 @@ case 0x52: { rd = op_readdp(dp); rd &= ~0x04; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -173,7 +153,6 @@ case 0x62: { rd = op_readdp(dp); rd |= 0x08; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -182,7 +161,6 @@ case 0x72: { rd = op_readdp(dp); rd &= ~0x08; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -191,7 +169,6 @@ case 0x82: { rd = op_readdp(dp); rd |= 0x10; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -200,7 +177,6 @@ case 0x92: { rd = op_readdp(dp); rd &= ~0x10; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -209,7 +185,6 @@ case 0xa2: { rd = op_readdp(dp); rd |= 0x20; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -218,7 +193,6 @@ case 0xb2: { rd = op_readdp(dp); rd &= ~0x20; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -227,7 +201,6 @@ case 0xc2: { rd = op_readdp(dp); rd |= 0x40; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -236,7 +209,6 @@ case 0xd2: { rd = op_readdp(dp); rd &= ~0x40; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -245,7 +217,6 @@ case 0xe2: { rd = op_readdp(dp); rd |= 0x80; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -254,63 +225,54 @@ case 0xf2: { rd = op_readdp(dp); rd &= ~0x80; op_writedp(dp, rd); - opcode_cycle = 0; break; } case 0x2d: { op_io(2); op_writestack(regs.a); - opcode_cycle = 0; break; } case 0x4d: { op_io(2); op_writestack(regs.x); - opcode_cycle = 0; break; } case 0x6d: { op_io(2); op_writestack(regs.y); - opcode_cycle = 0; break; } case 0x0d: { op_io(2); op_writestack(regs.p); - opcode_cycle = 0; break; } case 0xae: { op_io(2); regs.a = op_readstack(); - opcode_cycle = 0; break; } case 0xce: { op_io(2); regs.x = op_readstack(); - opcode_cycle = 0; break; } case 0xee: { op_io(2); regs.y = op_readstack(); - opcode_cycle = 0; break; } case 0x8e: { op_io(2); regs.p = op_readstack(); - opcode_cycle = 0; break; } @@ -322,7 +284,6 @@ case 0xcf: { //result is set based on y (high-byte) only regs.p.n = !!(regs.y & 0x80); regs.p.z = (regs.y == 0); - opcode_cycle = 0; break; } @@ -345,7 +306,6 @@ case 0x9e: { //result is set based on a (quotient) only regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); - opcode_cycle = 0; break; } diff --git a/apu/bapu/smp/core/opcycle_mov.cpp b/apu/bapu/smp/core/opcycle_mov.cpp index b358b66c..fd44ad29 100644 --- a/apu/bapu/smp/core/opcycle_mov.cpp +++ b/apu/bapu/smp/core/opcycle_mov.cpp @@ -3,7 +3,6 @@ case 0x7d: { regs.a = regs.x; regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); - opcode_cycle = 0; break; } @@ -12,7 +11,6 @@ case 0xdd: { regs.a = regs.y; regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); - opcode_cycle = 0; break; } @@ -21,7 +19,6 @@ case 0x5d: { regs.x = regs.a; regs.p.n = !!(regs.x & 0x80); regs.p.z = (regs.x == 0); - opcode_cycle = 0; break; } @@ -30,7 +27,6 @@ case 0xfd: { regs.y = regs.a; regs.p.n = !!(regs.y & 0x80); regs.p.z = (regs.y == 0); - opcode_cycle = 0; break; } @@ -39,14 +35,12 @@ case 0x9d: { regs.x = regs.sp; regs.p.n = !!(regs.x & 0x80); regs.p.z = (regs.x == 0); - opcode_cycle = 0; break; } case 0xbd: { op_io(); regs.sp = regs.x; - opcode_cycle = 0; break; } @@ -54,7 +48,6 @@ case 0xe8: { regs.a = op_readpc(); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); - opcode_cycle = 0; break; } @@ -62,7 +55,6 @@ case 0xcd: { regs.x = op_readpc(); regs.p.n = !!(regs.x & 0x80); regs.p.z = (regs.x == 0); - opcode_cycle = 0; break; } @@ -70,12 +62,11 @@ case 0x8d: { regs.y = op_readpc(); regs.p.n = !!(regs.y & 0x80); regs.p.z = (regs.y == 0); - opcode_cycle = 0; break; } case 0xe6: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: op_io(); break; @@ -90,7 +81,7 @@ case 0xe6: { } case 0xbf: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: op_io(); break; @@ -106,7 +97,7 @@ case 0xbf: { } case 0xe4: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); break; @@ -121,7 +112,7 @@ case 0xe4: { } case 0xf8: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); break; @@ -136,7 +127,7 @@ case 0xf8: { } case 0xeb: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); break; @@ -151,7 +142,7 @@ case 0xeb: { } case 0xf4: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); op_io(); @@ -167,7 +158,7 @@ case 0xf4: { } case 0xf9: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); op_io(); @@ -183,7 +174,7 @@ case 0xf9: { } case 0xfb: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); op_io(); @@ -199,7 +190,7 @@ case 0xfb: { } case 0xe5: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); break; @@ -217,7 +208,7 @@ case 0xe5: { } case 0xe9: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); sp |= op_readpc() << 8; @@ -233,7 +224,7 @@ case 0xe9: { } case 0xec: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); sp |= op_readpc() << 8; @@ -249,7 +240,7 @@ case 0xec: { } case 0xf5: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); sp |= op_readpc() << 8; @@ -266,7 +257,7 @@ case 0xf5: { } case 0xf6: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); sp |= op_readpc() << 8; @@ -283,7 +274,7 @@ case 0xf6: { } case 0xe7: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc() + regs.x; op_io(); @@ -305,7 +296,7 @@ case 0xe7: { } case 0xf7: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); op_io(); @@ -327,7 +318,7 @@ case 0xf7: { } case 0xfa: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); break; @@ -346,7 +337,7 @@ case 0xfa: { } case 0x8f: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: rd = op_readpc(); dp = op_readpc(); @@ -363,7 +354,7 @@ case 0x8f: { } case 0xc6: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: op_io(); break; @@ -379,7 +370,7 @@ case 0xc6: { } case 0xaf: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: op_io(2); case 2: @@ -391,7 +382,7 @@ case 0xaf: { } case 0xc4: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); break; @@ -407,7 +398,7 @@ case 0xc4: { } case 0xd8: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); break; @@ -423,7 +414,7 @@ case 0xd8: { } case 0xcb: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); break; @@ -439,7 +430,7 @@ case 0xcb: { } case 0xd4: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); op_io(); @@ -457,7 +448,7 @@ case 0xd4: { } case 0xd9: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); op_io(); @@ -475,7 +466,7 @@ case 0xd9: { } case 0xdb: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); op_io(); @@ -493,7 +484,7 @@ case 0xdb: { } case 0xc5: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); break; @@ -512,7 +503,7 @@ case 0xc5: { } case 0xc9: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); break; @@ -531,7 +522,7 @@ case 0xc9: { } case 0xcc: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); break; @@ -550,7 +541,7 @@ case 0xcc: { } case 0xd5: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); dp |= op_readpc() << 8; @@ -569,7 +560,7 @@ case 0xd5: { } case 0xd6: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); dp |= op_readpc() << 8; @@ -588,7 +579,7 @@ case 0xd6: { } case 0xc7: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); op_io(); @@ -612,7 +603,7 @@ case 0xc7: { } case 0xd7: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); break; @@ -636,7 +627,7 @@ case 0xd7: { } case 0xba: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); break; @@ -655,7 +646,7 @@ case 0xba: { } case 0xda: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); break; @@ -674,7 +665,7 @@ case 0xda: { } case 0xaa: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); sp |= op_readpc() << 8; @@ -691,7 +682,7 @@ case 0xaa: { } case 0xca: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); dp |= op_readpc() << 8; diff --git a/apu/bapu/smp/core/opcycle_pc.cpp b/apu/bapu/smp/core/opcycle_pc.cpp index ed808a6b..022179d1 100644 --- a/apu/bapu/smp/core/opcycle_pc.cpp +++ b/apu/bapu/smp/core/opcycle_pc.cpp @@ -1,81 +1,72 @@ case 0x2f: { rd = op_readpc(); - if(0){ opcode_cycle = 0; break; } + if(0){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } case 0xf0: { rd = op_readpc(); - if(!regs.p.z){ opcode_cycle = 0; break; } + if(!regs.p.z){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } case 0xd0: { rd = op_readpc(); - if(regs.p.z){ opcode_cycle = 0; break; } + if(regs.p.z){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } case 0xb0: { rd = op_readpc(); - if(!regs.p.c){ opcode_cycle = 0; break; } + if(!regs.p.c){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } case 0x90: { rd = op_readpc(); - if(regs.p.c){ opcode_cycle = 0; break; } + if(regs.p.c){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } case 0x70: { rd = op_readpc(); - if(!regs.p.v){ opcode_cycle = 0; break; } + if(!regs.p.v){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } case 0x50: { rd = op_readpc(); - if(regs.p.v){ opcode_cycle = 0; break; } + if(regs.p.v){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } case 0x30: { rd = op_readpc(); - if(!regs.p.n){ opcode_cycle = 0; break; } + if(!regs.p.n){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } case 0x10: { rd = op_readpc(); - if(regs.p.n){ opcode_cycle = 0; break; } + if(regs.p.n){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -84,10 +75,9 @@ case 0x03: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x01) != 0x01){ opcode_cycle = 0; break; } + if((sp & 0x01) != 0x01){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -96,10 +86,9 @@ case 0x13: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x01) == 0x01){ opcode_cycle = 0; break; } + if((sp & 0x01) == 0x01){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -108,10 +97,9 @@ case 0x23: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x02) != 0x02){ opcode_cycle = 0; break; } + if((sp & 0x02) != 0x02){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -120,10 +108,9 @@ case 0x33: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x02) == 0x02){ opcode_cycle = 0; break; } + if((sp & 0x02) == 0x02){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -132,10 +119,9 @@ case 0x43: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x04) != 0x04){ opcode_cycle = 0; break; } + if((sp & 0x04) != 0x04){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -144,10 +130,9 @@ case 0x53: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x04) == 0x04){ opcode_cycle = 0; break; } + if((sp & 0x04) == 0x04){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -156,10 +141,9 @@ case 0x63: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x08) != 0x08){ opcode_cycle = 0; break; } + if((sp & 0x08) != 0x08){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -168,10 +152,9 @@ case 0x73: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x08) == 0x08){ opcode_cycle = 0; break; } + if((sp & 0x08) == 0x08){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -180,10 +163,9 @@ case 0x83: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x10) != 0x10){ opcode_cycle = 0; break; } + if((sp & 0x10) != 0x10){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -192,10 +174,9 @@ case 0x93: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x10) == 0x10){ opcode_cycle = 0; break; } + if((sp & 0x10) == 0x10){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -204,10 +185,9 @@ case 0xa3: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x20) != 0x20){ opcode_cycle = 0; break; } + if((sp & 0x20) != 0x20){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -216,10 +196,9 @@ case 0xb3: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x20) == 0x20){ opcode_cycle = 0; break; } + if((sp & 0x20) == 0x20){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -228,10 +207,9 @@ case 0xc3: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x40) != 0x40){ opcode_cycle = 0; break; } + if((sp & 0x40) != 0x40){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -240,10 +218,9 @@ case 0xd3: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x40) == 0x40){ opcode_cycle = 0; break; } + if((sp & 0x40) == 0x40){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -252,10 +229,9 @@ case 0xe3: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x80) != 0x80){ opcode_cycle = 0; break; } + if((sp & 0x80) != 0x80){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -264,10 +240,9 @@ case 0xf3: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x80) == 0x80){ opcode_cycle = 0; break; } + if((sp & 0x80) == 0x80){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -276,10 +251,9 @@ case 0x2e: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if(regs.a == sp){ opcode_cycle = 0; break; } + if(regs.a == sp){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -289,10 +263,9 @@ case 0xde: { sp = op_readdp(dp + regs.x); rd = op_readpc(); op_io(); - if(regs.a == sp){ opcode_cycle = 0; break; } + if(regs.a == sp){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -301,10 +274,9 @@ case 0x6e: { wr = op_readdp(dp); op_writedp(dp, --wr); rd = op_readpc(); - if(wr == 0x00){ opcode_cycle = 0; break; } + if(wr == 0x00){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -313,10 +285,9 @@ case 0xfe: { op_io(); regs.y--; op_io(); - if(regs.y == 0x00){ opcode_cycle = 0; break; } + if(regs.y == 0x00){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -324,7 +295,6 @@ case 0x5f: { rd = op_readpc(); rd |= op_readpc() << 8; regs.pc = rd; - opcode_cycle = 0; break; } @@ -336,7 +306,6 @@ case 0x1f: { rd = op_readaddr(dp); rd |= op_readaddr(dp + 1) << 8; regs.pc = rd; - opcode_cycle = 0; break; } @@ -347,7 +316,6 @@ case 0x3f: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -357,7 +325,6 @@ case 0x4f: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = 0xff00 | rd; - opcode_cycle = 0; break; } @@ -369,7 +336,6 @@ case 0x01: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -381,7 +347,6 @@ case 0x11: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -393,7 +358,6 @@ case 0x21: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -405,7 +369,6 @@ case 0x31: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -417,7 +380,6 @@ case 0x41: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -429,7 +391,6 @@ case 0x51: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -441,7 +402,6 @@ case 0x61: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -453,7 +413,6 @@ case 0x71: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -465,7 +424,6 @@ case 0x81: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -477,7 +435,6 @@ case 0x91: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -489,7 +446,6 @@ case 0xa1: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -501,7 +457,6 @@ case 0xb1: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -513,7 +468,6 @@ case 0xc1: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -525,7 +479,6 @@ case 0xd1: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -537,7 +490,6 @@ case 0xe1: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -549,7 +501,6 @@ case 0xf1: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -563,7 +514,6 @@ case 0x0f: { regs.pc = rd; regs.p.b = 1; regs.p.i = 0; - opcode_cycle = 0; break; } @@ -572,7 +522,6 @@ case 0x6f: { rd |= op_readstack() << 8; op_io(2); regs.pc = rd; - opcode_cycle = 0; break; } @@ -582,7 +531,6 @@ case 0x7f: { rd |= op_readstack() << 8; op_io(2); regs.pc = rd; - opcode_cycle = 0; break; } diff --git a/apu/bapu/smp/core/opcycle_read.cpp b/apu/bapu/smp/core/opcycle_read.cpp index 3eb1cd77..2a16a3c8 100644 --- a/apu/bapu/smp/core/opcycle_read.cpp +++ b/apu/bapu/smp/core/opcycle_read.cpp @@ -1,56 +1,48 @@ case 0x88: { rd = op_readpc(); regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; break; } case 0x28: { rd = op_readpc(); regs.a = op_and(regs.a, rd); - opcode_cycle = 0; break; } case 0x68: { rd = op_readpc(); regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; break; } case 0xc8: { rd = op_readpc(); regs.x = op_cmp(regs.x, rd); - opcode_cycle = 0; break; } case 0xad: { rd = op_readpc(); regs.y = op_cmp(regs.y, rd); - opcode_cycle = 0; break; } case 0x48: { rd = op_readpc(); regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; break; } case 0x08: { rd = op_readpc(); regs.a = op_or(regs.a, rd); - opcode_cycle = 0; break; } case 0xa8: { rd = op_readpc(); regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; break; } @@ -58,7 +50,6 @@ case 0x86: { op_io(); rd = op_readdp(regs.x); regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; break; } @@ -66,7 +57,6 @@ case 0x26: { op_io(); rd = op_readdp(regs.x); regs.a = op_and(regs.a, rd); - opcode_cycle = 0; break; } @@ -74,7 +64,6 @@ case 0x66: { op_io(); rd = op_readdp(regs.x); regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; break; } @@ -82,7 +71,6 @@ case 0x46: { op_io(); rd = op_readdp(regs.x); regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; break; } @@ -90,7 +78,6 @@ case 0x06: { op_io(); rd = op_readdp(regs.x); regs.a = op_or(regs.a, rd); - opcode_cycle = 0; break; } @@ -98,7 +85,6 @@ case 0xa6: { op_io(); rd = op_readdp(regs.x); regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; break; } @@ -106,7 +92,6 @@ case 0x84: { dp = op_readpc(); rd = op_readdp(dp); regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; break; } @@ -114,7 +99,6 @@ case 0x24: { dp = op_readpc(); rd = op_readdp(dp); regs.a = op_and(regs.a, rd); - opcode_cycle = 0; break; } @@ -122,7 +106,6 @@ case 0x64: { dp = op_readpc(); rd = op_readdp(dp); regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; break; } @@ -130,7 +113,6 @@ case 0x3e: { dp = op_readpc(); rd = op_readdp(dp); regs.x = op_cmp(regs.x, rd); - opcode_cycle = 0; break; } @@ -138,7 +120,6 @@ case 0x7e: { dp = op_readpc(); rd = op_readdp(dp); regs.y = op_cmp(regs.y, rd); - opcode_cycle = 0; break; } @@ -146,7 +127,6 @@ case 0x44: { dp = op_readpc(); rd = op_readdp(dp); regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; break; } @@ -154,7 +134,6 @@ case 0x04: { dp = op_readpc(); rd = op_readdp(dp); regs.a = op_or(regs.a, rd); - opcode_cycle = 0; break; } @@ -162,7 +141,6 @@ case 0xa4: { dp = op_readpc(); rd = op_readdp(dp); regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; break; } @@ -171,7 +149,6 @@ case 0x94: { op_io(); rd = op_readdp(dp + regs.x); regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; break; } @@ -180,7 +157,6 @@ case 0x34: { op_io(); rd = op_readdp(dp + regs.x); regs.a = op_and(regs.a, rd); - opcode_cycle = 0; break; } @@ -189,7 +165,6 @@ case 0x74: { op_io(); rd = op_readdp(dp + regs.x); regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; break; } @@ -198,7 +173,6 @@ case 0x54: { op_io(); rd = op_readdp(dp + regs.x); regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; break; } @@ -207,7 +181,6 @@ case 0x14: { op_io(); rd = op_readdp(dp + regs.x); regs.a = op_or(regs.a, rd); - opcode_cycle = 0; break; } @@ -216,7 +189,6 @@ case 0xb4: { op_io(); rd = op_readdp(dp + regs.x); regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; break; } @@ -225,7 +197,6 @@ case 0x85: { dp |= op_readpc() << 8; rd = op_readaddr(dp); regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; break; } @@ -234,7 +205,6 @@ case 0x25: { dp |= op_readpc() << 8; rd = op_readaddr(dp); regs.a = op_and(regs.a, rd); - opcode_cycle = 0; break; } @@ -243,7 +213,6 @@ case 0x65: { dp |= op_readpc() << 8; rd = op_readaddr(dp); regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; break; } @@ -252,7 +221,6 @@ case 0x1e: { dp |= op_readpc() << 8; rd = op_readaddr(dp); regs.x = op_cmp(regs.x, rd); - opcode_cycle = 0; break; } @@ -261,7 +229,6 @@ case 0x5e: { dp |= op_readpc() << 8; rd = op_readaddr(dp); regs.y = op_cmp(regs.y, rd); - opcode_cycle = 0; break; } @@ -270,7 +237,6 @@ case 0x45: { dp |= op_readpc() << 8; rd = op_readaddr(dp); regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; break; } @@ -279,7 +245,6 @@ case 0x05: { dp |= op_readpc() << 8; rd = op_readaddr(dp); regs.a = op_or(regs.a, rd); - opcode_cycle = 0; break; } @@ -288,7 +253,6 @@ case 0xa5: { dp |= op_readpc() << 8; rd = op_readaddr(dp); regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; break; } @@ -298,7 +262,6 @@ case 0x95: { op_io(); rd = op_readaddr(dp + regs.x); regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; break; } @@ -308,7 +271,6 @@ case 0x96: { op_io(); rd = op_readaddr(dp + regs.y); regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; break; } @@ -318,7 +280,6 @@ case 0x35: { op_io(); rd = op_readaddr(dp + regs.x); regs.a = op_and(regs.a, rd); - opcode_cycle = 0; break; } @@ -328,7 +289,6 @@ case 0x36: { op_io(); rd = op_readaddr(dp + regs.y); regs.a = op_and(regs.a, rd); - opcode_cycle = 0; break; } @@ -338,7 +298,6 @@ case 0x75: { op_io(); rd = op_readaddr(dp + regs.x); regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; break; } @@ -348,7 +307,6 @@ case 0x76: { op_io(); rd = op_readaddr(dp + regs.y); regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; break; } @@ -358,7 +316,6 @@ case 0x55: { op_io(); rd = op_readaddr(dp + regs.x); regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; break; } @@ -368,7 +325,6 @@ case 0x56: { op_io(); rd = op_readaddr(dp + regs.y); regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; break; } @@ -378,7 +334,6 @@ case 0x15: { op_io(); rd = op_readaddr(dp + regs.x); regs.a = op_or(regs.a, rd); - opcode_cycle = 0; break; } @@ -388,7 +343,6 @@ case 0x16: { op_io(); rd = op_readaddr(dp + regs.y); regs.a = op_or(regs.a, rd); - opcode_cycle = 0; break; } @@ -398,7 +352,6 @@ case 0xb5: { op_io(); rd = op_readaddr(dp + regs.x); regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; break; } @@ -408,7 +361,6 @@ case 0xb6: { op_io(); rd = op_readaddr(dp + regs.y); regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; break; } @@ -419,7 +371,6 @@ case 0x87: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp); regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; break; } @@ -430,7 +381,6 @@ case 0x27: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp); regs.a = op_and(regs.a, rd); - opcode_cycle = 0; break; } @@ -441,7 +391,6 @@ case 0x67: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp); regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; break; } @@ -452,7 +401,6 @@ case 0x47: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp); regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; break; } @@ -463,7 +411,6 @@ case 0x07: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp); regs.a = op_or(regs.a, rd); - opcode_cycle = 0; break; } @@ -474,7 +421,6 @@ case 0xa7: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp); regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; break; } @@ -485,7 +431,6 @@ case 0x97: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp + regs.y); regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; break; } @@ -496,7 +441,6 @@ case 0x37: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp + regs.y); regs.a = op_and(regs.a, rd); - opcode_cycle = 0; break; } @@ -507,7 +451,6 @@ case 0x77: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp + regs.y); regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; break; } @@ -518,7 +461,6 @@ case 0x57: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp + regs.y); regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; break; } @@ -529,7 +471,6 @@ case 0x17: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp + regs.y); regs.a = op_or(regs.a, rd); - opcode_cycle = 0; break; } @@ -540,7 +481,6 @@ case 0xb7: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp + regs.y); regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; break; } @@ -550,7 +490,6 @@ case 0x99: { wr = op_readdp(regs.x); wr = op_adc(wr, rd); (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; break; } @@ -560,7 +499,6 @@ case 0x39: { wr = op_readdp(regs.x); wr = op_and(wr, rd); (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; break; } @@ -570,7 +508,6 @@ case 0x79: { wr = op_readdp(regs.x); wr = op_cmp(wr, rd); (0) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; break; } @@ -580,7 +517,6 @@ case 0x59: { wr = op_readdp(regs.x); wr = op_eor(wr, rd); (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; break; } @@ -590,7 +526,6 @@ case 0x19: { wr = op_readdp(regs.x); wr = op_or(wr, rd); (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; break; } @@ -600,7 +535,6 @@ case 0xb9: { wr = op_readdp(regs.x); wr = op_sbc(wr, rd); (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; break; } @@ -611,7 +545,6 @@ case 0x89: { wr = op_readdp(dp); wr = op_adc(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -622,7 +555,6 @@ case 0x29: { wr = op_readdp(dp); wr = op_and(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -633,7 +565,6 @@ case 0x69: { wr = op_readdp(dp); wr = op_cmp(wr, rd); (0) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -644,7 +575,6 @@ case 0x49: { wr = op_readdp(dp); wr = op_eor(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -655,7 +585,6 @@ case 0x09: { wr = op_readdp(dp); wr = op_or(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -666,7 +595,6 @@ case 0xa9: { wr = op_readdp(dp); wr = op_sbc(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -676,7 +604,6 @@ case 0x98: { wr = op_readdp(dp); wr = op_adc(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -686,7 +613,6 @@ case 0x38: { wr = op_readdp(dp); wr = op_and(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -696,7 +622,6 @@ case 0x78: { wr = op_readdp(dp); wr = op_cmp(wr, rd); (0) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -706,7 +631,6 @@ case 0x58: { wr = op_readdp(dp); wr = op_eor(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -716,7 +640,6 @@ case 0x18: { wr = op_readdp(dp); wr = op_or(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -726,7 +649,6 @@ case 0xb8: { wr = op_readdp(dp); wr = op_sbc(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -736,7 +658,6 @@ case 0x7a: { op_io(); rd |= op_readdp(dp + 1) << 8; regs.ya = op_addw(regs.ya, rd); - opcode_cycle = 0; break; } @@ -746,7 +667,6 @@ case 0x9a: { op_io(); rd |= op_readdp(dp + 1) << 8; regs.ya = op_subw(regs.ya, rd); - opcode_cycle = 0; break; } @@ -755,7 +675,6 @@ case 0x5a: { rd = op_readdp(dp); rd |= op_readdp(dp + 1) << 8; op_cmpw(regs.ya, rd); - opcode_cycle = 0; break; } @@ -766,7 +685,6 @@ case 0x4a: { dp &= 0x1fff; rd = op_readaddr(dp); regs.p.c = regs.p.c & !!(rd & (1 << bit)); - opcode_cycle = 0; break; } @@ -777,7 +695,6 @@ case 0x6a: { dp &= 0x1fff; rd = op_readaddr(dp); regs.p.c = regs.p.c & !(rd & (1 << bit)); - opcode_cycle = 0; break; } @@ -789,7 +706,6 @@ case 0x8a: { rd = op_readaddr(dp); op_io(); regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); - opcode_cycle = 0; break; } @@ -801,7 +717,6 @@ case 0xea: { rd = op_readaddr(dp); rd ^= (1 << bit); op_writeaddr(dp, rd); - opcode_cycle = 0; break; } @@ -813,7 +728,6 @@ case 0x0a: { rd = op_readaddr(dp); op_io(); regs.p.c = regs.p.c | !!(rd & (1 << bit)); - opcode_cycle = 0; break; } @@ -825,7 +739,6 @@ case 0x2a: { rd = op_readaddr(dp); op_io(); regs.p.c = regs.p.c | !(rd & (1 << bit)); - opcode_cycle = 0; break; } diff --git a/apu/bapu/smp/core/opcycle_rmw.cpp b/apu/bapu/smp/core/opcycle_rmw.cpp index fcacfc71..9b0dd2fb 100644 --- a/apu/bapu/smp/core/opcycle_rmw.cpp +++ b/apu/bapu/smp/core/opcycle_rmw.cpp @@ -1,75 +1,61 @@ case 0xbc: { op_io(); regs.a = op_inc(regs.a); - opcode_cycle = 0; break; } case 0x3d: { op_io(); regs.x = op_inc(regs.x); - opcode_cycle = 0; break; } case 0xfc: { op_io(); regs.y = op_inc(regs.y); - opcode_cycle = 0; break; } case 0x9c: { op_io(); regs.a = op_dec(regs.a); - opcode_cycle = 0; break; } case 0x1d: { op_io(); regs.x = op_dec(regs.x); - opcode_cycle = 0; break; } case 0xdc: { op_io(); regs.y = op_dec(regs.y); - opcode_cycle = 0; break; } case 0x1c: { op_io(); regs.a = op_asl(regs.a); - opcode_cycle = 0; break; } case 0x5c: { op_io(); regs.a = op_lsr(regs.a); - opcode_cycle = 0; break; } case 0x3c: { op_io(); regs.a = op_rol(regs.a); - opcode_cycle = 0; break; } case 0x7c: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = op_ror(regs.a); - opcode_cycle = 0; + op_io(); + regs.a = op_ror(regs.a); break; - } - break; } case 0xab: { @@ -77,7 +63,6 @@ case 0xab: { rd = op_readdp(dp); rd = op_inc(rd); op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -86,7 +71,6 @@ case 0x8b: { rd = op_readdp(dp); rd = op_dec(rd); op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -95,7 +79,6 @@ case 0x0b: { rd = op_readdp(dp); rd = op_asl(rd); op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -104,7 +87,6 @@ case 0x4b: { rd = op_readdp(dp); rd = op_lsr(rd); op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -113,7 +95,6 @@ case 0x2b: { rd = op_readdp(dp); rd = op_rol(rd); op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -122,7 +103,6 @@ case 0x6b: { rd = op_readdp(dp); rd = op_ror(rd); op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -132,7 +112,6 @@ case 0xbb: { rd = op_readdp(dp + regs.x); rd = op_inc(rd); op_writedp(dp + regs.x, rd); - opcode_cycle = 0; break; } @@ -142,7 +121,6 @@ case 0x9b: { rd = op_readdp(dp + regs.x); rd = op_dec(rd); op_writedp(dp + regs.x, rd); - opcode_cycle = 0; break; } @@ -152,7 +130,6 @@ case 0x1b: { rd = op_readdp(dp + regs.x); rd = op_asl(rd); op_writedp(dp + regs.x, rd); - opcode_cycle = 0; break; } @@ -162,7 +139,6 @@ case 0x5b: { rd = op_readdp(dp + regs.x); rd = op_lsr(rd); op_writedp(dp + regs.x, rd); - opcode_cycle = 0; break; } @@ -172,7 +148,6 @@ case 0x3b: { rd = op_readdp(dp + regs.x); rd = op_rol(rd); op_writedp(dp + regs.x, rd); - opcode_cycle = 0; break; } @@ -182,7 +157,6 @@ case 0x7b: { rd = op_readdp(dp + regs.x); rd = op_ror(rd); op_writedp(dp + regs.x, rd); - opcode_cycle = 0; break; } @@ -192,7 +166,6 @@ case 0xac: { rd = op_readaddr(dp); rd = op_inc(rd); op_writeaddr(dp, rd); - opcode_cycle = 0; break; } @@ -202,7 +175,6 @@ case 0x8c: { rd = op_readaddr(dp); rd = op_dec(rd); op_writeaddr(dp, rd); - opcode_cycle = 0; break; } @@ -212,7 +184,6 @@ case 0x0c: { rd = op_readaddr(dp); rd = op_asl(rd); op_writeaddr(dp, rd); - opcode_cycle = 0; break; } @@ -222,7 +193,6 @@ case 0x4c: { rd = op_readaddr(dp); rd = op_lsr(rd); op_writeaddr(dp, rd); - opcode_cycle = 0; break; } @@ -232,7 +202,6 @@ case 0x2c: { rd = op_readaddr(dp); rd = op_rol(rd); op_writeaddr(dp, rd); - opcode_cycle = 0; break; } @@ -242,7 +211,6 @@ case 0x6c: { rd = op_readaddr(dp); rd = op_ror(rd); op_writeaddr(dp, rd); - opcode_cycle = 0; break; } @@ -254,7 +222,6 @@ case 0x0e: { regs.p.z = ((regs.a - rd) == 0); op_readaddr(dp); op_writeaddr(dp, rd | regs.a); - opcode_cycle = 0; break; } @@ -266,7 +233,6 @@ case 0x4e: { regs.p.z = ((regs.a - rd) == 0); op_readaddr(dp); op_writeaddr(dp, rd &~ regs.a); - opcode_cycle = 0; break; } @@ -279,7 +245,6 @@ case 0x3a: { op_writedp(dp, rd >> 8); regs.p.n = !!(rd & 0x8000); regs.p.z = (rd == 0); - opcode_cycle = 0; break; } @@ -292,7 +257,6 @@ case 0x1a: { op_writedp(dp, rd >> 8); regs.p.n = !!(rd & 0x8000); regs.p.z = (rd == 0); - opcode_cycle = 0; break; } From 13c55b92607a3beb7d5c0f889e14a9d59d6ea43c Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Tue, 18 Oct 2011 13:10:06 -0500 Subject: [PATCH 28/33] Allow switching between 3 SMP cores at compile-time. --- apu/bapu/smp/core.cpp | 19 +- apu/bapu/smp/core/opcycle_misc.cpp | 681 ++++++++--- apu/bapu/smp/core/opcycle_mov.cpp | 311 +++-- apu/bapu/smp/core/opcycle_pc.cpp | 1467 ++++++++++++++++++------ apu/bapu/smp/core/opcycle_read.cpp | 1647 ++++++++++++++++++++------- apu/bapu/smp/core/opcycle_rmw.cpp | 556 ++++++--- apu/bapu/smp/core/oppseudo_misc.cpp | 311 +++++ apu/bapu/smp/core/oppseudo_mov.cpp | 705 ++++++++++++ apu/bapu/smp/core/oppseudo_pc.cpp | 536 +++++++++ apu/bapu/smp/core/oppseudo_read.cpp | 744 ++++++++++++ apu/bapu/smp/core/oppseudo_rmw.cpp | 262 +++++ apu/bapu/smp/smp.cpp | 1 + 12 files changed, 6126 insertions(+), 1114 deletions(-) create mode 100644 apu/bapu/smp/core/oppseudo_misc.cpp create mode 100644 apu/bapu/smp/core/oppseudo_mov.cpp create mode 100644 apu/bapu/smp/core/oppseudo_pc.cpp create mode 100644 apu/bapu/smp/core/oppseudo_read.cpp create mode 100644 apu/bapu/smp/core/oppseudo_rmw.cpp diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp index a7a70072..43234f6a 100644 --- a/apu/bapu/smp/core.cpp +++ b/apu/bapu/smp/core.cpp @@ -59,12 +59,25 @@ void SMP::op_step() { #define op_writestack(data) op_write(0x0100 | regs.sp--, data) #if defined(CYCLE_ACCURATE) + #if defined(PSEUDO_CYCLE) if(opcode_cycle == 0) opcode_number = op_readpc(); -// opcode_cycle++; switch(opcode_number) { + #include "core/oppseudo_misc.cpp" + #include "core/oppseudo_mov.cpp" + #include "core/oppseudo_pc.cpp" + #include "core/oppseudo_read.cpp" + #include "core/oppseudo_rmw.cpp" + } + + #else + + if(opcode_cycle == 0) { + opcode_number = op_readpc(); + opcode_cycle++; + } else switch(opcode_number) { #include "core/opcycle_misc.cpp" #include "core/opcycle_mov.cpp" #include "core/opcycle_pc.cpp" @@ -72,6 +85,7 @@ void SMP::op_step() { #include "core/opcycle_rmw.cpp" } + #endif // defined(PSEUDO_CYCLE) #else unsigned opcode = op_readpc(); @@ -98,8 +112,7 @@ void SMP::op_step() { dsp.clock += cycle_count_table[opcode]; #endif - - #endif + #endif // defined(CYCLE_ACCURATE) } const unsigned SMP::cycle_count_table[256] = { diff --git a/apu/bapu/smp/core/opcycle_misc.cpp b/apu/bapu/smp/core/opcycle_misc.cpp index d266ef92..963f9fc2 100644 --- a/apu/bapu/smp/core/opcycle_misc.cpp +++ b/apu/bapu/smp/core/opcycle_misc.cpp @@ -1,311 +1,696 @@ case 0x00: { - op_io(); + switch(opcode_cycle++) { + case 1: + op_io(); + opcode_cycle = 0; + break; + } break; } case 0xef: { - op_io(2); - regs.pc--; + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.pc--; + opcode_cycle = 0; + break; + } break; } case 0xff: { - op_io(2); - regs.pc--; + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.pc--; + opcode_cycle = 0; + break; + } break; } case 0x9f: { - op_io(4); - regs.a = (regs.a >> 4) | (regs.a << 4); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_io(); + break; + case 4: + op_io(); + regs.a = (regs.a >> 4) | (regs.a << 4); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } break; } case 0xdf: { - op_io(2); - if(regs.p.c || (regs.a) > 0x99) { - regs.a += 0x60; - regs.p.c = 1; + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + if(regs.p.c || (regs.a) > 0x99) { + regs.a += 0x60; + regs.p.c = 1; + } + if(regs.p.h || (regs.a & 15) > 0x09) { + regs.a += 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; } - if(regs.p.h || (regs.a & 15) > 0x09) { - regs.a += 0x06; - } - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); break; } case 0xbe: { - op_io(2); - if(!regs.p.c || (regs.a) > 0x99) { - regs.a -= 0x60; - regs.p.c = 0; + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + if(!regs.p.c || (regs.a) > 0x99) { + regs.a -= 0x60; + regs.p.c = 0; + } + if(!regs.p.h || (regs.a & 15) > 0x09) { + regs.a -= 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; } - if(!regs.p.h || (regs.a & 15) > 0x09) { - regs.a -= 0x06; - } - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); break; } case 0x60: { - op_io(); - regs.p.c = 0; + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.c = 0; + opcode_cycle = 0; + break; + } break; } case 0x20: { - op_io(); - regs.p.p = 0; + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.p = 0; + opcode_cycle = 0; + break; + } break; } case 0x80: { - op_io(); - regs.p.c = 1; + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.c = 1; + opcode_cycle = 0; + break; + } break; } case 0x40: { - op_io(); - regs.p.p = 1; + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.p = 1; + opcode_cycle = 0; + break; + } break; } case 0xe0: { - op_io(); - regs.p.v = 0; - regs.p.h = 0; + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.v = 0; + regs.p.h = 0; + opcode_cycle = 0; + break; + } break; } case 0xed: { - op_io(2); - regs.p.c = !regs.p.c; + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.p.c = !regs.p.c; + opcode_cycle = 0; + break; + } break; } case 0xa0: { - op_io(2); - regs.p.i = 1; + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.p.i = 1; + opcode_cycle = 0; + break; + } break; } case 0xc0: { - op_io(2); - regs.p.i = 0; + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.p.i = 0; + opcode_cycle = 0; + break; + } break; } case 0x02: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x01; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x01; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x12: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x01; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x01; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x22: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x02; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x02; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x32: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x02; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x02; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x42: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x04; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x04; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x52: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x04; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x04; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x62: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x08; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x08; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x72: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x08; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x08; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x82: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x10; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x10; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x92: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x10; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x10; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0xa2: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x20; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x20; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0xb2: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x20; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x20; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0xc2: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x40; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x40; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0xd2: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x40; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x40; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0xe2: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x80; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x80; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0xf2: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x80; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x80; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x2d: { - op_io(2); - op_writestack(regs.a); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_writestack(regs.a); + opcode_cycle = 0; + break; + } break; } case 0x4d: { - op_io(2); - op_writestack(regs.x); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_writestack(regs.x); + opcode_cycle = 0; + break; + } break; } case 0x6d: { - op_io(2); - op_writestack(regs.y); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_writestack(regs.y); + opcode_cycle = 0; + break; + } break; } case 0x0d: { - op_io(2); - op_writestack(regs.p); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_writestack(regs.p); + opcode_cycle = 0; + break; + } break; } case 0xae: { - op_io(2); - regs.a = op_readstack(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + regs.a = op_readstack(); + opcode_cycle = 0; + break; + } break; } case 0xce: { - op_io(2); - regs.x = op_readstack(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + regs.x = op_readstack(); + opcode_cycle = 0; + break; + } break; } case 0xee: { - op_io(2); - regs.y = op_readstack(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + regs.y = op_readstack(); + opcode_cycle = 0; + break; + } break; } case 0x8e: { - op_io(2); - regs.p = op_readstack(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + regs.p = op_readstack(); + opcode_cycle = 0; + break; + } break; } case 0xcf: { - op_io(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); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_io(); + break; + case 7: + op_io(); + break; + case 8: + op_io(); + ya = regs.y * regs.a; + regs.a = ya; + regs.y = ya >> 8; + //result is set based on y (high-byte) only + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } break; } case 0x9e: { - op_io(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 S-SMP in this case - regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); - regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_io(); + break; + case 7: + op_io(); + break; + case 8: + op_io(); + break; + case 9: + op_io(); + break; + case 10: + op_io(); + break; + case 11: + op_io(); + ya = regs.ya; + //overflow set if quotient >= 256 + regs.p.v = !!(regs.y >= regs.x); + regs.p.h = !!((regs.y & 15) >= (regs.x & 15)); + if(regs.y < (regs.x << 1)) { + //if quotient is <= 511 (will fit into 9-bit result) + regs.a = ya / regs.x; + regs.y = ya % regs.x; + } else { + //otherwise, the quotient won't fit into regs.p.v + regs.a + //this emulates the odd behavior of the S-SMP 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); + opcode_cycle = 0; + break; } - //result is set based on a (quotient) only - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); break; } diff --git a/apu/bapu/smp/core/opcycle_mov.cpp b/apu/bapu/smp/core/opcycle_mov.cpp index fd44ad29..635c7ca5 100644 --- a/apu/bapu/smp/core/opcycle_mov.cpp +++ b/apu/bapu/smp/core/opcycle_mov.cpp @@ -1,72 +1,117 @@ case 0x7d: { - op_io(); - regs.a = regs.x; - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = regs.x; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } break; } case 0xdd: { - op_io(); - regs.a = regs.y; - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = regs.y; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } break; } case 0x5d: { - op_io(); - regs.x = regs.a; - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.x = regs.a; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } break; } case 0xfd: { - op_io(); - regs.y = regs.a; - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.y = regs.a; + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } break; } case 0x9d: { - op_io(); - regs.x = regs.sp; - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.x = regs.sp; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } break; } case 0xbd: { - op_io(); - regs.sp = regs.x; + switch(opcode_cycle++) { + case 1: + op_io(); + regs.sp = regs.x; + opcode_cycle = 0; + break; + } break; } case 0xe8: { - regs.a = op_readpc(); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); + switch(opcode_cycle++) { + case 1: + regs.a = op_readpc(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } break; } case 0xcd: { - regs.x = op_readpc(); - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); + switch(opcode_cycle++) { + case 1: + regs.x = op_readpc(); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } break; } case 0x8d: { - regs.y = op_readpc(); - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); + switch(opcode_cycle++) { + case 1: + regs.y = op_readpc(); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } break; } case 0xe6: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: op_io(); break; @@ -81,12 +126,14 @@ case 0xe6: { } case 0xbf: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: op_io(); break; case 2: regs.a = op_readdp(regs.x++); + break; + case 3: op_io(); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -97,7 +144,7 @@ case 0xbf: { } case 0xe4: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); break; @@ -112,7 +159,7 @@ case 0xe4: { } case 0xf8: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); break; @@ -127,7 +174,7 @@ case 0xf8: { } case 0xeb: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); break; @@ -142,12 +189,14 @@ case 0xeb: { } case 0xf4: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); - op_io(); break; case 2: + op_io(); + break; + case 3: regs.a = op_readdp(sp + regs.x); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -158,12 +207,14 @@ case 0xf4: { } case 0xf9: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); - op_io(); break; case 2: + op_io(); + break; + case 3: regs.x = op_readdp(sp + regs.y); regs.p.n = !!(regs.x & 0x80); regs.p.z = (regs.x == 0); @@ -174,12 +225,14 @@ case 0xf9: { } case 0xfb: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); - op_io(); break; case 2: + op_io(); + break; + case 3: regs.y = op_readdp(sp + regs.x); regs.p.n = !!(regs.y & 0x80); regs.p.z = (regs.y == 0); @@ -190,7 +243,7 @@ case 0xfb: { } case 0xe5: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); break; @@ -208,12 +261,14 @@ case 0xe5: { } case 0xe9: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); - sp |= op_readpc() << 8; break; case 2: + sp |= op_readpc() << 8; + break; + case 3: regs.x = op_readaddr(sp); regs.p.n = !!(regs.x & 0x80); regs.p.z = (regs.x == 0); @@ -224,12 +279,14 @@ case 0xe9: { } case 0xec: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); - sp |= op_readpc() << 8; break; case 2: + sp |= op_readpc() << 8; + break; + case 3: regs.y = op_readaddr(sp); regs.p.n = !!(regs.y & 0x80); regs.p.z = (regs.y == 0); @@ -240,13 +297,17 @@ case 0xec: { } case 0xf5: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); - sp |= op_readpc() << 8; - op_io(); break; case 2: + sp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: regs.a = op_readaddr(sp + regs.x); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -257,13 +318,17 @@ case 0xf5: { } case 0xf6: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); - sp |= op_readpc() << 8; - op_io(); break; case 2: + sp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: regs.a = op_readaddr(sp + regs.y); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -274,18 +339,20 @@ case 0xf6: { } case 0xe7: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc() + regs.x; - op_io(); break; case 2: - sp = op_readdp(dp); + op_io(); break; case 3: - sp |= op_readdp(dp + 1) << 8; + sp = op_readdp(dp); break; case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: regs.a = op_readaddr(sp); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -296,18 +363,20 @@ case 0xe7: { } case 0xf7: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); - op_io(); break; case 2: - sp = op_readdp(dp); + op_io(); break; case 3: - sp |= op_readdp(dp + 1) << 8; + sp = op_readdp(dp); break; case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: regs.a = op_readaddr(sp + regs.y); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -318,7 +387,7 @@ case 0xf7: { } case 0xfa: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); break; @@ -337,15 +406,17 @@ case 0xfa: { } case 0x8f: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: rd = op_readpc(); - dp = op_readpc(); break; case 2: - op_readdp(dp); + dp = op_readpc(); break; case 3: + op_readdp(dp); + break; + case 4: op_writedp(dp, rd); opcode_cycle = 0; break; @@ -354,7 +425,7 @@ case 0x8f: { } case 0xc6: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: op_io(); break; @@ -370,10 +441,14 @@ case 0xc6: { } case 0xaf: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: - op_io(2); + op_io(); + break; case 2: + op_io(); + break; + case 3: op_writedp(regs.x++, regs.a); opcode_cycle = 0; break; @@ -382,7 +457,7 @@ case 0xaf: { } case 0xc4: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); break; @@ -398,7 +473,7 @@ case 0xc4: { } case 0xd8: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); break; @@ -414,7 +489,7 @@ case 0xd8: { } case 0xcb: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); break; @@ -430,16 +505,18 @@ case 0xcb: { } case 0xd4: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); + break; + case 2: op_io(); dp += regs.x; break; - case 2: + case 3: op_readdp(dp); break; - case 3: + case 4: op_writedp(dp, regs.a); opcode_cycle = 0; break; @@ -448,16 +525,18 @@ case 0xd4: { } case 0xd9: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); + break; + case 2: op_io(); dp += regs.y; break; - case 2: + case 3: op_readdp(dp); break; - case 3: + case 4: op_writedp(dp, regs.x); opcode_cycle = 0; break; @@ -466,16 +545,18 @@ case 0xd9: { } case 0xdb: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); + break; + case 2: op_io(); dp += regs.x; break; - case 2: + case 3: op_readdp(dp); break; - case 3: + case 4: op_writedp(dp, regs.y); opcode_cycle = 0; break; @@ -484,7 +565,7 @@ case 0xdb: { } case 0xc5: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); break; @@ -503,7 +584,7 @@ case 0xc5: { } case 0xc9: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); break; @@ -522,7 +603,7 @@ case 0xc9: { } case 0xcc: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); break; @@ -541,17 +622,21 @@ case 0xcc: { } case 0xd5: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); + break; + case 2: dp |= op_readpc() << 8; + break; + case 3: op_io(); dp += regs.x; break; - case 2: + case 4: op_readaddr(dp); break; - case 3: + case 5: op_writeaddr(dp, regs.a); opcode_cycle = 0; break; @@ -560,17 +645,21 @@ case 0xd5: { } case 0xd6: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); + break; + case 2: dp |= op_readpc() << 8; + break; + case 3: op_io(); dp += regs.y; break; - case 2: + case 4: op_readaddr(dp); break; - case 3: + case 5: op_writeaddr(dp, regs.a); opcode_cycle = 0; break; @@ -579,22 +668,24 @@ case 0xd6: { } case 0xc7: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); + break; + case 2: op_io(); sp += regs.x; break; - case 2: + case 3: dp = op_readdp(sp); break; - case 3: + case 4: dp |= op_readdp(sp + 1) << 8; break; - case 4: + case 5: op_readaddr(dp); break; - case 5: + case 6: op_writeaddr(dp, regs.a); opcode_cycle = 0; break; @@ -603,7 +694,7 @@ case 0xc7: { } case 0xd7: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); break; @@ -612,13 +703,15 @@ case 0xd7: { break; case 3: dp |= op_readdp(sp + 1) << 8; + break; + case 4: op_io(); dp += regs.y; break; - case 4: + case 5: op_readaddr(dp); break; - case 5: + case 6: op_writeaddr(dp, regs.a); opcode_cycle = 0; break; @@ -627,15 +720,17 @@ case 0xd7: { } case 0xba: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); break; case 2: regs.a = op_readdp(sp); - op_io(); break; case 3: + op_io(); + break; + case 4: regs.y = op_readdp(sp + 1); regs.p.n = !!(regs.ya & 0x8000); regs.p.z = (regs.ya == 0); @@ -646,7 +741,7 @@ case 0xba: { } case 0xda: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); break; @@ -665,12 +760,14 @@ case 0xda: { } case 0xaa: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); - sp |= op_readpc() << 8; break; case 2: + sp |= op_readpc() << 8; + break; + case 3: bit = sp >> 13; sp &= 0x1fff; rd = op_readaddr(sp); @@ -682,20 +779,24 @@ case 0xaa: { } case 0xca: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); - dp |= op_readpc() << 8; break; case 2: + dp |= op_readpc() << 8; + break; + case 3: bit = dp >> 13; dp &= 0x1fff; rd = op_readaddr(dp); if(regs.p.c)rd |= (1 << bit); else rd &= ~(1 << bit); + break; + case 4: op_io(); break; - case 3: + case 5: op_writeaddr(dp, rd); opcode_cycle = 0; break; diff --git a/apu/bapu/smp/core/opcycle_pc.cpp b/apu/bapu/smp/core/opcycle_pc.cpp index 022179d1..1cdda647 100644 --- a/apu/bapu/smp/core/opcycle_pc.cpp +++ b/apu/bapu/smp/core/opcycle_pc.cpp @@ -1,536 +1,1347 @@ case 0x2f: { - rd = op_readpc(); - if(0){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(0){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xf0: { - rd = op_readpc(); - if(!regs.p.z){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(!regs.p.z){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xd0: { - rd = op_readpc(); - if(regs.p.z){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(regs.p.z){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xb0: { - rd = op_readpc(); - if(!regs.p.c){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(!regs.p.c){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x90: { - rd = op_readpc(); - if(regs.p.c){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(regs.p.c){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x70: { - rd = op_readpc(); - if(!regs.p.v){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(!regs.p.v){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x50: { - rd = op_readpc(); - if(regs.p.v){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(regs.p.v){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x30: { - rd = op_readpc(); - if(!regs.p.n){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(!regs.p.n){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x10: { - rd = op_readpc(); - if(regs.p.n){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(regs.p.n){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x03: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x01) != 0x01){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x01) != 0x01){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x13: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x01) == 0x01){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x01) == 0x01){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x23: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x02) != 0x02){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x02) != 0x02){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x33: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x02) == 0x02){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x02) == 0x02){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x43: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x04) != 0x04){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x04) != 0x04){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x53: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x04) == 0x04){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x04) == 0x04){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x63: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x08) != 0x08){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x08) != 0x08){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x73: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x08) == 0x08){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x08) == 0x08){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x83: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x10) != 0x10){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x10) != 0x10){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x93: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x10) == 0x10){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x10) == 0x10){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xa3: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x20) != 0x20){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x20) != 0x20){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xb3: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x20) == 0x20){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x20) == 0x20){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xc3: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x40) != 0x40){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x40) != 0x40){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xd3: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x40) == 0x40){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x40) == 0x40){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xe3: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x80) != 0x80){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x80) != 0x80){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xf3: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x80) == 0x80){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x80) == 0x80){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x2e: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if(regs.a == sp){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if(regs.a == sp){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xde: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp + regs.x); - rd = op_readpc(); - op_io(); - if(regs.a == sp){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp + regs.x); + break; + case 4: + rd = op_readpc(); + break; + case 5: + op_io(); + if(regs.a == sp){ opcode_cycle = 0; break; } + break; + case 6: + op_io(); + break; + case 7: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x6e: { - dp = op_readpc(); - wr = op_readdp(dp); - op_writedp(dp, --wr); - rd = op_readpc(); - if(wr == 0x00){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + wr = op_readdp(dp); + break; + case 3: + op_writedp(dp, --wr); + break; + case 4: + rd = op_readpc(); + if(wr == 0x00){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xfe: { - rd = op_readpc(); - op_io(); - regs.y--; - op_io(); - if(regs.y == 0x00){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + op_io(); + regs.y--; + break; + case 3: + op_io(); + if(regs.y == 0x00){ opcode_cycle = 0; break; } + break; + case 4: + op_io(); + break; + case 5: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x5f: { - rd = op_readpc(); - rd |= op_readpc() << 8; - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + rd |= op_readpc() << 8; + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x1f: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - dp += regs.x; - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + dp += regs.x; + break; + case 4: + rd = op_readaddr(dp); + break; + case 5: + rd |= op_readaddr(dp + 1) << 8; + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x3f: { - rd = op_readpc(); - rd |= op_readpc() << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + rd |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x4f: { - rd = op_readpc(); - op_io(2); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = 0xff00 | rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + op_io(); + break; + case 4: + op_writestack(regs.pc >> 8); + break; + case 5: + op_writestack(regs.pc); + regs.pc = 0xff00 | rd; + opcode_cycle = 0; + break; + } break; } case 0x01: { - dp = 0xffde - (0 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (0 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x11: { - dp = 0xffde - (1 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (1 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x21: { - dp = 0xffde - (2 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (2 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x31: { - dp = 0xffde - (3 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (3 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x41: { - dp = 0xffde - (4 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (4 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x51: { - dp = 0xffde - (5 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (5 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x61: { - dp = 0xffde - (6 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (6 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x71: { - dp = 0xffde - (7 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (7 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x81: { - dp = 0xffde - (8 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (8 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x91: { - dp = 0xffde - (9 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (9 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0xa1: { - dp = 0xffde - (10 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (10 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0xb1: { - dp = 0xffde - (11 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (11 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0xc1: { - dp = 0xffde - (12 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (12 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0xd1: { - dp = 0xffde - (13 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (13 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0xe1: { - dp = 0xffde - (14 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (14 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0xf1: { - dp = 0xffde - (15 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (15 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x0f: { - rd = op_readaddr(0xffde); - rd |= op_readaddr(0xffdf) << 8; - op_io(2); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - op_writestack(regs.p); - regs.pc = rd; - regs.p.b = 1; - regs.p.i = 0; + switch(opcode_cycle++) { + case 1: + rd = op_readaddr(0xffde); + break; + case 2: + rd |= op_readaddr(0xffdf) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_writestack(regs.pc >> 8); + break; + case 6: + op_writestack(regs.pc); + break; + case 7: + op_writestack(regs.p); + regs.pc = rd; + regs.p.b = 1; + regs.p.i = 0; + opcode_cycle = 0; + break; + } break; } case 0x6f: { - rd = op_readstack(); - rd |= op_readstack() << 8; - op_io(2); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + rd = op_readstack(); + break; + case 2: + rd |= op_readstack() << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x7f: { - regs.p = op_readstack(); - rd = op_readstack(); - rd |= op_readstack() << 8; - op_io(2); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + regs.p = op_readstack(); + break; + case 2: + rd = op_readstack(); + break; + case 3: + rd |= op_readstack() << 8; + break; + case 4: + op_io(); + break; + case 5: + op_io(); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } diff --git a/apu/bapu/smp/core/opcycle_read.cpp b/apu/bapu/smp/core/opcycle_read.cpp index 2a16a3c8..6c19f3a9 100644 --- a/apu/bapu/smp/core/opcycle_read.cpp +++ b/apu/bapu/smp/core/opcycle_read.cpp @@ -1,744 +1,1599 @@ case 0x88: { - rd = op_readpc(); - regs.a = op_adc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x28: { - rd = op_readpc(); - regs.a = op_and(regs.a, rd); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x68: { - rd = op_readpc(); - regs.a = op_cmp(regs.a, rd); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xc8: { - rd = op_readpc(); - regs.x = op_cmp(regs.x, rd); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.x = op_cmp(regs.x, rd); + opcode_cycle = 0; + break; + } break; } case 0xad: { - rd = op_readpc(); - regs.y = op_cmp(regs.y, rd); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.y = op_cmp(regs.y, rd); + opcode_cycle = 0; + break; + } break; } case 0x48: { - rd = op_readpc(); - regs.a = op_eor(regs.a, rd); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x08: { - rd = op_readpc(); - regs.a = op_or(regs.a, rd); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xa8: { - rd = op_readpc(); - regs.a = op_sbc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x86: { - op_io(); - rd = op_readdp(regs.x); - regs.a = op_adc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x26: { - op_io(); - rd = op_readdp(regs.x); - regs.a = op_and(regs.a, rd); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x66: { - op_io(); - rd = op_readdp(regs.x); - regs.a = op_cmp(regs.a, rd); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x46: { - op_io(); - rd = op_readdp(regs.x); - regs.a = op_eor(regs.a, rd); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x06: { - op_io(); - rd = op_readdp(regs.x); - regs.a = op_or(regs.a, rd); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xa6: { - op_io(); - rd = op_readdp(regs.x); - regs.a = op_sbc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x84: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.a = op_adc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x24: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.a = op_and(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x64: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.a = op_cmp(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x3e: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.x = op_cmp(regs.x, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.x = op_cmp(regs.x, rd); + opcode_cycle = 0; + break; + } break; } case 0x7e: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.y = op_cmp(regs.y, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.y = op_cmp(regs.y, rd); + opcode_cycle = 0; + break; + } break; } case 0x44: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.a = op_eor(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x04: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.a = op_or(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xa4: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.a = op_sbc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x94: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - regs.a = op_adc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x34: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - regs.a = op_and(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x74: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - regs.a = op_cmp(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x54: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - regs.a = op_eor(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x14: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - regs.a = op_or(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xb4: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - regs.a = op_sbc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x85: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.a = op_adc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x25: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.a = op_and(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x65: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.a = op_cmp(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x1e: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.x = op_cmp(regs.x, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.x = op_cmp(regs.x, rd); + opcode_cycle = 0; + break; + } break; } case 0x5e: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.y = op_cmp(regs.y, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.y = op_cmp(regs.y, rd); + opcode_cycle = 0; + break; + } break; } case 0x45: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.a = op_eor(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x05: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.a = op_or(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xa5: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.a = op_sbc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x95: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.x); - regs.a = op_adc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x96: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.y); - regs.a = op_adc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x35: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.x); - regs.a = op_and(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x36: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.y); - regs.a = op_and(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x75: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.x); - regs.a = op_cmp(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x76: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.y); - regs.a = op_cmp(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x55: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.x); - regs.a = op_eor(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x56: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.y); - regs.a = op_eor(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x15: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.x); - regs.a = op_or(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x16: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.y); - regs.a = op_or(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xb5: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.x); - regs.a = op_sbc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xb6: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.y); - regs.a = op_sbc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x87: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp); - regs.a = op_adc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x27: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp); - regs.a = op_and(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x67: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp); - regs.a = op_cmp(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x47: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp); - regs.a = op_eor(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x07: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp); - regs.a = op_or(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xa7: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp); - regs.a = op_sbc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x97: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp + regs.y); - regs.a = op_adc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x37: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp + regs.y); - regs.a = op_and(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x77: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp + regs.y); - regs.a = op_cmp(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x57: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp + regs.y); - regs.a = op_eor(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x17: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp + regs.y); - regs.a = op_or(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xb7: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp + regs.y); - regs.a = op_sbc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x99: { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = op_adc(wr, rd); - (1) ? op_writedp(regs.x, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_adc(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x39: { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = op_and(wr, rd); - (1) ? op_writedp(regs.x, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_and(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x79: { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = op_cmp(wr, rd); - (0) ? op_writedp(regs.x, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_cmp(wr, rd); + break; + case 4: + (0) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x59: { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = op_eor(wr, rd); - (1) ? op_writedp(regs.x, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_eor(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x19: { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = op_or(wr, rd); - (1) ? op_writedp(regs.x, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_or(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0xb9: { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = op_sbc(wr, rd); - (1) ? op_writedp(regs.x, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_sbc(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x89: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_adc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x29: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_and(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x69: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_cmp(wr, rd); - (0) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x49: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_eor(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x09: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_or(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0xa9: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_sbc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x98: { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_adc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x38: { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_and(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x78: { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_cmp(wr, rd); - (0) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x58: { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_eor(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x18: { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_or(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0xb8: { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_sbc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x7a: { - dp = op_readpc(); - rd = op_readdp(dp); - op_io(); - rd |= op_readdp(dp + 1) << 8; - regs.ya = op_addw(regs.ya, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + op_io(); + break; + case 4: + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_addw(regs.ya, rd); + opcode_cycle = 0; + break; + } break; } case 0x9a: { - dp = op_readpc(); - rd = op_readdp(dp); - op_io(); - rd |= op_readdp(dp + 1) << 8; - regs.ya = op_subw(regs.ya, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + op_io(); + break; + case 4: + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_subw(regs.ya, rd); + opcode_cycle = 0; + break; + } break; } case 0x5a: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= op_readdp(dp + 1) << 8; - op_cmpw(regs.ya, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= op_readdp(dp + 1) << 8; + op_cmpw(regs.ya, rd); + opcode_cycle = 0; + break; + } break; } case 0x4a: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - regs.p.c = regs.p.c & !!(rd & (1 << bit)); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !!(rd & (1 << bit)); + opcode_cycle = 0; + break; + } break; } case 0x6a: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - regs.p.c = regs.p.c & !(rd & (1 << bit)); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !(rd & (1 << bit)); + opcode_cycle = 0; + break; + } break; } case 0x8a: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - op_io(); - regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + break; + case 4: + op_io(); + regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); + opcode_cycle = 0; + break; + } break; } case 0xea: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - rd ^= (1 << bit); - op_writeaddr(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + rd ^= (1 << bit); + break; + case 4: + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x0a: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - op_io(); - regs.p.c = regs.p.c | !!(rd & (1 << bit)); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + break; + case 4: + op_io(); + regs.p.c = regs.p.c | !!(rd & (1 << bit)); + opcode_cycle = 0; + break; + } break; } case 0x2a: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - op_io(); - regs.p.c = regs.p.c | !(rd & (1 << bit)); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + break; + case 4: + op_io(); + regs.p.c = regs.p.c | !(rd & (1 << bit)); + opcode_cycle = 0; + break; + } break; } diff --git a/apu/bapu/smp/core/opcycle_rmw.cpp b/apu/bapu/smp/core/opcycle_rmw.cpp index 9b0dd2fb..eca62f02 100644 --- a/apu/bapu/smp/core/opcycle_rmw.cpp +++ b/apu/bapu/smp/core/opcycle_rmw.cpp @@ -1,262 +1,550 @@ case 0xbc: { - op_io(); - regs.a = op_inc(regs.a); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_inc(regs.a); + opcode_cycle = 0; + break; + } break; } case 0x3d: { - op_io(); - regs.x = op_inc(regs.x); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.x = op_inc(regs.x); + opcode_cycle = 0; + break; + } break; } case 0xfc: { - op_io(); - regs.y = op_inc(regs.y); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.y = op_inc(regs.y); + opcode_cycle = 0; + break; + } break; } case 0x9c: { - op_io(); - regs.a = op_dec(regs.a); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_dec(regs.a); + opcode_cycle = 0; + break; + } break; } case 0x1d: { - op_io(); - regs.x = op_dec(regs.x); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.x = op_dec(regs.x); + opcode_cycle = 0; + break; + } break; } case 0xdc: { - op_io(); - regs.y = op_dec(regs.y); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.y = op_dec(regs.y); + opcode_cycle = 0; + break; + } break; } case 0x1c: { - op_io(); - regs.a = op_asl(regs.a); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_asl(regs.a); + opcode_cycle = 0; + break; + } break; } case 0x5c: { - op_io(); - regs.a = op_lsr(regs.a); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_lsr(regs.a); + opcode_cycle = 0; + break; + } break; } case 0x3c: { - op_io(); - regs.a = op_rol(regs.a); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_rol(regs.a); + opcode_cycle = 0; + break; + } break; } case 0x7c: { - op_io(); - regs.a = op_ror(regs.a); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_ror(regs.a); + opcode_cycle = 0; break; + } + break; } case 0xab: { - dp = op_readpc(); - rd = op_readdp(dp); - rd = op_inc(rd); - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_inc(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x8b: { - dp = op_readpc(); - rd = op_readdp(dp); - rd = op_dec(rd); - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_dec(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x0b: { - dp = op_readpc(); - rd = op_readdp(dp); - rd = op_asl(rd); - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_asl(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x4b: { - dp = op_readpc(); - rd = op_readdp(dp); - rd = op_lsr(rd); - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_lsr(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x2b: { - dp = op_readpc(); - rd = op_readdp(dp); - rd = op_rol(rd); - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_rol(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x6b: { - dp = op_readpc(); - rd = op_readdp(dp); - rd = op_ror(rd); - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_ror(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0xbb: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = op_inc(rd); - op_writedp(dp + regs.x, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_inc(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } break; } case 0x9b: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = op_dec(rd); - op_writedp(dp + regs.x, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_dec(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } break; } case 0x1b: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = op_asl(rd); - op_writedp(dp + regs.x, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_asl(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } break; } case 0x5b: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = op_lsr(rd); - op_writedp(dp + regs.x, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_lsr(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } break; } case 0x3b: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = op_rol(rd); - op_writedp(dp + regs.x, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_rol(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } break; } case 0x7b: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = op_ror(rd); - op_writedp(dp + regs.x, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_ror(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } break; } case 0xac: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - rd = op_inc(rd); - op_writeaddr(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_inc(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x8c: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - rd = op_dec(rd); - op_writeaddr(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_dec(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x0c: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - rd = op_asl(rd); - op_writeaddr(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_asl(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x4c: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - rd = op_lsr(rd); - op_writeaddr(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_lsr(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x2c: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - rd = op_rol(rd); - op_writeaddr(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_rol(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x6c: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - rd = op_ror(rd); - op_writeaddr(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_ror(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x0e: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.p.n = !!((regs.a - rd) & 0x80); - regs.p.z = ((regs.a - rd) == 0); - op_readaddr(dp); - op_writeaddr(dp, rd | regs.a); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + break; + case 4: + op_readaddr(dp); + break; + case 5: + op_writeaddr(dp, rd | regs.a); + opcode_cycle = 0; + break; + } break; } case 0x4e: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.p.n = !!((regs.a - rd) & 0x80); - regs.p.z = ((regs.a - rd) == 0); - op_readaddr(dp); - op_writeaddr(dp, rd &~ regs.a); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + break; + case 4: + op_readaddr(dp); + break; + case 5: + op_writeaddr(dp, rd &~ regs.a); + opcode_cycle = 0; + break; + } break; } case 0x3a: { - dp = op_readpc(); - rd = op_readdp(dp); - rd++; - op_writedp(dp++, rd); - rd += op_readdp(dp) << 8; - op_writedp(dp, rd >> 8); - regs.p.n = !!(rd & 0x8000); - regs.p.z = (rd == 0); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + rd++; + break; + case 3: + op_writedp(dp++, rd); + break; + case 4: + rd += op_readdp(dp) << 8; + break; + case 5: + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + opcode_cycle = 0; + break; + } break; } case 0x1a: { - dp = op_readpc(); - rd = op_readdp(dp); - rd--; - op_writedp(dp++, rd); - rd += op_readdp(dp) << 8; - op_writedp(dp, rd >> 8); - regs.p.n = !!(rd & 0x8000); - regs.p.z = (rd == 0); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + rd--; + break; + case 3: + op_writedp(dp++, rd); + break; + case 4: + rd += op_readdp(dp) << 8; + break; + case 5: + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + opcode_cycle = 0; + break; + } break; } diff --git a/apu/bapu/smp/core/oppseudo_misc.cpp b/apu/bapu/smp/core/oppseudo_misc.cpp new file mode 100644 index 00000000..d266ef92 --- /dev/null +++ b/apu/bapu/smp/core/oppseudo_misc.cpp @@ -0,0 +1,311 @@ +case 0x00: { + op_io(); + break; +} + +case 0xef: { + op_io(2); + regs.pc--; + break; +} + +case 0xff: { + op_io(2); + regs.pc--; + break; +} + +case 0x9f: { + op_io(4); + regs.a = (regs.a >> 4) | (regs.a << 4); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xdf: { + op_io(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); + break; +} + +case 0xbe: { + op_io(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); + break; +} + +case 0x60: { + op_io(); + regs.p.c = 0; + break; +} + +case 0x20: { + op_io(); + regs.p.p = 0; + break; +} + +case 0x80: { + op_io(); + regs.p.c = 1; + break; +} + +case 0x40: { + op_io(); + regs.p.p = 1; + break; +} + +case 0xe0: { + op_io(); + regs.p.v = 0; + regs.p.h = 0; + break; +} + +case 0xed: { + op_io(2); + regs.p.c = !regs.p.c; + break; +} + +case 0xa0: { + op_io(2); + regs.p.i = 1; + break; +} + +case 0xc0: { + op_io(2); + regs.p.i = 0; + break; +} + +case 0x02: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x01; + op_writedp(dp, rd); + break; +} + +case 0x12: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x01; + op_writedp(dp, rd); + break; +} + +case 0x22: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x02; + op_writedp(dp, rd); + break; +} + +case 0x32: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x02; + op_writedp(dp, rd); + break; +} + +case 0x42: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x04; + op_writedp(dp, rd); + break; +} + +case 0x52: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x04; + op_writedp(dp, rd); + break; +} + +case 0x62: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x08; + op_writedp(dp, rd); + break; +} + +case 0x72: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x08; + op_writedp(dp, rd); + break; +} + +case 0x82: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x10; + op_writedp(dp, rd); + break; +} + +case 0x92: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x10; + op_writedp(dp, rd); + break; +} + +case 0xa2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x20; + op_writedp(dp, rd); + break; +} + +case 0xb2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x20; + op_writedp(dp, rd); + break; +} + +case 0xc2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x40; + op_writedp(dp, rd); + break; +} + +case 0xd2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x40; + op_writedp(dp, rd); + break; +} + +case 0xe2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x80; + op_writedp(dp, rd); + break; +} + +case 0xf2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x80; + op_writedp(dp, rd); + break; +} + +case 0x2d: { + op_io(2); + op_writestack(regs.a); + break; +} + +case 0x4d: { + op_io(2); + op_writestack(regs.x); + break; +} + +case 0x6d: { + op_io(2); + op_writestack(regs.y); + break; +} + +case 0x0d: { + op_io(2); + op_writestack(regs.p); + break; +} + +case 0xae: { + op_io(2); + regs.a = op_readstack(); + break; +} + +case 0xce: { + op_io(2); + regs.x = op_readstack(); + break; +} + +case 0xee: { + op_io(2); + regs.y = op_readstack(); + break; +} + +case 0x8e: { + op_io(2); + regs.p = op_readstack(); + break; +} + +case 0xcf: { + op_io(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); + break; +} + +case 0x9e: { + op_io(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 S-SMP in this case + regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); + regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); + } + //result is set based on a (quotient) only + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + diff --git a/apu/bapu/smp/core/oppseudo_mov.cpp b/apu/bapu/smp/core/oppseudo_mov.cpp new file mode 100644 index 00000000..fd44ad29 --- /dev/null +++ b/apu/bapu/smp/core/oppseudo_mov.cpp @@ -0,0 +1,705 @@ +case 0x7d: { + op_io(); + regs.a = regs.x; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xdd: { + op_io(); + regs.a = regs.y; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0x5d: { + op_io(); + regs.x = regs.a; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + break; +} + +case 0xfd: { + op_io(); + regs.y = regs.a; + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + break; +} + +case 0x9d: { + op_io(); + regs.x = regs.sp; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + break; +} + +case 0xbd: { + op_io(); + regs.sp = regs.x; + break; +} + +case 0xe8: { + regs.a = op_readpc(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xcd: { + regs.x = op_readpc(); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + break; +} + +case 0x8d: { + regs.y = op_readpc(); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + break; +} + +case 0xe6: { + switch(++opcode_cycle) { + case 1: + op_io(); + break; + case 2: + regs.a = op_readdp(regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xbf: { + switch(++opcode_cycle) { + case 1: + op_io(); + break; + case 2: + regs.a = op_readdp(regs.x++); + op_io(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe4: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + break; + case 2: + regs.a = op_readdp(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf8: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + break; + case 2: + regs.x = op_readdp(sp); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xeb: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + break; + case 2: + regs.y = op_readdp(sp); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf4: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + op_io(); + break; + case 2: + regs.a = op_readdp(sp + regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf9: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + op_io(); + break; + case 2: + regs.x = op_readdp(sp + regs.y); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xfb: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + op_io(); + break; + case 2: + regs.y = op_readdp(sp + regs.x); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe5: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + break; + case 2: + sp |= op_readpc() << 8; + break; + case 3: + regs.a = op_readaddr(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe9: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + sp |= op_readpc() << 8; + break; + case 2: + regs.x = op_readaddr(sp); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xec: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + sp |= op_readpc() << 8; + break; + case 2: + regs.y = op_readaddr(sp); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf5: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + sp |= op_readpc() << 8; + op_io(); + break; + case 2: + regs.a = op_readaddr(sp + regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf6: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + sp |= op_readpc() << 8; + op_io(); + break; + case 2: + regs.a = op_readaddr(sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe7: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc() + regs.x; + op_io(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + sp |= op_readdp(dp + 1) << 8; + break; + case 4: + regs.a = op_readaddr(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf7: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + op_io(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + sp |= op_readdp(dp + 1) << 8; + break; + case 4: + regs.a = op_readaddr(sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xfa: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x8f: { + switch(++opcode_cycle) { + case 1: + rd = op_readpc(); + dp = op_readpc(); + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc6: { + switch(++opcode_cycle) { + case 1: + op_io(); + break; + case 2: + op_readdp(regs.x); + break; + case 3: + op_writedp(regs.x, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xaf: { + switch(++opcode_cycle) { + case 1: + op_io(2); + case 2: + op_writedp(regs.x++, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc4: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd8: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.x); + opcode_cycle = 0; + break; + } + break; +} + +case 0xcb: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd4: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + op_io(); + dp += regs.x; + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd9: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + op_io(); + dp += regs.y; + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.x); + opcode_cycle = 0; + break; + } + break; +} + +case 0xdb: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + op_io(); + dp += regs.x; + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc5: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_readaddr(dp); + break; + case 4: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc9: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_readaddr(dp); + break; + case 4: + op_writeaddr(dp, regs.x); + opcode_cycle = 0; + break; + } + break; +} + +case 0xcc: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_readaddr(dp); + break; + case 4: + op_writeaddr(dp, regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd5: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + dp += regs.x; + break; + case 2: + op_readaddr(dp); + break; + case 3: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd6: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + dp += regs.y; + break; + case 2: + op_readaddr(dp); + break; + case 3: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc7: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + op_io(); + sp += regs.x; + break; + case 2: + dp = op_readdp(sp); + break; + case 3: + dp |= op_readdp(sp + 1) << 8; + break; + case 4: + op_readaddr(dp); + break; + case 5: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd7: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + break; + case 2: + dp = op_readdp(sp); + break; + case 3: + dp |= op_readdp(sp + 1) << 8; + op_io(); + dp += regs.y; + break; + case 4: + op_readaddr(dp); + break; + case 5: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xba: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + break; + case 2: + regs.a = op_readdp(sp); + op_io(); + break; + case 3: + regs.y = op_readdp(sp + 1); + regs.p.n = !!(regs.ya & 0x8000); + regs.p.z = (regs.ya == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xda: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.a); + break; + case 4: + op_writedp(dp + 1, regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0xaa: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + sp |= op_readpc() << 8; + break; + case 2: + bit = sp >> 13; + sp &= 0x1fff; + rd = op_readaddr(sp); + regs.p.c = !!(rd & (1 << bit)); + opcode_cycle = 0; + break; + } + break; +} + +case 0xca: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + dp |= op_readpc() << 8; + break; + case 2: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + if(regs.p.c)rd |= (1 << bit); + else rd &= ~(1 << bit); + op_io(); + break; + case 3: + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + diff --git a/apu/bapu/smp/core/oppseudo_pc.cpp b/apu/bapu/smp/core/oppseudo_pc.cpp new file mode 100644 index 00000000..022179d1 --- /dev/null +++ b/apu/bapu/smp/core/oppseudo_pc.cpp @@ -0,0 +1,536 @@ +case 0x2f: { + rd = op_readpc(); + if(0){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xf0: { + rd = op_readpc(); + if(!regs.p.z){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xd0: { + rd = op_readpc(); + if(regs.p.z){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xb0: { + rd = op_readpc(); + if(!regs.p.c){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x90: { + rd = op_readpc(); + if(regs.p.c){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x70: { + rd = op_readpc(); + if(!regs.p.v){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x50: { + rd = op_readpc(); + if(regs.p.v){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x30: { + rd = op_readpc(); + if(!regs.p.n){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x10: { + rd = op_readpc(); + if(regs.p.n){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x03: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x01) != 0x01){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x13: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x01) == 0x01){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x23: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x02) != 0x02){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x33: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x02) == 0x02){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x43: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x04) != 0x04){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x53: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x04) == 0x04){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x63: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x08) != 0x08){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x73: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x08) == 0x08){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x83: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x10) != 0x10){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x93: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x10) == 0x10){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xa3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x20) != 0x20){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xb3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x20) == 0x20){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xc3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x40) != 0x40){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xd3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x40) == 0x40){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xe3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x80) != 0x80){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xf3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x80) == 0x80){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x2e: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if(regs.a == sp){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xde: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp + regs.x); + rd = op_readpc(); + op_io(); + if(regs.a == sp){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x6e: { + dp = op_readpc(); + wr = op_readdp(dp); + op_writedp(dp, --wr); + rd = op_readpc(); + if(wr == 0x00){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xfe: { + rd = op_readpc(); + op_io(); + regs.y--; + op_io(); + if(regs.y == 0x00){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x5f: { + rd = op_readpc(); + rd |= op_readpc() << 8; + regs.pc = rd; + break; +} + +case 0x1f: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + dp += regs.x; + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + regs.pc = rd; + break; +} + +case 0x3f: { + rd = op_readpc(); + rd |= op_readpc() << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x4f: { + rd = op_readpc(); + op_io(2); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = 0xff00 | rd; + break; +} + +case 0x01: { + dp = 0xffde - (0 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x11: { + dp = 0xffde - (1 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x21: { + dp = 0xffde - (2 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x31: { + dp = 0xffde - (3 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x41: { + dp = 0xffde - (4 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x51: { + dp = 0xffde - (5 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x61: { + dp = 0xffde - (6 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x71: { + dp = 0xffde - (7 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x81: { + dp = 0xffde - (8 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x91: { + dp = 0xffde - (9 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xa1: { + dp = 0xffde - (10 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xb1: { + dp = 0xffde - (11 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xc1: { + dp = 0xffde - (12 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xd1: { + dp = 0xffde - (13 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xe1: { + dp = 0xffde - (14 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xf1: { + dp = 0xffde - (15 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x0f: { + rd = op_readaddr(0xffde); + rd |= op_readaddr(0xffdf) << 8; + op_io(2); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + op_writestack(regs.p); + regs.pc = rd; + regs.p.b = 1; + regs.p.i = 0; + break; +} + +case 0x6f: { + rd = op_readstack(); + rd |= op_readstack() << 8; + op_io(2); + regs.pc = rd; + break; +} + +case 0x7f: { + regs.p = op_readstack(); + rd = op_readstack(); + rd |= op_readstack() << 8; + op_io(2); + regs.pc = rd; + break; +} + diff --git a/apu/bapu/smp/core/oppseudo_read.cpp b/apu/bapu/smp/core/oppseudo_read.cpp new file mode 100644 index 00000000..2a16a3c8 --- /dev/null +++ b/apu/bapu/smp/core/oppseudo_read.cpp @@ -0,0 +1,744 @@ +case 0x88: { + rd = op_readpc(); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x28: { + rd = op_readpc(); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x68: { + rd = op_readpc(); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0xc8: { + rd = op_readpc(); + regs.x = op_cmp(regs.x, rd); + break; +} + +case 0xad: { + rd = op_readpc(); + regs.y = op_cmp(regs.y, rd); + break; +} + +case 0x48: { + rd = op_readpc(); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x08: { + rd = op_readpc(); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa8: { + rd = op_readpc(); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x86: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x26: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x66: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x46: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x06: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa6: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x84: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x24: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x64: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x3e: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.x = op_cmp(regs.x, rd); + break; +} + +case 0x7e: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.y = op_cmp(regs.y, rd); + break; +} + +case 0x44: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x04: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa4: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x94: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x34: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x74: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x54: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x14: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xb4: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x85: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x25: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x65: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x1e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.x = op_cmp(regs.x, rd); + break; +} + +case 0x5e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.y = op_cmp(regs.y, rd); + break; +} + +case 0x45: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x05: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa5: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x95: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x96: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x35: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x36: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x75: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x76: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x55: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x56: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x15: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_or(regs.a, rd); + break; +} + +case 0x16: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xb5: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0xb6: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x87: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x27: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x67: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x47: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x07: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa7: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x97: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x37: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x77: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x57: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x17: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xb7: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x99: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_adc(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x39: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_and(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x79: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_cmp(wr, rd); + (0) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x59: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_eor(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x19: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_or(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0xb9: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_sbc(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x89: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x29: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x69: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x49: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x09: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0xa9: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x98: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x38: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x78: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x58: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x18: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0xb8: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x7a: { + dp = op_readpc(); + rd = op_readdp(dp); + op_io(); + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_addw(regs.ya, rd); + break; +} + +case 0x9a: { + dp = op_readpc(); + rd = op_readdp(dp); + op_io(); + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_subw(regs.ya, rd); + break; +} + +case 0x5a: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= op_readdp(dp + 1) << 8; + op_cmpw(regs.ya, rd); + break; +} + +case 0x4a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !!(rd & (1 << bit)); + break; +} + +case 0x6a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !(rd & (1 << bit)); + break; +} + +case 0x8a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); + break; +} + +case 0xea: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + rd ^= (1 << bit); + op_writeaddr(dp, rd); + break; +} + +case 0x0a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c | !!(rd & (1 << bit)); + break; +} + +case 0x2a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c | !(rd & (1 << bit)); + break; +} + diff --git a/apu/bapu/smp/core/oppseudo_rmw.cpp b/apu/bapu/smp/core/oppseudo_rmw.cpp new file mode 100644 index 00000000..9b0dd2fb --- /dev/null +++ b/apu/bapu/smp/core/oppseudo_rmw.cpp @@ -0,0 +1,262 @@ +case 0xbc: { + op_io(); + regs.a = op_inc(regs.a); + break; +} + +case 0x3d: { + op_io(); + regs.x = op_inc(regs.x); + break; +} + +case 0xfc: { + op_io(); + regs.y = op_inc(regs.y); + break; +} + +case 0x9c: { + op_io(); + regs.a = op_dec(regs.a); + break; +} + +case 0x1d: { + op_io(); + regs.x = op_dec(regs.x); + break; +} + +case 0xdc: { + op_io(); + regs.y = op_dec(regs.y); + break; +} + +case 0x1c: { + op_io(); + regs.a = op_asl(regs.a); + break; +} + +case 0x5c: { + op_io(); + regs.a = op_lsr(regs.a); + break; +} + +case 0x3c: { + op_io(); + regs.a = op_rol(regs.a); + break; +} + +case 0x7c: { + op_io(); + regs.a = op_ror(regs.a); + break; +} + +case 0xab: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_inc(rd); + op_writedp(dp, rd); + break; +} + +case 0x8b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_dec(rd); + op_writedp(dp, rd); + break; +} + +case 0x0b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_asl(rd); + op_writedp(dp, rd); + break; +} + +case 0x4b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_lsr(rd); + op_writedp(dp, rd); + break; +} + +case 0x2b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_rol(rd); + op_writedp(dp, rd); + break; +} + +case 0x6b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_ror(rd); + op_writedp(dp, rd); + break; +} + +case 0xbb: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_inc(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x9b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_dec(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x1b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_asl(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x5b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_lsr(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x3b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_rol(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x7b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_ror(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0xac: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_inc(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x8c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_dec(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x0c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_asl(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x4c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_lsr(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x2c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_rol(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x6c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_ror(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x0e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + op_readaddr(dp); + op_writeaddr(dp, rd | regs.a); + break; +} + +case 0x4e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + op_readaddr(dp); + op_writeaddr(dp, rd &~ regs.a); + break; +} + +case 0x3a: { + dp = op_readpc(); + rd = op_readdp(dp); + rd++; + op_writedp(dp++, rd); + rd += op_readdp(dp) << 8; + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + break; +} + +case 0x1a: { + dp = op_readpc(); + rd = op_readdp(dp); + rd--; + op_writedp(dp++, rd); + rd += op_readdp(dp) << 8; + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + break; +} + diff --git a/apu/bapu/smp/smp.cpp b/apu/bapu/smp/smp.cpp index a8092fcb..1a20b7ae 100644 --- a/apu/bapu/smp/smp.cpp +++ b/apu/bapu/smp/smp.cpp @@ -1,4 +1,5 @@ #define CYCLE_ACCURATE +#define PSEUDO_CYCLE #include From 1678b71d1e855e7204ab579b0a166f882c205859 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 14 Dec 2011 02:46:12 -0600 Subject: [PATCH 29/33] Prioritize GLX_EXT_swap_control over GLX_SGI_swap_control. --- gtk/src/gtk_display_driver_opengl.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/gtk/src/gtk_display_driver_opengl.cpp b/gtk/src/gtk_display_driver_opengl.cpp index 5e692c43..153bfc17 100644 --- a/gtk/src/gtk_display_driver_opengl.cpp +++ b/gtk/src/gtk_display_driver_opengl.cpp @@ -905,16 +905,19 @@ S9xOpenGLDisplayDriver::swap_control (int enable) queried = TRUE; } - if (glSwapInterval) - { - glSwapInterval (enable); - } - if (glXSwapIntervalEXT) { + if (glSwapInterval) + glSwapInterval (0); + glXSwapIntervalEXT (display, xwindow, enable); } + else if (glSwapInterval) + { + glSwapInterval (enable); + } + return; } From 1b0c82ed3b2b5aaf1b120cf883fa24ba1dcd6031 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 14 Dec 2011 02:47:28 -0600 Subject: [PATCH 30/33] Clean up configure.ac slightly. --- gtk/configure.ac | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/gtk/configure.ac b/gtk/configure.ac index f946b695..95024a23 100644 --- a/gtk/configure.ac +++ b/gtk/configure.ac @@ -342,15 +342,6 @@ if test yes = "$with_jma_decomp"; then JMA=yes fi -dnl FIXME: There is a third case (OLD) that is missed with this. -if test yes = "$with_newblend"; then - CFLAGS="$CFLAGS -DNEW_COLOUR_BLENDING" -else - #OLD_COLOUR_BLENDING hasn't been default for a while - # SYSDEFINES="$SYSDEFINES"' -DOLD_COLOUR_BLENDING' - : -fi - if test yes = "$with_zlib"; then AC_CHECK_HEADERS(zlib.h) AC_CHECK_LIB(z, gzread, [ @@ -432,7 +423,7 @@ if test $ac_cv_my_sar_int8 = yes && \ CFLAGS="$CFLAGS -DRIGHTSHIFT_IS_SAR" fi -CFLAGS="$CFLAGS -DCPU_SHUTDOWN -DSPC700_SHUTDOWN -DNO_INLINE_SET_GET -DUNZIP_SUPPORT -DSPC700_C -I. -I.. -I../unzip" +CFLAGS="$CFLAGS -DUNZIP_SUPPORT -DSPC700_C -I. -I.. -I../unzip" CXXFLAGS="$CFLAGS" From 2337ab3ed01e56bcdd77608319b732527788392c Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 14 Dec 2011 02:47:44 -0600 Subject: [PATCH 31/33] Optimize hermite resampler slightly. The vtable lookup on read probably still hurts fine-granularity sound systems like OSS. --- apu/hermite_resampler.h | 46 ++++++++++++----------------------------- 1 file changed, 13 insertions(+), 33 deletions(-) diff --git a/apu/hermite_resampler.h b/apu/hermite_resampler.h index 30ee1032..eda547f4 100644 --- a/apu/hermite_resampler.h +++ b/apu/hermite_resampler.h @@ -14,25 +14,20 @@ class HermiteResampler : public Resampler { protected: - double r_step; - double r_frac; - int r_left[4], r_right[4]; + float r_step; + float r_frac; + int r_left[4], r_right[4]; - double - hermite (double mu1, double a, double b, double c, double d) + static inline float + hermite (float mu1, float a, float b, float c, float d) { - const double tension = 0.0; //-1 = low, 0 = normal, 1 = high - const double bias = 0.0; //-1 = left, 0 = even, 1 = right - - double mu2, mu3, m0, m1, a0, a1, a2, a3; + float mu2, mu3, m0, m1, a0, a1, a2, a3; mu2 = mu1 * mu1; mu3 = mu2 * mu1; - m0 = (b - a) * (1 + bias) * (1 - tension) / 2; - m0 += (c - b) * (1 - bias) * (1 - tension) / 2; - m1 = (c - b) * (1 + bias) * (1 - tension) / 2; - m1 += (d - c) * (1 - bias) * (1 - tension) / 2; + m0 = (c - a) * 0.5; + m1 = (d - b) * 0.5; a0 = +2 * mu3 - 3 * mu2 + 1; a1 = mu3 - 2 * mu2 + mu1; @@ -72,6 +67,7 @@ class HermiteResampler : public Resampler read (short *data, int num_samples) { int i_position = start >> 1; + int max_samples = buffer_size >> 1; short *internal_buffer = (short *) buffer; int o_position = 0; int consumed = 0; @@ -80,22 +76,6 @@ class HermiteResampler : public Resampler { int s_left = internal_buffer[i_position]; int s_right = internal_buffer[i_position + 1]; - int max_samples = buffer_size >> 1; - const double margin_of_error = 1.0e-10; - - if (fabs(r_step - 1.0) < margin_of_error) - { - data[o_position] = (short) s_left; - data[o_position + 1] = (short) s_right; - - o_position += 2; - i_position += 2; - if (i_position >= max_samples) - i_position -= max_samples; - consumed += 2; - - continue; - } while (r_frac <= 1.0 && o_position < num_samples) { @@ -113,14 +93,14 @@ class HermiteResampler : public Resampler r_left [1] = r_left [2]; r_left [2] = r_left [3]; r_left [3] = s_left; - + r_right[0] = r_right[1]; r_right[1] = r_right[2]; r_right[2] = r_right[3]; - r_right[3] = s_right; - + r_right[3] = s_right; + r_frac -= 1.0; - + i_position += 2; if (i_position >= max_samples) i_position -= max_samples; From a66f10d9e405e3545100c27f11dc3c2d06d0b475 Mon Sep 17 00:00:00 2001 From: OV2 Date: Fri, 20 Jan 2012 04:24:36 +0100 Subject: [PATCH 32/33] Convert old savestates for new smp --- apu/apu.cpp | 112 ++++++++++++ apu/apu.h | 1 + port.h | 10 +- snapshot.cpp | 8 +- snapshot.h | 4 +- win32/snes9xw.vcproj | 402 ++++++------------------------------------- 6 files changed, 179 insertions(+), 358 deletions(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index 237f3939..bc9f616a 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -637,6 +637,118 @@ void S9xAPULoadState (uint8 *block) memcpy (SNES::cpu.registers, ptr, 4); } +static void to_var_from_buf (uint8 **buf, void *var, size_t size) +{ + memcpy(var, *buf, size); + *buf += size; +} + +#undef IF_0_THEN_256 +#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1) +void S9xAPULoadBlarggState(uint8 *oldblock) +{ + uint8 *ptr = oldblock; + + SNES::SPC_State_Copier copier(&ptr,to_var_from_buf); + + copier.copy(SNES::smp.apuram,0x10000); // RAM + + uint8_t regs_in [0x10]; + uint8_t regs [0x10]; + uint16_t pc, spc_time, dsp_time; + uint8_t a,x,y,psw,sp; + + copier.copy(regs,0x10); // REGS + copier.copy(regs_in,0x10); // REGS_IN + + // CPU Regs + pc = copier.copy_int( 0, sizeof(uint16_t) ); + a = copier.copy_int( 0, sizeof(uint8_t) ); + x = copier.copy_int( 0, sizeof(uint8_t) ); + y = copier.copy_int( 0, sizeof(uint8_t) ); + psw = copier.copy_int( 0, sizeof(uint8_t) ); + sp = copier.copy_int( 0, sizeof(uint8_t) ); + copier.extra(); + + // times + spc_time = copier.copy_int( 0, sizeof(uint16_t) ); + dsp_time = copier.copy_int( 0, sizeof(uint16_t) ); + + int cur_time = S9xAPUGetClock(CPU.Cycles); + + // spc_time is absolute, dsp_time is relative + // smp.clock is relative, dsp.clock relative but counting upwards + SNES::smp.clock = spc_time - cur_time; + SNES::dsp.clock = -1 * dsp_time; + + // DSP + SNES::dsp.load_state(&ptr); + + // Timers + uint16_t next_time[3]; + uint8_t divider[3], counter[3]; + for ( int i = 0; i < 3; i++ ) + { + next_time[i] = copier.copy_int( 0, sizeof(uint16_t) ); + divider[i] = copier.copy_int( 0, sizeof(uint8_t) ); + counter[i] = copier.copy_int( 0, sizeof(uint8_t) ); + copier.extra(); + } + // construct timers out of available parts from blargg smp + SNES::smp.timer0.enable = regs[1] >> 0 & 1; // regs[1] = CONTROL + SNES::smp.timer0.target = IF_0_THEN_256(regs[10]); // regs[10+i] = TiTARGET + // blargg counts time, get ticks through timer frequency + // (assume tempo = 256) + SNES::smp.timer0.stage1_ticks = 128 - (next_time[0] - cur_time) / 128; + SNES::smp.timer0.stage2_ticks = divider[0]; + SNES::smp.timer0.stage3_ticks = counter[0]; + + SNES::smp.timer1.enable = regs[1] >> 1 & 1; + SNES::smp.timer1.target = IF_0_THEN_256(regs[11]); + SNES::smp.timer1.stage1_ticks = 128 - (next_time[1] - cur_time) / 128; + SNES::smp.timer1.stage2_ticks = divider[0]; + SNES::smp.timer1.stage3_ticks = counter[0]; + + SNES::smp.timer2.enable = regs[1] >> 2 & 1; + SNES::smp.timer2.target = IF_0_THEN_256(regs[12]); + SNES::smp.timer2.stage1_ticks = 16 - (next_time[2] - cur_time) / 16; + SNES::smp.timer2.stage2_ticks = divider[0]; + SNES::smp.timer2.stage3_ticks = counter[0]; + + copier.extra(); + + SNES::smp.opcode_number = 0; + SNES::smp.opcode_cycle = 0; + + SNES::smp.regs.pc = pc; + SNES::smp.regs.sp = sp; + SNES::smp.regs.a = a; + SNES::smp.regs.x = x; + SNES::smp.regs.y = y; + + // blargg's psw has same layout as byuu's flags + SNES::smp.regs.p = psw; + + // blargg doesn't explicitly store iplrom_enable + SNES::smp.status.iplrom_enable = regs[1] & 0x80; + + SNES::smp.status.dsp_addr = regs[2]; + + SNES::smp.status.ram00f8 = regs_in[8]; + SNES::smp.status.ram00f9 = regs_in[9]; + + // default to 0 - we are on an opcode boundary, shouldn't matter + SNES::smp.rd=SNES::smp.wr=SNES::smp.dp=SNES::smp.sp=SNES::smp.ya=SNES::smp.bit=0; + + spc::reference_time = SNES::get_le32(ptr); + ptr += sizeof(int32); + spc::remainder = SNES::get_le32(ptr); + ptr += sizeof(int32); + + // blargg stores CPUIx in regs_in + memcpy (SNES::cpu.registers, regs_in + 4, 4); +} + bool8 S9xSPCDump (const char *filename) { FILE *fs; diff --git a/apu/apu.h b/apu/apu.h index 44b183a8..61575dae 100644 --- a/apu/apu.h +++ b/apu/apu.h @@ -198,6 +198,7 @@ void S9xAPUSetReferenceTime (int32); void S9xAPUTimingSetSpeedup (int); void S9xAPUAllowTimeOverflow (bool); void S9xAPULoadState (uint8 *); +void S9xAPULoadBlarggState(uint8 *oldblock); void S9xAPUSaveState (uint8 *); void S9xDumpSPCSnapshot (void); bool8 S9xSPCDump (const char *); diff --git a/port.h b/port.h index 0e8192e5..bd43353c 100644 --- a/port.h +++ b/port.h @@ -248,10 +248,16 @@ typedef signed int int32; #endif typedef unsigned int uint32; #endif -typedef unsigned char uint8_t; -typedef signed char int8_t; typedef signed __int64 int64; typedef unsigned __int64 uint64; +typedef int8 int8_t; +typedef uint8 uint8_t; +typedef int16 int16_t; +typedef uint16 uint16_t; +typedef int32 int32_t; +typedef uint32 uint32_t; +typedef int64 int64_t; +typedef uint64 uint64_t; typedef int socklen_t; #else // __WIN32__ typedef signed char int8; diff --git a/snapshot.cpp b/snapshot.cpp index e6cd879a..8c9a434e 100644 --- a/snapshot.cpp +++ b/snapshot.cpp @@ -1626,7 +1626,11 @@ int S9xUnfreezeFromStream (STREAM stream) memcpy(Memory.FillRAM, local_fillram, 0x8000); - S9xAPULoadState(local_apu_sound); + if(version < SNAPSHOT_VERSION_BAPU) { + printf("Using Blargg APU snapshot loading (snapshot version %d, current is %d)\n...", version, SNAPSHOT_VERSION); + S9xAPULoadBlarggState(local_apu_sound); + } else + S9xAPULoadState(local_apu_sound); struct SControlSnapshot ctl_snap; UnfreezeStructFromCopy(&ctl_snap, SnapControls, COUNT(SnapControls), local_control_data, version); @@ -1678,7 +1682,7 @@ int S9xUnfreezeFromStream (STREAM stream) if (local_bsx_data) UnfreezeStructFromCopy(&BSX, SnapBSX, COUNT(SnapBSX), local_bsx_data, version); - if (version < SNAPSHOT_VERSION) + if (version < SNAPSHOT_VERSION_IRQ) { printf("Converting old snapshot version %d to %d\n...", version, SNAPSHOT_VERSION); diff --git a/snapshot.h b/snapshot.h index 1cb4bd8c..a522abae 100644 --- a/snapshot.h +++ b/snapshot.h @@ -180,7 +180,9 @@ #define _SNAPSHOT_H_ #define SNAPSHOT_MAGIC "#!s9xsnp" -#define SNAPSHOT_VERSION 7 +#define SNAPSHOT_VERSION_IRQ 7 +#define SNAPSHOT_VERSION_BAPU 8 +#define SNAPSHOT_VERSION 8 #define SUCCESS 1 #define WRONG_FORMAT (-1) diff --git a/win32/snes9xw.vcproj b/win32/snes9xw.vcproj index 4b5bda35..06e38e15 100644 --- a/win32/snes9xw.vcproj +++ b/win32/snes9xw.vcproj @@ -158,7 +158,7 @@ FavorSizeOrSpeed="1" OmitFramePointers="true" WholeProgramOptimization="true" - AdditionalIncludeDirectories="$(ProjectDir),$(ProjectDir)..\,$(ProjectDir)..\..\,$(ProjectDir)..\..\zLib,$(ProjectDir)..\unzip,$(ProjectDir)..\..\FMOD\api\inc,$(ProjectDir)..\..\libPNG\src,$(ProjectDir)..\snes9x" + AdditionalIncludeDirectories="$(ProjectDir),$(ProjectDir)..\,$(ProjectDir)..\..\,$(ProjectDir)..\..\zLib,$(ProjectDir)..\unzip,$(ProjectDir)..\..\FMOD\api\inc,$(ProjectDir)..\..\libPNG\src,$(ProjectDir)..\apu\bapu" PreprocessorDefinitions="NDEBUG;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;FMODEX_SUPPORT;NETPLAY_SUPPORT" StringPooling="true" RuntimeLibrary="0" @@ -255,7 +255,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - + - - - + - - - - + + + + + + + + + + - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + Date: Thu, 26 Jan 2012 13:42:27 -0600 Subject: [PATCH 33/33] Inline some functions to avoid vtable lookups. --- apu/bapu/smp/smp.hpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp index 0a17cb8f..ed3a4767 100644 --- a/apu/bapu/smp/smp.hpp +++ b/apu/bapu/smp/smp.hpp @@ -107,21 +107,21 @@ public: unsigned cycle_table_dsp[256]; uint64 cycle_step_cpu; - uint8 op_adc (uint8 x, uint8 y); - uint16 op_addw(uint16 x, uint16 y); - uint8 op_and (uint8 x, uint8 y); - uint8 op_cmp (uint8 x, uint8 y); - uint16 op_cmpw(uint16 x, uint16 y); - uint8 op_eor (uint8 x, uint8 y); - uint8 op_inc (uint8 x); - uint8 op_dec (uint8 x); - uint8 op_or (uint8 x, uint8 y); - uint8 op_sbc (uint8 x, uint8 y); - uint16 op_subw(uint16 x, uint16 y); - uint8 op_asl (uint8 x); - uint8 op_lsr (uint8 x); - uint8 op_rol (uint8 x); - uint8 op_ror (uint8 x); + 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 uint8 op_dec (uint8 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); }; #if defined(DEBUGGER)