Update InterruptRequester
This commit is contained in:
parent
6036aefd13
commit
7b518d0cf7
|
@ -1,106 +1,120 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2010 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
//
|
||||
// Copyright (C) 2010 by sinamas <sinamas at users.sourceforge.net>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
// published by the Free Software Foundation.
|
||||
//
|
||||
// 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 version 2 for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// version 2 along with this program; if not, write to the
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include "interruptrequester.h"
|
||||
#include "savestate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
InterruptRequester::InterruptRequester() : minIntTime(0), ifreg_(0), iereg_(0) {}
|
||||
InterruptRequester::InterruptRequester()
|
||||
: eventTimes_(disabled_time)
|
||||
, minIntTime_(0)
|
||||
, ifreg_(0)
|
||||
, iereg_(0)
|
||||
{
|
||||
}
|
||||
|
||||
void InterruptRequester::loadState(const SaveState &state) {
|
||||
minIntTime = state.mem.minIntTime;
|
||||
void InterruptRequester::loadState(SaveState const &state) {
|
||||
minIntTime_ = state.mem.minIntTime;
|
||||
ifreg_ = state.mem.ioamhram.get()[0x10F];
|
||||
iereg_ = state.mem.ioamhram.get()[0x1FF] & 0x1F;
|
||||
intFlags.set(state.mem.IME, state.mem.halted);
|
||||
intFlags_.set(state.mem.IME, state.mem.halted);
|
||||
|
||||
eventTimes.setValue<intevent_interrupts>(intFlags.imeOrHalted() && pendingIrqs() ? minIntTime : static_cast<unsigned long>(disabled_time));
|
||||
eventTimes_.setValue<intevent_interrupts>(intFlags_.imeOrHalted() && pendingIrqs()
|
||||
? minIntTime_
|
||||
: static_cast<unsigned long>(disabled_time));
|
||||
}
|
||||
|
||||
void InterruptRequester::resetCc(const unsigned long oldCc, const unsigned long newCc) {
|
||||
minIntTime = minIntTime < oldCc ? 0 : minIntTime - (oldCc - newCc);
|
||||
void InterruptRequester::resetCc(unsigned long oldCc, unsigned long newCc) {
|
||||
minIntTime_ = minIntTime_ < oldCc ? 0 : minIntTime_ - (oldCc - newCc);
|
||||
|
||||
if (eventTimes.value(intevent_interrupts) != disabled_time)
|
||||
eventTimes.setValue<intevent_interrupts>(minIntTime);
|
||||
if (eventTimes_.value(intevent_interrupts) != disabled_time)
|
||||
eventTimes_.setValue<intevent_interrupts>(minIntTime_);
|
||||
}
|
||||
|
||||
void InterruptRequester::ei(const unsigned long cc) {
|
||||
intFlags.setIme();
|
||||
minIntTime = cc + 1;
|
||||
void InterruptRequester::ei(unsigned long cc) {
|
||||
intFlags_.setIme();
|
||||
minIntTime_ = cc + 1;
|
||||
|
||||
if (pendingIrqs())
|
||||
eventTimes.setValue<intevent_interrupts>(minIntTime);
|
||||
eventTimes_.setValue<intevent_interrupts>(minIntTime_);
|
||||
}
|
||||
|
||||
void InterruptRequester::di() {
|
||||
intFlags.unsetIme();
|
||||
intFlags_.unsetIme();
|
||||
|
||||
if (!intFlags.imeOrHalted())
|
||||
eventTimes.setValue<intevent_interrupts>(disabled_time);
|
||||
if (!intFlags_.imeOrHalted())
|
||||
eventTimes_.setValue<intevent_interrupts>(disabled_time);
|
||||
}
|
||||
|
||||
void InterruptRequester::halt() {
|
||||
intFlags.setHalted();
|
||||
intFlags_.setHalted();
|
||||
|
||||
if (pendingIrqs())
|
||||
eventTimes.setValue<intevent_interrupts>(minIntTime);
|
||||
eventTimes_.setValue<intevent_interrupts>(minIntTime_);
|
||||
}
|
||||
|
||||
void InterruptRequester::unhalt() {
|
||||
intFlags.unsetHalted();
|
||||
intFlags_.unsetHalted();
|
||||
|
||||
if (!intFlags.imeOrHalted())
|
||||
eventTimes.setValue<intevent_interrupts>(disabled_time);
|
||||
if (!intFlags_.imeOrHalted())
|
||||
eventTimes_.setValue<intevent_interrupts>(disabled_time);
|
||||
}
|
||||
|
||||
void InterruptRequester::flagIrq(const unsigned bit) {
|
||||
void InterruptRequester::flagIrq(unsigned bit) {
|
||||
ifreg_ |= bit;
|
||||
|
||||
if (intFlags.imeOrHalted() && pendingIrqs())
|
||||
eventTimes.setValue<intevent_interrupts>(minIntTime);
|
||||
if (intFlags_.imeOrHalted() && pendingIrqs())
|
||||
eventTimes_.setValue<intevent_interrupts>(minIntTime_);
|
||||
}
|
||||
|
||||
void InterruptRequester::ackIrq(const unsigned bit) {
|
||||
void InterruptRequester::ackIrq(unsigned bit) {
|
||||
ifreg_ ^= bit;
|
||||
di();
|
||||
}
|
||||
|
||||
void InterruptRequester::setIereg(const unsigned iereg) {
|
||||
void InterruptRequester::setIereg(unsigned iereg) {
|
||||
iereg_ = iereg & 0x1F;
|
||||
|
||||
if (intFlags.imeOrHalted())
|
||||
eventTimes.setValue<intevent_interrupts>(pendingIrqs() ? minIntTime : static_cast<unsigned long>(disabled_time));
|
||||
if (intFlags_.imeOrHalted()) {
|
||||
eventTimes_.setValue<intevent_interrupts>(pendingIrqs()
|
||||
? minIntTime_
|
||||
: static_cast<unsigned long>(disabled_time));
|
||||
}
|
||||
}
|
||||
|
||||
void InterruptRequester::setIfreg(const unsigned ifreg) {
|
||||
void InterruptRequester::setIfreg(unsigned ifreg) {
|
||||
ifreg_ = ifreg;
|
||||
|
||||
if (intFlags.imeOrHalted())
|
||||
eventTimes.setValue<intevent_interrupts>(pendingIrqs() ? minIntTime : static_cast<unsigned long>(disabled_time));
|
||||
if (intFlags_.imeOrHalted()) {
|
||||
eventTimes_.setValue<intevent_interrupts>(pendingIrqs()
|
||||
? minIntTime_
|
||||
: static_cast<unsigned long>(disabled_time));
|
||||
}
|
||||
}
|
||||
|
||||
SYNCFUNC(InterruptRequester)
|
||||
{
|
||||
SSS(eventTimes);
|
||||
NSS(minIntTime);
|
||||
SSS(eventTimes_);
|
||||
NSS(minIntTime_);
|
||||
NSS(ifreg_);
|
||||
NSS(iereg_);
|
||||
NSS(intFlags.flags_);
|
||||
NSS(intFlags_.flags_);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2010 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
//
|
||||
// Copyright (C) 2010 by sinamas <sinamas at users.sourceforge.net>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
// published by the Free Software Foundation.
|
||||
//
|
||||
// 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 version 2 for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// version 2 along with this program; if not, write to the
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifndef INTERRUPT_REQUESTER_H
|
||||
#define INTERRUPT_REQUESTER_H
|
||||
|
||||
|
@ -24,49 +24,29 @@
|
|||
#include "newstate.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
struct SaveState;
|
||||
enum IntEventId { intevent_unhalt, intevent_end, intevent_blit, intevent_serial, intevent_oam, intevent_dma, intevent_tima, intevent_video, intevent_interrupts };
|
||||
|
||||
enum IntEventId { intevent_unhalt,
|
||||
intevent_end,
|
||||
intevent_blit,
|
||||
intevent_serial,
|
||||
intevent_oam,
|
||||
intevent_dma,
|
||||
intevent_tima,
|
||||
intevent_video,
|
||||
intevent_interrupts, intevent_last = intevent_interrupts };
|
||||
|
||||
class InterruptRequester {
|
||||
MinKeeper<intevent_interrupts + 1> eventTimes;
|
||||
unsigned long minIntTime;
|
||||
unsigned ifreg_;
|
||||
unsigned iereg_;
|
||||
|
||||
class IntFlags {
|
||||
friend class InterruptRequester;
|
||||
unsigned char flags_;
|
||||
enum { IME_MASK = 1, HALTED_MASK = 2 };
|
||||
|
||||
public:
|
||||
IntFlags() : flags_(0) {}
|
||||
|
||||
bool ime() const { return flags_ & IME_MASK; }
|
||||
bool halted() const { return flags_ & HALTED_MASK; }
|
||||
bool imeOrHalted() const { return flags_; }
|
||||
|
||||
void setIme() { flags_ |= IME_MASK; }
|
||||
void unsetIme() { flags_ &= ~IME_MASK; }
|
||||
|
||||
void setHalted() { flags_ |= HALTED_MASK; }
|
||||
void unsetHalted() { flags_ &= ~HALTED_MASK; }
|
||||
|
||||
void set(const bool ime, const bool halted) { flags_ = halted * HALTED_MASK + ime * IME_MASK; }
|
||||
} intFlags;
|
||||
|
||||
public:
|
||||
InterruptRequester();
|
||||
|
||||
void loadState(const SaveState &);
|
||||
|
||||
void loadState(SaveState const &);
|
||||
void resetCc(unsigned long oldCc, unsigned long newCc);
|
||||
|
||||
unsigned ifreg() const { return ifreg_; }
|
||||
unsigned iereg() const { return iereg_; }
|
||||
unsigned pendingIrqs() const { return ifreg_ & iereg_; }
|
||||
bool ime() const { return intFlags.ime(); }
|
||||
bool halted() const { return intFlags.halted(); }
|
||||
|
||||
bool ime() const { return intFlags_.ime(); }
|
||||
bool halted() const { return intFlags_.halted(); }
|
||||
void ei(unsigned long cc);
|
||||
void di();
|
||||
void halt();
|
||||
|
@ -76,20 +56,47 @@ public:
|
|||
void setIereg(unsigned iereg);
|
||||
void setIfreg(unsigned ifreg);
|
||||
|
||||
IntEventId minEventId() const { return static_cast<IntEventId>(eventTimes.min()); }
|
||||
unsigned long minEventTime() const { return eventTimes.minValue(); }
|
||||
template<IntEventId id> void setEventTime(unsigned long value) { eventTimes.setValue<id>(value); }
|
||||
void setEventTime(const IntEventId id, unsigned long value) { eventTimes.setValue(id, value); }
|
||||
unsigned long eventTime(IntEventId id) const { return eventTimes.value(id); }
|
||||
IntEventId minEventId() const { return static_cast<IntEventId>(eventTimes_.min()); }
|
||||
unsigned long minEventTime() const { return eventTimes_.minValue(); }
|
||||
template<IntEventId id> void setEventTime(unsigned long value) { eventTimes_.setValue<id>(value); }
|
||||
void setEventTime(IntEventId id, unsigned long value) { eventTimes_.setValue(id, value); }
|
||||
unsigned long eventTime(IntEventId id) const { return eventTimes_.value(id); }
|
||||
|
||||
private:
|
||||
class IntFlags {
|
||||
friend class InterruptRequester;
|
||||
public:
|
||||
IntFlags() : flags_(0) {}
|
||||
bool ime() const { return flags_ & flag_ime; }
|
||||
bool halted() const { return flags_ & flag_halted; }
|
||||
bool imeOrHalted() const { return flags_; }
|
||||
void setIme() { flags_ |= flag_ime; }
|
||||
void unsetIme() { flags_ &= ~flag_ime; }
|
||||
void setHalted() { flags_ |= flag_halted; }
|
||||
void unsetHalted() { flags_ &= ~flag_halted; }
|
||||
void set(bool ime, bool halted) { flags_ = halted * flag_halted + ime * flag_ime; }
|
||||
|
||||
private:
|
||||
unsigned char flags_;
|
||||
enum { flag_ime = 1, flag_halted = 2 };
|
||||
};
|
||||
|
||||
MinKeeper<intevent_last + 1> eventTimes_;
|
||||
unsigned long minIntTime_;
|
||||
unsigned ifreg_;
|
||||
unsigned iereg_;
|
||||
IntFlags intFlags_;
|
||||
|
||||
|
||||
public:
|
||||
template<bool isReader>void SyncState(NewState *ns);
|
||||
};
|
||||
|
||||
inline void flagHdmaReq(InterruptRequester &intreq) { intreq.setEventTime<intevent_dma>(0); }
|
||||
inline void flagGdmaReq(InterruptRequester &intreq) { intreq.setEventTime<intevent_dma>(1); }
|
||||
inline void ackDmaReq(InterruptRequester &intreq) { intreq.setEventTime<intevent_dma>(disabled_time); }
|
||||
inline bool hdmaReqFlagged(const InterruptRequester &intreq) { return intreq.eventTime(intevent_dma) == 0; }
|
||||
inline bool gdmaReqFlagged(const InterruptRequester &intreq) { return intreq.eventTime(intevent_dma) == 1; }
|
||||
inline bool hdmaReqFlagged(InterruptRequester const &intreq) { return intreq.eventTime(intevent_dma) == 0; }
|
||||
inline bool gdmaReqFlagged(InterruptRequester const &intreq) { return intreq.eventTime(intevent_dma) == 1; }
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -593,6 +593,8 @@ LoadRes Cartridge::loadROM(const char *romfiledata, unsigned romfilelength, bool
|
|||
case 0x1C:
|
||||
case 0x1D:
|
||||
case 0x1E: type = MBC5; break;
|
||||
case 0x20: return LOADRES_UNSUPPORTED_MBC_MBC6;
|
||||
case 0x22: return LOADRES_UNSUPPORTED_MBC_MBC7;
|
||||
case 0xFC: return LOADRES_UNSUPPORTED_MBC_POCKET_CAMERA;
|
||||
case 0xFD: return LOADRES_UNSUPPORTED_MBC_TAMA5;
|
||||
case 0xFE: return LOADRES_UNSUPPORTED_MBC_HUC3;
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue