Merge branch 'byuuapu'
Conflicts: memmap.cpp
This commit is contained in:
commit
faa870ba49
564
apu/SNES_SPC.cpp
564
apu/SNES_SPC.cpp
@ -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 <string.h>
|
|
||||||
|
|
||||||
/* 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"
|
|
316
apu/SNES_SPC.h
316
apu/SNES_SPC.h
@ -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 <assert.h>
|
|
||||||
|
|
||||||
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
|
|
@ -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 <string.h>
|
|
||||||
|
|
||||||
/* 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
|
|
@ -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 <string.h>
|
|
||||||
|
|
||||||
/* 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 <stdio.h>
|
|
||||||
#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
|
|
1228
apu/SPC_CPU.h
1228
apu/SPC_CPU.h
File diff suppressed because it is too large
Load Diff
@ -1,68 +0,0 @@
|
|||||||
// snes_spc 0.9.0. http://www.slack.net/~ant/
|
|
||||||
|
|
||||||
#include "SPC_Filter.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/* 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 );
|
|
||||||
}
|
|
@ -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
|
|
268
apu/apu.cpp
268
apu/apu.cpp
@ -175,15 +175,15 @@
|
|||||||
Nintendo Co., Limited and its subsidiary companies.
|
Nintendo Co., Limited and its subsidiary companies.
|
||||||
***********************************************************************************/
|
***********************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "snes9x.h"
|
#include "snes9x.h"
|
||||||
#include "apu.h"
|
#include "apu.h"
|
||||||
#include "snapshot.h"
|
#include "snapshot.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "linear_resampler.h"
|
|
||||||
#include "hermite_resampler.h"
|
#include "hermite_resampler.h"
|
||||||
|
|
||||||
|
#include "snes/snes.hpp"
|
||||||
|
|
||||||
#define APU_DEFAULT_INPUT_RATE 32000
|
#define APU_DEFAULT_INPUT_RATE 32000
|
||||||
#define APU_MINIMUM_SAMPLE_COUNT 512
|
#define APU_MINIMUM_SAMPLE_COUNT 512
|
||||||
#define APU_MINIMUM_SAMPLE_BLOCK 128
|
#define APU_MINIMUM_SAMPLE_BLOCK 128
|
||||||
@ -191,21 +191,13 @@
|
|||||||
#define APU_DENOMINATOR_NTSC 328125
|
#define APU_DENOMINATOR_NTSC 328125
|
||||||
#define APU_NUMERATOR_PAL 34176
|
#define APU_NUMERATOR_PAL 34176
|
||||||
#define APU_DENOMINATOR_PAL 709379
|
#define APU_DENOMINATOR_PAL 709379
|
||||||
#define APU_DEFAULT_RESAMPLER HermiteResampler
|
|
||||||
|
|
||||||
SNES_SPC *spc_core = NULL;
|
namespace SNES
|
||||||
|
|
||||||
static uint8 APUROM[64] =
|
|
||||||
{
|
{
|
||||||
0xCD, 0xEF, 0xBD, 0xE8, 0x00, 0xC6, 0x1D, 0xD0,
|
#include "dsp/blargg_endian.h"
|
||||||
0xFC, 0x8F, 0xAA, 0xF4, 0x8F, 0xBB, 0xF5, 0x78,
|
|
||||||
0xCC, 0xF4, 0xD0, 0xFB, 0x2F, 0x19, 0xEB, 0xF4,
|
CPU cpu;
|
||||||
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
|
namespace spc
|
||||||
{
|
{
|
||||||
@ -227,8 +219,8 @@ namespace spc
|
|||||||
static int32 reference_time;
|
static int32 reference_time;
|
||||||
static uint32 remainder;
|
static uint32 remainder;
|
||||||
|
|
||||||
static const int timing_hack_numerator = SNES_SPC::tempo_unit;
|
static const int timing_hack_numerator = 256;
|
||||||
static int timing_hack_denominator = SNES_SPC::tempo_unit;
|
static int timing_hack_denominator = 256;
|
||||||
/* Set these to NTSC for now. Will change to PAL in S9xAPUTimingSetSpeedup
|
/* Set these to NTSC for now. Will change to PAL in S9xAPUTimingSetSpeedup
|
||||||
if necessary on game load. */
|
if necessary on game load. */
|
||||||
static uint32 ratio_numerator = APU_NUMERATOR_NTSC;
|
static uint32 ratio_numerator = APU_NUMERATOR_NTSC;
|
||||||
@ -239,8 +231,6 @@ static void EightBitize (uint8 *, int);
|
|||||||
static void DeStereo (uint8 *, int);
|
static void DeStereo (uint8 *, int);
|
||||||
static void ReverseStereo (uint8 *, int);
|
static void ReverseStereo (uint8 *, int);
|
||||||
static void UpdatePlaybackRate (void);
|
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 void SPCSnapshotCallback (void);
|
||||||
static inline int S9xAPUGetClock (int32);
|
static inline int S9xAPUGetClock (int32);
|
||||||
static inline int S9xAPUGetClockRemainder (int32);
|
static inline int S9xAPUGetClockRemainder (int32);
|
||||||
@ -354,11 +344,12 @@ int S9xGetSampleCount (void)
|
|||||||
return (spc::resampler->avail() >> (Settings.Stereo ? 0 : 1));
|
return (spc::resampler->avail() >> (Settings.Stereo ? 0 : 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: Attach */
|
||||||
void S9xFinalizeSamples (void)
|
void S9xFinalizeSamples (void)
|
||||||
{
|
{
|
||||||
if (!Settings.Mute)
|
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. */
|
/* We weren't able to process the entire buffer. Potential overrun. */
|
||||||
spc::sound_in_sync = FALSE;
|
spc::sound_in_sync = FALSE;
|
||||||
@ -376,7 +367,7 @@ void S9xFinalizeSamples (void)
|
|||||||
else
|
else
|
||||||
spc::sound_in_sync = FALSE;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xLandSamples (void)
|
void S9xLandSamples (void)
|
||||||
@ -452,7 +443,7 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms)
|
|||||||
arguments. Use 2x in the resampler for buffer leveling with SoundSync */
|
arguments. Use 2x in the resampler for buffer leveling with SoundSync */
|
||||||
if (!spc::resampler)
|
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)
|
if (!spc::resampler)
|
||||||
{
|
{
|
||||||
delete[] spc::landing_buffer;
|
delete[] spc::landing_buffer;
|
||||||
@ -462,7 +453,7 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms)
|
|||||||
else
|
else
|
||||||
spc::resampler->resize(spc::buffer_size >> (Settings.SoundSync ? 0 : 1));
|
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);
|
||||||
|
|
||||||
UpdatePlaybackRate();
|
UpdatePlaybackRate();
|
||||||
|
|
||||||
@ -473,7 +464,7 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms)
|
|||||||
|
|
||||||
void S9xSetSoundControl (uint8 voice_switch)
|
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)
|
void S9xSetSoundMute (bool8 mute)
|
||||||
@ -485,7 +476,8 @@ void S9xSetSoundMute (bool8 mute)
|
|||||||
|
|
||||||
void S9xDumpSPCSnapshot (void)
|
void S9xDumpSPCSnapshot (void)
|
||||||
{
|
{
|
||||||
spc_core->dsp_dump_spc_snapshot();
|
SNES::dsp.spc_dsp.dump_spc_snapshot();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SPCSnapshotCallback (void)
|
static void SPCSnapshotCallback (void)
|
||||||
@ -496,15 +488,6 @@ static void SPCSnapshotCallback (void)
|
|||||||
|
|
||||||
bool8 S9xInitAPU (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::landing_buffer = NULL;
|
||||||
spc::shrink_buffer = NULL;
|
spc::shrink_buffer = NULL;
|
||||||
spc::resampler = NULL;
|
spc::resampler = NULL;
|
||||||
@ -514,12 +497,6 @@ bool8 S9xInitAPU (void)
|
|||||||
|
|
||||||
void S9xDeinitAPU (void)
|
void S9xDeinitAPU (void)
|
||||||
{
|
{
|
||||||
if (spc_core)
|
|
||||||
{
|
|
||||||
delete spc_core;
|
|
||||||
spc_core = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spc::resampler)
|
if (spc::resampler)
|
||||||
{
|
{
|
||||||
delete spc::resampler;
|
delete spc::resampler;
|
||||||
@ -553,12 +530,14 @@ static inline int S9xAPUGetClockRemainder (int32 cpucycles)
|
|||||||
|
|
||||||
uint8 S9xAPUReadPort (int port)
|
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)
|
void S9xAPUWritePort (int port, uint8 byte)
|
||||||
{
|
{
|
||||||
spc_core->write_port(S9xAPUGetClock(CPU.Cycles), port, byte);
|
S9xAPUExecute ();
|
||||||
|
SNES::cpu.port_write (port & 3, byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xAPUSetReferenceTime (int32 cpucycles)
|
void S9xAPUSetReferenceTime (int32 cpucycles)
|
||||||
@ -568,8 +547,8 @@ void S9xAPUSetReferenceTime (int32 cpucycles)
|
|||||||
|
|
||||||
void S9xAPUExecute (void)
|
void S9xAPUExecute (void)
|
||||||
{
|
{
|
||||||
/* Accumulate partial APU cycles */
|
SNES::smp.clock -= S9xAPUGetClock (CPU.Cycles);
|
||||||
spc_core->end_frame(S9xAPUGetClock(CPU.Cycles));
|
SNES::smp.enter ();
|
||||||
|
|
||||||
spc::remainder = S9xAPUGetClockRemainder(CPU.Cycles);
|
spc::remainder = S9xAPUGetClockRemainder(CPU.Cycles);
|
||||||
|
|
||||||
@ -579,8 +558,9 @@ void S9xAPUExecute (void)
|
|||||||
void S9xAPUEndScanline (void)
|
void S9xAPUEndScanline (void)
|
||||||
{
|
{
|
||||||
S9xAPUExecute();
|
S9xAPUExecute();
|
||||||
|
SNES::dsp.synchronize();
|
||||||
|
|
||||||
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();
|
S9xLandSamples();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,8 +569,7 @@ void S9xAPUTimingSetSpeedup (int ticks)
|
|||||||
if (ticks != 0)
|
if (ticks != 0)
|
||||||
printf("APU speedup hack: %d\n", ticks);
|
printf("APU speedup hack: %d\n", ticks);
|
||||||
|
|
||||||
spc::timing_hack_denominator = SNES_SPC::tempo_unit - ticks;
|
spc::timing_hack_denominator = 256 - ticks;
|
||||||
spc_core->set_tempo(spc::timing_hack_denominator);
|
|
||||||
|
|
||||||
spc::ratio_numerator = Settings.PAL ? APU_NUMERATOR_PAL : APU_NUMERATOR_NTSC;
|
spc::ratio_numerator = Settings.PAL ? APU_NUMERATOR_PAL : APU_NUMERATOR_NTSC;
|
||||||
spc::ratio_denominator = Settings.PAL ? APU_DENOMINATOR_PAL : APU_DENOMINATOR_NTSC;
|
spc::ratio_denominator = Settings.PAL ? APU_DENOMINATOR_PAL : APU_DENOMINATOR_NTSC;
|
||||||
@ -599,20 +578,17 @@ void S9xAPUTimingSetSpeedup (int ticks)
|
|||||||
UpdatePlaybackRate();
|
UpdatePlaybackRate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xAPUAllowTimeOverflow (bool allow)
|
|
||||||
{
|
|
||||||
if (allow)
|
|
||||||
printf("APU time overflow allowed\n");
|
|
||||||
|
|
||||||
spc_core->spc_allow_time_overflow(allow);
|
|
||||||
}
|
|
||||||
|
|
||||||
void S9xResetAPU (void)
|
void S9xResetAPU (void)
|
||||||
{
|
{
|
||||||
spc::reference_time = 0;
|
spc::reference_time = 0;
|
||||||
spc::remainder = 0;
|
spc::remainder = 0;
|
||||||
spc_core->reset();
|
|
||||||
spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1);
|
SNES::cpu.reset ();
|
||||||
|
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);
|
||||||
|
SNES::dsp.spc_dsp.set_spc_snapshot_callback(SPCSnapshotCallback);
|
||||||
|
|
||||||
spc::resampler->clear();
|
spc::resampler->clear();
|
||||||
}
|
}
|
||||||
@ -621,44 +597,178 @@ void S9xSoftResetAPU (void)
|
|||||||
{
|
{
|
||||||
spc::reference_time = 0;
|
spc::reference_time = 0;
|
||||||
spc::remainder = 0;
|
spc::remainder = 0;
|
||||||
spc_core->soft_reset();
|
SNES::cpu.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();
|
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)
|
void S9xAPUSaveState (uint8 *block)
|
||||||
{
|
{
|
||||||
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);
|
ptr += sizeof(int32);
|
||||||
SET_LE32(ptr, spc::remainder);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xAPULoadState (uint8 *block)
|
void S9xAPULoadState (uint8 *block)
|
||||||
{
|
{
|
||||||
uint8 *ptr = block;
|
uint8 *ptr = block;
|
||||||
|
|
||||||
S9xResetAPU();
|
SNES::smp.load_state (&ptr);
|
||||||
|
SNES::dsp.load_state (&ptr);
|
||||||
|
|
||||||
spc_core->copy_state(&ptr, to_apu_from_state);
|
spc::reference_time = SNES::get_le32(ptr);
|
||||||
|
|
||||||
spc::reference_time = GET_LE32(ptr);
|
|
||||||
ptr += sizeof(int32);
|
ptr += sizeof(int32);
|
||||||
spc::remainder = GET_LE32(ptr);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
uint8 buf[SPC_FILE_SIZE];
|
||||||
|
size_t ignore;
|
||||||
|
|
||||||
|
fs = fopen(filename, "wb");
|
||||||
|
if (!fs)
|
||||||
|
return (FALSE);
|
||||||
|
|
||||||
|
S9xSetSoundMute(TRUE);
|
||||||
|
|
||||||
|
SNES::smp.save_spc (buf);
|
||||||
|
|
||||||
|
if ((ignore = fwrite(buf, SPC_FILE_SIZE, 1, fs)) <= 0)
|
||||||
|
fprintf (stderr, "Couldn't write file %s.\n", filename);
|
||||||
|
|
||||||
|
fclose(fs);
|
||||||
|
|
||||||
|
S9xSetSoundMute(FALSE);
|
||||||
|
|
||||||
|
return (TRUE);
|
||||||
}
|
}
|
||||||
|
@ -180,11 +180,11 @@
|
|||||||
#define _APU_H_
|
#define _APU_H_
|
||||||
|
|
||||||
#include "snes9x.h"
|
#include "snes9x.h"
|
||||||
#include "SNES_SPC.h"
|
|
||||||
|
|
||||||
typedef void (*apu_callback) (void *);
|
typedef void (*apu_callback) (void *);
|
||||||
|
|
||||||
#define SPC_SAVE_STATE_BLOCK_SIZE (SNES_SPC::state_size + 8)
|
#define SPC_SAVE_STATE_BLOCK_SIZE (1024 * 65)
|
||||||
|
#define SPC_FILE_SIZE (66048)
|
||||||
|
|
||||||
bool8 S9xInitAPU (void);
|
bool8 S9xInitAPU (void);
|
||||||
void S9xDeinitAPU (void);
|
void S9xDeinitAPU (void);
|
||||||
@ -198,8 +198,10 @@ void S9xAPUSetReferenceTime (int32);
|
|||||||
void S9xAPUTimingSetSpeedup (int);
|
void S9xAPUTimingSetSpeedup (int);
|
||||||
void S9xAPUAllowTimeOverflow (bool);
|
void S9xAPUAllowTimeOverflow (bool);
|
||||||
void S9xAPULoadState (uint8 *);
|
void S9xAPULoadState (uint8 *);
|
||||||
|
void S9xAPULoadBlarggState(uint8 *oldblock);
|
||||||
void S9xAPUSaveState (uint8 *);
|
void S9xAPUSaveState (uint8 *);
|
||||||
void S9xDumpSPCSnapshot (void);
|
void S9xDumpSPCSnapshot (void);
|
||||||
|
bool8 S9xSPCDump (const char *);
|
||||||
|
|
||||||
bool8 S9xInitSound (int, int);
|
bool8 S9xInitSound (int, int);
|
||||||
bool8 S9xOpenSoundDevice (void);
|
bool8 S9xOpenSoundDevice (void);
|
||||||
@ -214,6 +216,4 @@ void S9xClearSamples (void);
|
|||||||
bool8 S9xMixSamples (uint8 *, int);
|
bool8 S9xMixSamples (uint8 *, int);
|
||||||
void S9xSetSamplesAvailableCallback (apu_callback, void *);
|
void S9xSetSamplesAvailableCallback (apu_callback, void *);
|
||||||
|
|
||||||
extern SNES_SPC *spc_core;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -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 )
|
inline void SPC_DSP::echo_read( int ch )
|
||||||
{
|
{
|
||||||
int s;
|
int s = GET_LE16SA( ECHO_PTR( ch ) );
|
||||||
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
|
// second copy simplifies wrap-around handling
|
||||||
ECHO_FIR( 0 ) [ch] = ECHO_FIR( 8 ) [ch] = s >> 1;
|
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 )
|
inline void SPC_DSP::echo_write( int ch )
|
||||||
{
|
{
|
||||||
if ( !(m.t_echo_enabled & 0x20) )
|
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;
|
m.t_echo_out [ch] = 0;
|
||||||
}
|
}
|
@ -69,8 +69,6 @@ public:
|
|||||||
|
|
||||||
int stereo_switch;
|
int stereo_switch;
|
||||||
int take_spc_snapshot;
|
int take_spc_snapshot;
|
||||||
int rom_enabled; // mirror
|
|
||||||
uint8_t *rom, *hi_ram; // mirror
|
|
||||||
void (*spc_snapshot_callback) (void);
|
void (*spc_snapshot_callback) (void);
|
||||||
|
|
||||||
void set_spc_snapshot_callback( void (*callback) (void) );
|
void set_spc_snapshot_callback( void (*callback) (void) );
|
@ -5,7 +5,7 @@
|
|||||||
#define BLARGG_CONFIG_H
|
#define BLARGG_CONFIG_H
|
||||||
|
|
||||||
// Uncomment to disable debugging checks
|
// Uncomment to disable debugging checks
|
||||||
//#define NDEBUG 1
|
#define NDEBUG 1
|
||||||
|
|
||||||
// Uncomment to enable platform-specific (and possibly non-portable) optimizations
|
// Uncomment to enable platform-specific (and possibly non-portable) optimizations
|
||||||
//#define BLARGG_NONPORTABLE 1
|
//#define BLARGG_NONPORTABLE 1
|
50
apu/bapu/dsp/sdsp.cpp
Normal file
50
apu/bapu/dsp/sdsp.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include <snes/snes.hpp>
|
||||||
|
|
||||||
|
#define DSP_CPP
|
||||||
|
namespace SNES {
|
||||||
|
|
||||||
|
DSP dsp;
|
||||||
|
|
||||||
|
#include "SPC_DSP.cpp"
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
clock = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
34
apu/bapu/dsp/sdsp.hpp
Normal file
34
apu/bapu/dsp/sdsp.hpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include "SPC_DSP.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void save_state(uint8 **);
|
||||||
|
void load_state(uint8 **);
|
||||||
|
|
||||||
|
void power();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
DSP();
|
||||||
|
|
||||||
|
SPC_DSP spc_dsp;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern DSP dsp;
|
122
apu/bapu/smp/algorithms.cpp
Normal file
122
apu/bapu/smp/algorithms.cpp
Normal file
@ -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;
|
||||||
|
}
|
142
apu/bapu/smp/core.cpp
Normal file
142
apu/bapu/smp/core.cpp
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
void SMP::tick() {
|
||||||
|
timer0.tick();
|
||||||
|
timer1.tick();
|
||||||
|
timer2.tick();
|
||||||
|
|
||||||
|
#ifndef SNES9X
|
||||||
|
clock += cycle_step_cpu;
|
||||||
|
dsp.clock -= 24;
|
||||||
|
synchronize_dsp();
|
||||||
|
#else
|
||||||
|
clock++;
|
||||||
|
dsp.clock++;
|
||||||
|
#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();
|
||||||
|
#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)
|
||||||
|
|
||||||
|
#if defined(CYCLE_ACCURATE)
|
||||||
|
#if defined(PSEUDO_CYCLE)
|
||||||
|
|
||||||
|
if(opcode_cycle == 0)
|
||||||
|
opcode_number = op_readpc();
|
||||||
|
|
||||||
|
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"
|
||||||
|
#include "core/opcycle_read.cpp"
|
||||||
|
#include "core/opcycle_rmw.cpp"
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // defined(PSEUDO_CYCLE)
|
||||||
|
#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]);
|
||||||
|
|
||||||
|
#ifndef SNES9X
|
||||||
|
clock += cycle_table_cpu[opcode];
|
||||||
|
dsp.clock -= cycle_table_dsp[opcode];
|
||||||
|
synchronize_dsp();
|
||||||
|
#else
|
||||||
|
clock += cycle_count_table[opcode];
|
||||||
|
dsp.clock += cycle_count_table[opcode];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // defined(CYCLE_ACCURATE)
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
1
apu/bapu/smp/core/cc.sh
Executable file
1
apu/bapu/smp/core/cc.sh
Executable file
@ -0,0 +1 @@
|
|||||||
|
g++-4.5 -std=gnu++0x -I../../../.. -o generate generate.cpp
|
154
apu/bapu/smp/core/generate.cpp
Normal file
154
apu/bapu/smp/core/generate.cpp
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
#include <nall/file.hpp>
|
||||||
|
#include <nall/stdint.hpp>
|
||||||
|
#include <nall/string.hpp>
|
||||||
|
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<opcode_t> 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;
|
||||||
|
}
|
163
apu/bapu/smp/core/op_misc.b
Normal file
163
apu/bapu/smp/core/op_misc.b
Normal file
@ -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);
|
||||||
|
}
|
346
apu/bapu/smp/core/op_misc.cpp
Normal file
346
apu/bapu/smp/core/op_misc.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
217
apu/bapu/smp/core/op_mov.b
Normal file
217
apu/bapu/smp/core/op_mov.b
Normal file
@ -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);
|
||||||
|
}
|
389
apu/bapu/smp/core/op_mov.cpp
Normal file
389
apu/bapu/smp/core/op_mov.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
179
apu/bapu/smp/core/op_pc.b
Normal file
179
apu/bapu/smp/core/op_pc.b
Normal file
@ -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;
|
||||||
|
}
|
603
apu/bapu/smp/core/op_pc.cpp
Normal file
603
apu/bapu/smp/core/op_pc.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
205
apu/bapu/smp/core/op_read.b
Normal file
205
apu/bapu/smp/core/op_read.b
Normal file
@ -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));
|
||||||
|
}
|
744
apu/bapu/smp/core/op_read.cpp
Normal file
744
apu/bapu/smp/core/op_read.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
74
apu/bapu/smp/core/op_rmw.b
Normal file
74
apu/bapu/smp/core/op_rmw.b
Normal file
@ -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);
|
||||||
|
}
|
262
apu/bapu/smp/core/op_rmw.cpp
Normal file
262
apu/bapu/smp/core/op_rmw.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
696
apu/bapu/smp/core/opcycle_misc.cpp
Normal file
696
apu/bapu/smp/core/opcycle_misc.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
806
apu/bapu/smp/core/opcycle_mov.cpp
Normal file
806
apu/bapu/smp/core/opcycle_mov.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
1347
apu/bapu/smp/core/opcycle_pc.cpp
Normal file
1347
apu/bapu/smp/core/opcycle_pc.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1599
apu/bapu/smp/core/opcycle_read.cpp
Normal file
1599
apu/bapu/smp/core/opcycle_read.cpp
Normal file
File diff suppressed because it is too large
Load Diff
550
apu/bapu/smp/core/opcycle_rmw.cpp
Normal file
550
apu/bapu/smp/core/opcycle_rmw.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
311
apu/bapu/smp/core/oppseudo_misc.cpp
Normal file
311
apu/bapu/smp/core/oppseudo_misc.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
705
apu/bapu/smp/core/oppseudo_mov.cpp
Normal file
705
apu/bapu/smp/core/oppseudo_mov.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
536
apu/bapu/smp/core/oppseudo_pc.cpp
Normal file
536
apu/bapu/smp/core/oppseudo_pc.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
744
apu/bapu/smp/core/oppseudo_read.cpp
Normal file
744
apu/bapu/smp/core/oppseudo_read.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
262
apu/bapu/smp/core/oppseudo_rmw.cpp
Normal file
262
apu/bapu/smp/core/oppseudo_rmw.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
75
apu/bapu/smp/debugger/debugger.cpp
Normal file
75
apu/bapu/smp/debugger/debugger.cpp
Normal file
@ -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
|
27
apu/bapu/smp/debugger/debugger.hpp
Normal file
27
apu/bapu/smp/debugger/debugger.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
class SMPDebugger : public SMP, public ChipDebugger {
|
||||||
|
public:
|
||||||
|
bool property(unsigned id, string &name, string &value);
|
||||||
|
|
||||||
|
function<bool ()> 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);
|
||||||
|
};
|
304
apu/bapu/smp/debugger/disassembler.cpp
Normal file
304
apu/bapu/smp/debugger/disassembler.cpp
Normal file
@ -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);
|
||||||
|
}
|
44
apu/bapu/smp/iplrom.cpp
Normal file
44
apu/bapu/smp/iplrom.cpp
Normal file
@ -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
|
130
apu/bapu/smp/memory.cpp
Normal file
130
apu/bapu/smp/memory.cpp
Normal file
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
157
apu/bapu/smp/smp.cpp
Normal file
157
apu/bapu/smp/smp.cpp
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
#define CYCLE_ACCURATE
|
||||||
|
#define PSEUDO_CYCLE
|
||||||
|
|
||||||
|
#include <snes/snes.hpp>
|
||||||
|
|
||||||
|
#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() {
|
||||||
|
#ifndef SNES9X
|
||||||
|
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() {
|
||||||
|
#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() {
|
||||||
|
while(clock < 0) op_step();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMP::power() {
|
||||||
|
#ifndef SNES9X
|
||||||
|
Processor::frequency = system.apu_frequency();
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef SNES9X
|
||||||
|
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() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
132
apu/bapu/smp/smp.hpp
Normal file
132
apu/bapu/smp/smp.hpp
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
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();
|
||||||
|
|
||||||
|
#ifndef SNES9X
|
||||||
|
void serialize(serializer&);
|
||||||
|
#else
|
||||||
|
void load_state(uint8 **);
|
||||||
|
void save_state(uint8 **);
|
||||||
|
void save_spc (uint8 *);
|
||||||
|
#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 data;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
unsigned rd, wr, dp, sp, ya, bit;
|
||||||
|
|
||||||
|
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<unsigned frequency>
|
||||||
|
struct Timer {
|
||||||
|
bool enable;
|
||||||
|
uint8 target;
|
||||||
|
uint8 stage1_ticks;
|
||||||
|
uint8 stage2_ticks;
|
||||||
|
uint8 stage3_ticks;
|
||||||
|
|
||||||
|
inline void tick();
|
||||||
|
inline void tick(unsigned clocks);
|
||||||
|
};
|
||||||
|
|
||||||
|
Timer<128> timer0;
|
||||||
|
Timer<128> timer1;
|
||||||
|
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();
|
||||||
|
static const unsigned cycle_count_table[256];
|
||||||
|
uint64 cycle_table_cpu[256];
|
||||||
|
unsigned cycle_table_dsp[256];
|
||||||
|
uint64 cycle_step_cpu;
|
||||||
|
|
||||||
|
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)
|
||||||
|
#include "debugger/debugger.hpp"
|
||||||
|
extern SMPDebugger smp;
|
||||||
|
#else
|
||||||
|
extern SMP smp;
|
||||||
|
#endif
|
197
apu/bapu/smp/smp_state.cpp
Normal file
197
apu/bapu/smp/smp_state.cpp
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
#include "snes/snes.hpp"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
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 <= 0xf9; 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);
|
||||||
|
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);
|
||||||
|
|
||||||
|
INT32(rd);
|
||||||
|
INT32(wr);
|
||||||
|
INT32(dp);
|
||||||
|
INT32(sp);
|
||||||
|
INT32(ya);
|
||||||
|
INT32(bit);
|
||||||
|
|
||||||
|
*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);
|
||||||
|
|
||||||
|
INT32(rd);
|
||||||
|
INT32(wr);
|
||||||
|
INT32(dp);
|
||||||
|
INT32(sp);
|
||||||
|
INT32(ya);
|
||||||
|
INT32(bit);
|
||||||
|
|
||||||
|
*block = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace SNES */
|
26
apu/bapu/smp/timing.cpp
Normal file
26
apu/bapu/smp/timing.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
template<unsigned cycle_frequency>
|
||||||
|
void SMP::Timer<cycle_frequency>::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<unsigned cycle_frequency>
|
||||||
|
void SMP::Timer<cycle_frequency>::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;
|
||||||
|
}
|
60
apu/bapu/snes/snes.hpp
Normal file
60
apu/bapu/snes/snes.hpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#ifndef __SNES_HPP
|
||||||
|
#define __SNES_HPP
|
||||||
|
|
||||||
|
#include "snes9x.h"
|
||||||
|
|
||||||
|
#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
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Processor
|
||||||
|
{
|
||||||
|
unsigned frequency;
|
||||||
|
int32 clock;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "smp/smp.hpp"
|
||||||
|
#include "dsp/sdsp.hpp"
|
||||||
|
|
||||||
|
class CPU
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum { Threaded = false };
|
||||||
|
int frequency;
|
||||||
|
uint8 registers[4];
|
||||||
|
|
||||||
|
inline void reset ()
|
||||||
|
{
|
||||||
|
registers[0] = registers[1] = registers[2] = registers[3] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
alwaysinline void port_write (uint8 port, uint8 data)
|
||||||
|
{
|
||||||
|
registers[port & 3] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
alwaysinline uint8 port_read (uint8 port)
|
||||||
|
{
|
||||||
|
return registers[port & 3];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
extern CPU cpu;
|
||||||
|
|
||||||
|
} /* namespace SNES */
|
||||||
|
|
||||||
|
#endif
|
@ -14,25 +14,20 @@ class HermiteResampler : public Resampler
|
|||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
double r_step;
|
float r_step;
|
||||||
double r_frac;
|
float r_frac;
|
||||||
int r_left[4], r_right[4];
|
int r_left[4], r_right[4];
|
||||||
|
|
||||||
double
|
static inline float
|
||||||
hermite (double mu1, double a, double b, double c, double d)
|
hermite (float mu1, float a, float b, float c, float d)
|
||||||
{
|
{
|
||||||
const double tension = 0.0; //-1 = low, 0 = normal, 1 = high
|
float mu2, mu3, m0, m1, a0, a1, a2, a3;
|
||||||
const double bias = 0.0; //-1 = left, 0 = even, 1 = right
|
|
||||||
|
|
||||||
double mu2, mu3, m0, m1, a0, a1, a2, a3;
|
|
||||||
|
|
||||||
mu2 = mu1 * mu1;
|
mu2 = mu1 * mu1;
|
||||||
mu3 = mu2 * mu1;
|
mu3 = mu2 * mu1;
|
||||||
|
|
||||||
m0 = (b - a) * (1 + bias) * (1 - tension) / 2;
|
m0 = (c - a) * 0.5;
|
||||||
m0 += (c - b) * (1 - bias) * (1 - tension) / 2;
|
m1 = (d - b) * 0.5;
|
||||||
m1 = (c - b) * (1 + bias) * (1 - tension) / 2;
|
|
||||||
m1 += (d - c) * (1 - bias) * (1 - tension) / 2;
|
|
||||||
|
|
||||||
a0 = +2 * mu3 - 3 * mu2 + 1;
|
a0 = +2 * mu3 - 3 * mu2 + 1;
|
||||||
a1 = mu3 - 2 * mu2 + mu1;
|
a1 = mu3 - 2 * mu2 + mu1;
|
||||||
@ -72,6 +67,7 @@ class HermiteResampler : public Resampler
|
|||||||
read (short *data, int num_samples)
|
read (short *data, int num_samples)
|
||||||
{
|
{
|
||||||
int i_position = start >> 1;
|
int i_position = start >> 1;
|
||||||
|
int max_samples = buffer_size >> 1;
|
||||||
short *internal_buffer = (short *) buffer;
|
short *internal_buffer = (short *) buffer;
|
||||||
int o_position = 0;
|
int o_position = 0;
|
||||||
int consumed = 0;
|
int consumed = 0;
|
||||||
@ -80,22 +76,6 @@ class HermiteResampler : public Resampler
|
|||||||
{
|
{
|
||||||
int s_left = internal_buffer[i_position];
|
int s_left = internal_buffer[i_position];
|
||||||
int s_right = internal_buffer[i_position + 1];
|
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)
|
while (r_frac <= 1.0 && o_position < num_samples)
|
||||||
{
|
{
|
||||||
|
504
apu/license.txt
504
apu/license.txt
@ -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.
|
|
||||||
|
|
||||||
<one line to give the library's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
<signature of Ty Coon>, 1 April 1990
|
|
||||||
Ty Coon, President of Vice
|
|
||||||
|
|
||||||
That's all there is to it!
|
|
||||||
|
|
||||||
|
|
@ -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 */
|
|
@ -8,7 +8,7 @@ snes9x_gtk_CXXFLAGS = -fno-exceptions -fno-rtti
|
|||||||
endif
|
endif
|
||||||
noinst_LIBRARIES =
|
noinst_LIBRARIES =
|
||||||
|
|
||||||
INCLUDES = -I$(top_srcdir) -I.. -DSNES9XLOCALEDIR=\""$(snes9xlocaledir)"\"
|
INCLUDES = -I../apu/bapu -I$(top_srcdir) -I.. -DSNES9XLOCALEDIR=\""$(snes9xlocaledir)"\"
|
||||||
|
|
||||||
CLEANFILES = \
|
CLEANFILES = \
|
||||||
src/gtk_snes9x_ui.cpp \
|
src/gtk_snes9x_ui.cpp \
|
||||||
@ -119,12 +119,14 @@ endif
|
|||||||
|
|
||||||
# APU
|
# APU
|
||||||
snes9x_gtk_SOURCES += \
|
snes9x_gtk_SOURCES += \
|
||||||
../apu/apu.cpp \
|
../apu/apu.cpp
|
||||||
../apu/SNES_SPC.cpp \
|
|
||||||
../apu/SNES_SPC_misc.cpp \
|
# Byuu's APU
|
||||||
../apu/SNES_SPC_state.cpp \
|
snes9x_gtk_SOURCES += \
|
||||||
../apu/SPC_DSP.cpp \
|
../apu/bapu/dsp/sdsp.cpp \
|
||||||
../apu/SPC_Filter.cpp
|
../apu/bapu/dsp/SPC_DSP.cpp \
|
||||||
|
../apu/bapu/smp/smp.cpp \
|
||||||
|
../apu/bapu/smp/smp_state.cpp
|
||||||
|
|
||||||
# DSP
|
# DSP
|
||||||
snes9x_gtk_SOURCES += \
|
snes9x_gtk_SOURCES += \
|
||||||
|
@ -342,15 +342,6 @@ if test yes = "$with_jma_decomp"; then
|
|||||||
JMA=yes
|
JMA=yes
|
||||||
fi
|
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
|
if test yes = "$with_zlib"; then
|
||||||
AC_CHECK_HEADERS(zlib.h)
|
AC_CHECK_HEADERS(zlib.h)
|
||||||
AC_CHECK_LIB(z, gzread, [
|
AC_CHECK_LIB(z, gzread, [
|
||||||
@ -432,7 +423,7 @@ if test $ac_cv_my_sar_int8 = yes && \
|
|||||||
CFLAGS="$CFLAGS -DRIGHTSHIFT_IS_SAR"
|
CFLAGS="$CFLAGS -DRIGHTSHIFT_IS_SAR"
|
||||||
fi
|
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"
|
CXXFLAGS="$CFLAGS"
|
||||||
|
|
||||||
|
@ -905,16 +905,19 @@ S9xOpenGLDisplayDriver::swap_control (int enable)
|
|||||||
queried = TRUE;
|
queried = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glSwapInterval)
|
|
||||||
{
|
|
||||||
glSwapInterval (enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (glXSwapIntervalEXT)
|
if (glXSwapIntervalEXT)
|
||||||
{
|
{
|
||||||
|
if (glSwapInterval)
|
||||||
|
glSwapInterval (0);
|
||||||
|
|
||||||
glXSwapIntervalEXT (display, xwindow, enable);
|
glXSwapIntervalEXT (display, xwindow, enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (glSwapInterval)
|
||||||
|
{
|
||||||
|
glSwapInterval (enable);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +221,6 @@ event_motion_notify (GtkWidget *widget,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
Snes9xWindow *window = (Snes9xWindow *) user_data;
|
Snes9xWindow *window = (Snes9xWindow *) user_data;
|
||||||
int c_width, c_height;
|
|
||||||
|
|
||||||
if (!window->config->rom_loaded ||
|
if (!window->config->rom_loaded ||
|
||||||
window->last_width <= 0 ||
|
window->last_width <= 0 ||
|
||||||
@ -230,9 +229,6 @@ event_motion_notify (GtkWidget *widget,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
c_width = window->get_width ();
|
|
||||||
c_height = window->get_height ();
|
|
||||||
|
|
||||||
window->mouse_loc_x = (uint16)
|
window->mouse_loc_x = (uint16)
|
||||||
((int) (event->x) - window->mouse_region_x) * 256 /
|
((int) (event->x) - window->mouse_region_x) * 256 /
|
||||||
(window->mouse_region_width <= 0 ? 1 : window->mouse_region_width);
|
(window->mouse_region_width <= 0 ? 1 : window->mouse_region_width);
|
||||||
|
19
memmap.cpp
19
memmap.cpp
@ -3613,14 +3613,13 @@ void CMemory::ApplyROMFixes (void)
|
|||||||
//// APU timing hacks :(
|
//// APU timing hacks :(
|
||||||
|
|
||||||
Timings.APUSpeedup = 0;
|
Timings.APUSpeedup = 0;
|
||||||
Timings.APUAllowTimeOverflow = FALSE;
|
|
||||||
|
|
||||||
if (!Settings.DisableGameSpecificHacks)
|
if (!Settings.DisableGameSpecificHacks)
|
||||||
{
|
{
|
||||||
if (match_id("AVCJ")) // Rendering Ranger R2
|
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("JG ") || // Illusion of Gaia
|
||||||
match_id("CQ ") || // Stunt Race FX
|
match_id("CQ ") || // Stunt Race FX
|
||||||
match_na("SOULBLADER - 1") || // Soul Blader
|
match_na("SOULBLADER - 1") || // Soul Blader
|
||||||
@ -3654,22 +3653,10 @@ void CMemory::ApplyROMFixes (void)
|
|||||||
match_nn("Parlor") || // Parlor mini/2/3/4/5/6/7, Parlor Parlor!/2/3/4/5
|
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_na("HEIWA Parlor!Mini8") || // Parlor mini 8
|
||||||
match_nn("SANKYO Fever! \xCC\xA8\xB0\xCA\xDE\xB0!")) // SANKYO Fever! Fever!
|
match_nn("SANKYO Fever! \xCC\xA8\xB0\xCA\xDE\xB0!")) // SANKYO Fever! Fever!
|
||||||
Timings.APUSpeedup = 1;
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
S9xAPUTimingSetSpeedup(Timings.APUSpeedup);
|
S9xAPUTimingSetSpeedup(Timings.APUSpeedup);
|
||||||
S9xAPUAllowTimeOverflow(Timings.APUAllowTimeOverflow);
|
|
||||||
|
|
||||||
//// Other timing hacks :(
|
//// Other timing hacks :(
|
||||||
|
|
||||||
|
10
port.h
10
port.h
@ -248,10 +248,16 @@ typedef signed int int32;
|
|||||||
#endif
|
#endif
|
||||||
typedef unsigned int uint32;
|
typedef unsigned int uint32;
|
||||||
#endif
|
#endif
|
||||||
typedef unsigned char uint8_t;
|
|
||||||
typedef signed char int8_t;
|
|
||||||
typedef signed __int64 int64;
|
typedef signed __int64 int64;
|
||||||
typedef unsigned __int64 uint64;
|
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;
|
typedef int socklen_t;
|
||||||
#else // __WIN32__
|
#else // __WIN32__
|
||||||
typedef signed char int8;
|
typedef signed char int8;
|
||||||
|
30
snapshot.cpp
30
snapshot.cpp
@ -1626,6 +1626,10 @@ int S9xUnfreezeFromStream (STREAM stream)
|
|||||||
|
|
||||||
memcpy(Memory.FillRAM, local_fillram, 0x8000);
|
memcpy(Memory.FillRAM, local_fillram, 0x8000);
|
||||||
|
|
||||||
|
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);
|
S9xAPULoadState(local_apu_sound);
|
||||||
|
|
||||||
struct SControlSnapshot ctl_snap;
|
struct SControlSnapshot ctl_snap;
|
||||||
@ -1678,7 +1682,7 @@ int S9xUnfreezeFromStream (STREAM stream)
|
|||||||
if (local_bsx_data)
|
if (local_bsx_data)
|
||||||
UnfreezeStructFromCopy(&BSX, SnapBSX, COUNT(SnapBSX), local_bsx_data, version);
|
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);
|
printf("Converting old snapshot version %d to %d\n...", version, SNAPSHOT_VERSION);
|
||||||
|
|
||||||
@ -2275,27 +2279,3 @@ static void UnfreezeStructFromCopy (void *sbase, FreezeData *fields, int num_fie
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool8 S9xSPCDump (const char *filename)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
@ -180,7 +180,9 @@
|
|||||||
#define _SNAPSHOT_H_
|
#define _SNAPSHOT_H_
|
||||||
|
|
||||||
#define SNAPSHOT_MAGIC "#!s9xsnp"
|
#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 SUCCESS 1
|
||||||
#define WRONG_FORMAT (-1)
|
#define WRONG_FORMAT (-1)
|
||||||
@ -195,6 +197,5 @@ bool8 S9xFreezeGame (const char *);
|
|||||||
bool8 S9xUnfreezeGame (const char *);
|
bool8 S9xUnfreezeGame (const char *);
|
||||||
void S9xFreezeToStream (STREAM);
|
void S9xFreezeToStream (STREAM);
|
||||||
int S9xUnfreezeFromStream (STREAM);
|
int S9xUnfreezeFromStream (STREAM);
|
||||||
bool8 S9xSPCDump (const char *);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -158,7 +158,7 @@
|
|||||||
FavorSizeOrSpeed="1"
|
FavorSizeOrSpeed="1"
|
||||||
OmitFramePointers="true"
|
OmitFramePointers="true"
|
||||||
WholeProgramOptimization="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"
|
PreprocessorDefinitions="NDEBUG;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;FMODEX_SUPPORT;NETPLAY_SUPPORT"
|
||||||
StringPooling="true"
|
StringPooling="true"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
@ -255,7 +255,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
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="_DEBUG;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;FMODEX_SUPPORT;NETPLAY_SUPPORT;D3D_DEBUG_INFO"
|
PreprocessorDefinitions="_DEBUG;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;FMODEX_SUPPORT;NETPLAY_SUPPORT;D3D_DEBUG_INFO"
|
||||||
RuntimeLibrary="1"
|
RuntimeLibrary="1"
|
||||||
StructMemberAlignment="0"
|
StructMemberAlignment="0"
|
||||||
@ -354,7 +354,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
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="_DEBUG;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;FMODEX_SUPPORT;NETPLAY_SUPPORT;D3D_DEBUG_INFO"
|
PreprocessorDefinitions="_DEBUG;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;FMODEX_SUPPORT;NETPLAY_SUPPORT;D3D_DEBUG_INFO"
|
||||||
RuntimeLibrary="1"
|
RuntimeLibrary="1"
|
||||||
StructMemberAlignment="0"
|
StructMemberAlignment="0"
|
||||||
@ -453,7 +453,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
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="_DEBUG;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;FMODEX_SUPPORT;NETPLAY_SUPPORT;D3D_DEBUG_INFO"
|
PreprocessorDefinitions="_DEBUG;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;FMODEX_SUPPORT;NETPLAY_SUPPORT;D3D_DEBUG_INFO"
|
||||||
RuntimeLibrary="1"
|
RuntimeLibrary="1"
|
||||||
StructMemberAlignment="0"
|
StructMemberAlignment="0"
|
||||||
@ -553,7 +553,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
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="_DEBUG;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;FMODEX_SUPPORT;NETPLAY_SUPPORT;D3D_DEBUG_INFO"
|
PreprocessorDefinitions="_DEBUG;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;FMODEX_SUPPORT;NETPLAY_SUPPORT;D3D_DEBUG_INFO"
|
||||||
RuntimeLibrary="1"
|
RuntimeLibrary="1"
|
||||||
StructMemberAlignment="0"
|
StructMemberAlignment="0"
|
||||||
@ -660,7 +660,7 @@
|
|||||||
FavorSizeOrSpeed="1"
|
FavorSizeOrSpeed="1"
|
||||||
OmitFramePointers="true"
|
OmitFramePointers="true"
|
||||||
WholeProgramOptimization="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"
|
PreprocessorDefinitions="NDEBUG;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;FMODEX_SUPPORT;NETPLAY_SUPPORT"
|
||||||
StringPooling="true"
|
StringPooling="true"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
@ -765,7 +765,7 @@
|
|||||||
FavorSizeOrSpeed="1"
|
FavorSizeOrSpeed="1"
|
||||||
OmitFramePointers="true"
|
OmitFramePointers="true"
|
||||||
WholeProgramOptimization="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"
|
PreprocessorDefinitions="NDEBUG;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;FMODEX_SUPPORT;NETPLAY_SUPPORT"
|
||||||
StringPooling="true"
|
StringPooling="true"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
@ -4537,375 +4537,71 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\apu\apu.h"
|
RelativePath="..\apu\apu.h"
|
||||||
>
|
>
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\apu\blargg_common.h"
|
RelativePath="..\apu\hermite_resampler.h"
|
||||||
>
|
>
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\apu\blargg_config.h"
|
|
||||||
>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\apu\blargg_endian.h"
|
|
||||||
>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\apu\blargg_source.h"
|
|
||||||
>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\apu\resampler.h"
|
RelativePath="..\apu\resampler.h"
|
||||||
>
|
>
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\apu\ring_buffer.h"
|
RelativePath="..\apu\ring_buffer.h"
|
||||||
>
|
>
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\apu\SNES_SPC.cpp"
|
RelativePath="..\apu\bapu\snes\snes.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<Filter
|
||||||
|
Name="DSP"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\apu\bapu\dsp\blargg_common.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\apu\SNES_SPC.h"
|
RelativePath="..\apu\bapu\dsp\blargg_config.h"
|
||||||
>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\apu\SNES_SPC_misc.cpp"
|
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\apu\SNES_SPC_state.cpp"
|
RelativePath="..\apu\bapu\dsp\blargg_endian.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\apu\SPC_CPU.h"
|
RelativePath="..\apu\bapu\dsp\blargg_source.h"
|
||||||
>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\apu\SPC_DSP.cpp"
|
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\apu\SPC_DSP.h"
|
RelativePath="..\apu\bapu\dsp\sdsp.cpp"
|
||||||
>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\apu\SPC_Filter.cpp"
|
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\apu\SPC_Filter.h"
|
RelativePath="..\apu\bapu\dsp\sdsp.hpp"
|
||||||
>
|
>
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug Unicode|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\apu\bapu\dsp\SPC_DSP.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\apu\bapu\dsp\SPC_DSP.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="SMP"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\apu\bapu\smp\smp.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\apu\bapu\smp\smp_state.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Filter"
|
Name="Filter"
|
||||||
|
Loading…
Reference in New Issue
Block a user