2012-11-19 22:43:34 +00:00
|
|
|
// Meteor - A Nintendo Gameboy Advance emulator
|
|
|
|
// Copyright (C) 2009-2011 Philippe Daouadi
|
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program 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 General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
#include "ameteor/cpu.hpp"
|
|
|
|
#include "ameteor/bios.hpp"
|
|
|
|
#include "globals.hpp"
|
|
|
|
#include "cpu_globals.hpp"
|
|
|
|
#include "ameteor.hpp"
|
|
|
|
|
|
|
|
#include "debug.hpp"
|
|
|
|
|
|
|
|
#include <cstring>
|
|
|
|
|
|
|
|
namespace AMeteor
|
|
|
|
{
|
|
|
|
Cpu::Cpu ()
|
|
|
|
{
|
|
|
|
Reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Cpu::Reset ()
|
|
|
|
{
|
|
|
|
std::memset(&m_st, 0, sizeof(m_st));
|
|
|
|
R(15) = 0x00000004;
|
|
|
|
m_st.icpsr.mode = M_SVC;
|
|
|
|
m_st.icpsr.fiq_d = true;
|
|
|
|
m_st.icpsr.irq_d = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Cpu::SoftReset ()
|
|
|
|
{
|
|
|
|
std::memset(&m_st, 0, sizeof(m_st));
|
|
|
|
R(13) = 0x03007F00;
|
|
|
|
R(15) = 0x08000004;
|
|
|
|
m_st.irq_r[0] = 0x03007FA0; // R13
|
|
|
|
m_st.svc_r[0] = 0x03007FE0; // R13
|
|
|
|
m_st.icpsr.mode = 0x1F;
|
|
|
|
m_st.icpsr.fiq_d = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Cpu::UpdateICpsr ()
|
|
|
|
{
|
|
|
|
m_st.icpsr.mode = m_st.cpsr.b.mode;
|
|
|
|
m_st.icpsr.irq_d = m_st.cpsr.b.irq_d;
|
|
|
|
m_st.icpsr.fiq_d = m_st.cpsr.b.fiq_d;
|
|
|
|
m_st.icpsr.thumb = m_st.cpsr.b.thumb;
|
|
|
|
m_st.icpsr.s_overflow = m_st.cpsr.b.s_overflow;
|
|
|
|
m_st.icpsr.f_overflow = m_st.cpsr.b.f_overflow;
|
|
|
|
m_st.icpsr.f_carry = m_st.cpsr.b.f_carry;
|
|
|
|
m_st.icpsr.f_zero = m_st.cpsr.b.f_zero;
|
|
|
|
m_st.icpsr.f_sign = m_st.cpsr.b.f_sign;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Cpu::UpdateCpsr ()
|
|
|
|
{
|
|
|
|
m_st.cpsr.b.mode = m_st.icpsr.mode;
|
|
|
|
m_st.cpsr.b.irq_d = m_st.icpsr.irq_d;
|
|
|
|
m_st.cpsr.b.fiq_d = m_st.icpsr.fiq_d;
|
|
|
|
m_st.cpsr.b.thumb = m_st.icpsr.thumb;
|
|
|
|
m_st.cpsr.b.s_overflow = m_st.icpsr.s_overflow;
|
|
|
|
m_st.cpsr.b.f_overflow = m_st.icpsr.f_overflow;
|
|
|
|
m_st.cpsr.b.f_carry = m_st.icpsr.f_carry;
|
|
|
|
m_st.cpsr.b.f_zero = m_st.icpsr.f_zero;
|
|
|
|
m_st.cpsr.b.f_sign = m_st.icpsr.f_sign;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Cpu::SwitchToMode (uint8_t newmode)
|
|
|
|
{
|
|
|
|
SaveMode(m_st.icpsr.mode);
|
|
|
|
|
|
|
|
switch (newmode)
|
|
|
|
{
|
|
|
|
case 0x10: // User (non-privileged)
|
|
|
|
case 0x1F: // System (privileged 'User' mode)
|
|
|
|
switch (m_st.icpsr.mode)
|
|
|
|
{
|
|
|
|
case 0x10:
|
|
|
|
case 0x1F:
|
|
|
|
case 0x11:
|
|
|
|
std::memcpy(m_st.r + 8, m_st.usr_r, sizeof(m_st.usr_r));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
std::memcpy(m_st.r + 13, m_st.usr_r + 5, 2*4);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x11: // FIQ
|
|
|
|
std::memcpy(m_st.r + 8, m_st.fiq_r, sizeof(m_st.fiq_r));
|
|
|
|
break;
|
|
|
|
case 0x12: // IRQ
|
|
|
|
std::memcpy(m_st.r + 13, m_st.irq_r, sizeof(m_st.irq_r));
|
|
|
|
break;
|
|
|
|
case 0x13: // Supervisor (SWI)
|
|
|
|
std::memcpy(m_st.r + 13, m_st.svc_r, sizeof(m_st.svc_r));
|
|
|
|
break;
|
|
|
|
case 0x17: // Abort
|
|
|
|
std::memcpy(m_st.r + 13, m_st.abt_r, sizeof(m_st.abt_r));
|
|
|
|
break;
|
|
|
|
case 0x1B: // Undefined
|
|
|
|
std::memcpy(m_st.r + 13, m_st.und_r, sizeof(m_st.und_r));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
met_abort("Unknown CPU mode : " << IOS_ADD << (int)newmode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
UpdateCpsr();
|
|
|
|
m_st.spsr.dw = m_st.cpsr.dw;
|
|
|
|
m_st.icpsr.mode = newmode;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Cpu::SwitchModeBack ()
|
|
|
|
{
|
|
|
|
// oldmode is the mode on which we want to switch back
|
|
|
|
uint8_t oldmode = m_st.spsr.b.mode, curmode = m_st.icpsr.mode;
|
|
|
|
// we don't care if the spsr of the mode we are using is modified
|
|
|
|
SaveMode(curmode);
|
|
|
|
|
|
|
|
m_st.cpsr.dw = m_st.spsr.dw;
|
|
|
|
UpdateICpsr();
|
|
|
|
CheckInterrupt();
|
|
|
|
switch (oldmode)
|
|
|
|
{
|
|
|
|
case 0x10: // User (non-privileged)
|
|
|
|
case 0x1F: // System (privileged 'User' mode)
|
|
|
|
switch (curmode)
|
|
|
|
{
|
|
|
|
case 0x10:
|
|
|
|
case 0x1F:
|
|
|
|
case 0x11:
|
|
|
|
std::memcpy(m_st.r + 8, m_st.usr_r, sizeof(m_st.usr_r));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
std::memcpy(m_st.r + 13, m_st.usr_r + 5, 2*4);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x11: // FIQ
|
|
|
|
std::memcpy(m_st.r + 8, m_st.fiq_r, sizeof(m_st.fiq_r));
|
|
|
|
m_st.spsr.dw = m_st.fiq_spsr.dw;
|
|
|
|
break;
|
|
|
|
case 0x12: // IRQ
|
|
|
|
std::memcpy(m_st.r + 13, m_st.irq_r, sizeof(m_st.irq_r));
|
|
|
|
m_st.spsr.dw = m_st.irq_spsr.dw;
|
|
|
|
break;
|
|
|
|
case 0x13: // Supervisor (SWI)
|
|
|
|
std::memcpy(m_st.r + 13, m_st.svc_r, sizeof(m_st.svc_r));
|
|
|
|
m_st.spsr.dw = m_st.svc_spsr.dw;
|
|
|
|
break;
|
|
|
|
case 0x17: // Abort
|
|
|
|
std::memcpy(m_st.r + 13, m_st.abt_r, sizeof(m_st.abt_r));
|
|
|
|
m_st.spsr.dw = m_st.abt_spsr.dw;
|
|
|
|
break;
|
|
|
|
case 0x1B: // Undefined
|
|
|
|
std::memcpy(m_st.r + 13, m_st.und_r, sizeof(m_st.und_r));
|
|
|
|
m_st.spsr.dw = m_st.und_spsr.dw;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
met_abort("Unknown CPU mode : " << IOS_ADD << (int)oldmode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Cpu::SaveMode (uint8_t mode)
|
|
|
|
{
|
|
|
|
switch (mode)
|
|
|
|
{
|
|
|
|
case 0x10: // User (non-privileged)
|
|
|
|
case 0x1F: // System (privileged 'User' mode)
|
|
|
|
std::memcpy(m_st.usr_r, m_st.r + 8, sizeof(m_st.usr_r));
|
|
|
|
break;
|
|
|
|
case 0x11: // FIQ
|
|
|
|
std::memcpy(m_st.fiq_r, m_st.r + 8, sizeof(m_st.fiq_r));
|
|
|
|
m_st.fiq_spsr.dw = m_st.spsr.dw;
|
|
|
|
break;
|
|
|
|
case 0x12: // IRQ
|
|
|
|
std::memcpy(m_st.irq_r, m_st.r + 13, sizeof(m_st.irq_r));
|
|
|
|
m_st.irq_spsr.dw = m_st.spsr.dw;
|
|
|
|
break;
|
|
|
|
case 0x13: // Supervisor (SWI)
|
|
|
|
std::memcpy(m_st.svc_r, m_st.r + 13, sizeof(m_st.svc_r));
|
|
|
|
m_st.svc_spsr.dw = m_st.spsr.dw;
|
|
|
|
break;
|
|
|
|
case 0x17: // Abort
|
|
|
|
std::memcpy(m_st.abt_r, m_st.r + 13, sizeof(m_st.abt_r));
|
|
|
|
m_st.abt_spsr.dw = m_st.spsr.dw;
|
|
|
|
break;
|
|
|
|
case 0x1B: // Undefined
|
|
|
|
std::memcpy(m_st.und_r, m_st.r + 13, sizeof(m_st.und_r));
|
|
|
|
m_st.und_spsr.dw = m_st.spsr.dw;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
met_abort("Unknown CPU mode : " << IOS_ADD << (int)mode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Cpu::Interrupt ()
|
|
|
|
{
|
|
|
|
// Switch mode
|
|
|
|
SwitchToMode(0x12); // IRQ
|
|
|
|
// Save PC
|
|
|
|
R(14) = R(15);
|
|
|
|
// FIXME : why ? this seems to be USELESS ! (look at bios irq end)
|
|
|
|
if (m_st.icpsr.thumb)
|
|
|
|
R(14) += 2;
|
|
|
|
// Switch to ARM
|
|
|
|
m_st.icpsr.thumb = false;
|
|
|
|
// Disable IRQ
|
|
|
|
m_st.icpsr.irq_d = true;
|
|
|
|
SetInterrupt(false);
|
|
|
|
// Branch on 0x18
|
|
|
|
R(15) = 0x1C;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Cpu::SoftwareInterrupt ()
|
|
|
|
{
|
|
|
|
// Switch mode
|
|
|
|
SwitchToMode(0x13); // Supervisor
|
|
|
|
// Save PC
|
|
|
|
R(14) = R(15) - (m_st.icpsr.thumb ? 2 : 4);
|
|
|
|
// Switch to ARM
|
|
|
|
m_st.icpsr.thumb = false;
|
|
|
|
// Disable IRQ
|
|
|
|
m_st.icpsr.irq_d = true;
|
|
|
|
SetInterrupt(false);
|
|
|
|
// Branch on 0x8
|
|
|
|
R(15) = 0xC;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO put this in Bios, no ?
|
|
|
|
void Cpu::SoftwareInterrupt (uint32_t comment)
|
|
|
|
{
|
2012-12-03 18:49:05 +00:00
|
|
|
if (true)
|
|
|
|
{
|
|
|
|
char buff[256];
|
|
|
|
int pos = 0;
|
|
|
|
pos += sprintf (buff + pos, "SWI %02xh : ", comment);
|
|
|
|
switch (comment) // no one cares about the sound driver
|
|
|
|
{
|
|
|
|
case 0x00: pos += sprintf (buff + pos, "SoftReset");
|
|
|
|
break;
|
|
|
|
case 0x01: pos += sprintf (buff + pos, "RegisterRamReset"); // todo: display flags
|
|
|
|
break;
|
|
|
|
case 0x02: pos += sprintf (buff + pos, "Halt");
|
|
|
|
break;
|
|
|
|
case 0x03: pos += sprintf (buff + pos, "Stop");
|
|
|
|
break;
|
|
|
|
case 0x04: pos += sprintf (buff + pos, "IntrWait"); // todo: display flags
|
|
|
|
break;
|
|
|
|
case 0x05: pos += sprintf (buff + pos, "VBlankIntrWait");
|
|
|
|
break;
|
|
|
|
case 0x06: pos += sprintf (buff + pos, "Div: ");
|
|
|
|
pos += sprintf (buff + pos, "%08xh/%08xh", R(0), R(1));
|
|
|
|
break;
|
|
|
|
case 0x07: pos += sprintf (buff + pos, "DivArm: ");
|
|
|
|
pos += sprintf (buff + pos, "%08xh/%08xh", R(1), R(0));
|
|
|
|
break;
|
|
|
|
case 0x08: pos += sprintf (buff + pos, "Sqrt: ");
|
|
|
|
pos += sprintf (buff + pos, "sqrt(%08xh)", R(0));
|
|
|
|
break;
|
|
|
|
case 0x09: pos += sprintf (buff + pos, "ArcTan: ");
|
|
|
|
pos += sprintf (buff + pos, "atan(%04xh)", R(0) & 0xffff);
|
|
|
|
break;
|
|
|
|
case 0x0a: pos += sprintf (buff + pos, "ArcTan2: ");
|
|
|
|
pos += sprintf (buff + pos, "atan2(%04xh,%04xh)", R(1) & 0xffff, R(0) & 0xffff);
|
|
|
|
break;
|
|
|
|
case 0x0b: pos += sprintf (buff + pos, "CpuSet: ");
|
|
|
|
pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh], wcnt=%xh, fixed=%c, size=%d", R(0), R(1), R(2) & 0x1fffff, R(2) & 0x1000000 ? 'Y' : 'N', R(2) & 0x4000000 ? 32 : 16);
|
|
|
|
break;
|
|
|
|
case 0x0c: pos += sprintf (buff + pos, "CpuFastSet: ");
|
|
|
|
pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh], wcnt=%xh, fixed=%c", R(0), R(1), R(2) & 0x1fffff, R(2) & 0x1000000 ? 'Y' : 'N');
|
|
|
|
break;
|
|
|
|
case 0x0d: pos += sprintf (buff + pos, "GetBiosChecksum");
|
|
|
|
break;
|
|
|
|
case 0x0e: pos += sprintf (buff + pos, "BgAffineSet: ");
|
|
|
|
pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh], cnt=%d", R(0), R(1), R(2));
|
|
|
|
break;
|
|
|
|
case 0x0f: pos += sprintf (buff + pos, "ObjAffineSet: ");
|
|
|
|
pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh], cnt=%d, offs=%d", R(0), R(1), R(2), R(3));
|
|
|
|
break;
|
|
|
|
case 0x10: pos += sprintf (buff + pos, "BitUnPack: ");
|
|
|
|
pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh], info=[%08xh]", R(0), R(1), R(2));
|
|
|
|
break;
|
|
|
|
case 0x11: pos += sprintf (buff + pos, "LZ77UnCompWram: ");
|
|
|
|
pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh]", R(0), R(1));
|
|
|
|
break;
|
|
|
|
case 0x12: pos += sprintf (buff + pos, "LZ77UnCompVram: ");
|
|
|
|
pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh]", R(0), R(1));
|
|
|
|
break;
|
|
|
|
case 0x13: pos += sprintf (buff + pos, "HuffUnComp: ");
|
|
|
|
pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh]", R(0), R(1));
|
|
|
|
break;
|
|
|
|
case 0x14: pos += sprintf (buff + pos, "RLUnCompWram: ");
|
|
|
|
pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh]", R(0), R(1));
|
|
|
|
break;
|
|
|
|
case 0x15: pos += sprintf (buff + pos, "RLUnCompVram: ");
|
|
|
|
pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh]", R(0), R(1));
|
|
|
|
break;
|
|
|
|
case 0x16: pos += sprintf (buff + pos, "Diff8bitUnFilterWram: ");
|
|
|
|
pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh]", R(0), R(1));
|
|
|
|
break;
|
|
|
|
case 0x17: pos += sprintf (buff + pos, "Diff8bitUnFilterVram: ");
|
|
|
|
pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh]", R(0), R(1));
|
|
|
|
break;
|
|
|
|
case 0x18: pos += sprintf (buff + pos, "Diff16bitUnFilter: ");
|
|
|
|
pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh]", R(0), R(1));
|
|
|
|
break;
|
|
|
|
case 0x19: pos += sprintf (buff + pos, "SoundBias");
|
|
|
|
break;
|
|
|
|
case 0x1a: pos += sprintf (buff + pos, "SoundDriverInit");
|
|
|
|
break;
|
|
|
|
case 0x1b: pos += sprintf (buff + pos, "SoundDriverMode");
|
|
|
|
break;
|
|
|
|
case 0x1c: pos += sprintf (buff + pos, "SoundDriverMain");
|
|
|
|
break;
|
|
|
|
case 0x1d: pos += sprintf (buff + pos, "SoundDriverVSync");
|
|
|
|
break;
|
|
|
|
case 0x1e: pos += sprintf (buff + pos, "SoundChannelClear");
|
|
|
|
break;
|
|
|
|
case 0x1f: pos += sprintf (buff + pos, "MidiKey2Freq");
|
|
|
|
break;
|
|
|
|
case 0x20: pos += sprintf (buff + pos, "SoundWhatever0");
|
|
|
|
break;
|
|
|
|
case 0x21: pos += sprintf (buff + pos, "SoundWhatever1");
|
|
|
|
break;
|
|
|
|
case 0x22: pos += sprintf (buff + pos, "SoundWhatever2");
|
|
|
|
break;
|
|
|
|
case 0x23: pos += sprintf (buff + pos, "SoundWhatever3");
|
|
|
|
break;
|
|
|
|
case 0x24: pos += sprintf (buff + pos, "SoundWhatever4");
|
|
|
|
break;
|
|
|
|
case 0x25: pos += sprintf (buff + pos, "MultiBoot: ");
|
|
|
|
pos += sprintf (buff + pos, "mbp=[%08xh], mode=%d", R(0), R(1));
|
|
|
|
break;
|
|
|
|
case 0x26: pos += sprintf (buff + pos, "HardReset");
|
|
|
|
break;
|
|
|
|
case 0x27: pos += sprintf (buff + pos, "CustomHalt: ");
|
|
|
|
pos += sprintf (buff + pos, "val=%02xh", R(2) & 0xff);
|
|
|
|
break;
|
|
|
|
case 0x28: pos += sprintf (buff + pos, "SoundDriverVSyncOff");
|
|
|
|
break;
|
|
|
|
case 0x29: pos += sprintf (buff + pos, "SoundDriverVSyncOnn");
|
|
|
|
break;
|
|
|
|
case 0x2a: pos += sprintf (buff + pos, "SoundGetJumpList");
|
|
|
|
break;
|
|
|
|
default: pos += sprintf (buff + pos, "UNKNOWN");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
pos += sprintf (buff + pos, "\n");
|
|
|
|
print_bizhawk(buff);
|
|
|
|
}
|
2012-11-19 22:43:34 +00:00
|
|
|
if (MEM.HasBios())
|
|
|
|
SoftwareInterrupt();
|
|
|
|
else
|
|
|
|
switch (comment)
|
|
|
|
{
|
|
|
|
case 0x00:
|
|
|
|
Bios::SoftReset();
|
|
|
|
break;
|
|
|
|
case 0x01:
|
|
|
|
Bios::RegisterRamReset();
|
|
|
|
break;
|
|
|
|
case 0x02:
|
|
|
|
Bios::Halt();
|
|
|
|
break;
|
|
|
|
case 0x04:
|
|
|
|
case 0x05:
|
|
|
|
SoftwareInterrupt();
|
|
|
|
break;
|
|
|
|
case 0x06:
|
|
|
|
Bios::Div();
|
|
|
|
break;
|
|
|
|
case 0x07:
|
|
|
|
Bios::DivArm();
|
|
|
|
break;
|
|
|
|
case 0x08:
|
|
|
|
Bios::Sqrt();
|
|
|
|
break;
|
|
|
|
case 0x09:
|
|
|
|
Bios::ArcTan();
|
|
|
|
break;
|
|
|
|
case 0x0A:
|
|
|
|
Bios::ArcTan2();
|
|
|
|
break;
|
|
|
|
case 0x0B:
|
|
|
|
Bios::CpuSet();
|
|
|
|
break;
|
|
|
|
case 0x0C:
|
|
|
|
Bios::CpuFastSet();
|
|
|
|
break;
|
|
|
|
case 0x0E:
|
|
|
|
Bios::BgAffineSet();
|
|
|
|
break;
|
|
|
|
case 0x0F:
|
|
|
|
Bios::ObjAffineSet();
|
|
|
|
break;
|
|
|
|
case 0x11:
|
|
|
|
Bios::LZ77UnCompWram();
|
|
|
|
break;
|
|
|
|
case 0x12:
|
|
|
|
Bios::LZ77UnCompVram();
|
|
|
|
break;
|
|
|
|
case 0x13:
|
|
|
|
Bios::HuffUnComp();
|
|
|
|
break;
|
|
|
|
case 0x14:
|
|
|
|
Bios::RLUnCompWram();
|
|
|
|
break;
|
|
|
|
case 0x15:
|
|
|
|
Bios::RLUnCompVram();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
met_abort("Unknown software interrupt : " << IOS_ADD << comment);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Cpu::SaveState (std::ostream& stream)
|
|
|
|
{
|
|
|
|
SS_WRITE_VAR(m_st);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Cpu::LoadState (std::istream& stream)
|
|
|
|
{
|
|
|
|
SS_READ_VAR(m_st);
|
|
|
|
|
|
|
|
CheckInterrupt();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|