libgambatte: refactor Tima
This commit is contained in:
parent
79085f9a3a
commit
51e8ba3cf5
|
@ -1199,6 +1199,7 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM
|
|||
state.mem.ioamhram.ptr[0x144] = 0x00;
|
||||
|
||||
state.mem.divLastUpdate = 0 - div;
|
||||
state.mem.timaBasetime = 0;
|
||||
state.mem.timaLastUpdate = 0;
|
||||
state.mem.tmatime = disabled_time;
|
||||
state.mem.nextSerialtime = disabled_time;
|
||||
|
|
|
@ -63,6 +63,7 @@ struct SaveState {
|
|||
Ptr<unsigned char> wram;
|
||||
Ptr<unsigned char> ioamhram;
|
||||
unsigned long divLastUpdate;
|
||||
unsigned long timaBasetime;
|
||||
unsigned long timaLastUpdate;
|
||||
unsigned long tmatime;
|
||||
unsigned long nextSerialtime;
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 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) 2007 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 SOUND_H
|
||||
#define SOUND_H
|
||||
|
||||
|
|
|
@ -1,61 +1,61 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 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) 2007 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 "tima.h"
|
||||
#include "savestate.h"
|
||||
|
||||
static const unsigned char timaClock[4] = { 10, 4, 6, 8 };
|
||||
static unsigned char const timaClock[4] = { 10, 4, 6, 8 };
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
Tima::Tima() :
|
||||
lastUpdate_(0),
|
||||
tmatime_(disabled_time),
|
||||
tima_(0),
|
||||
tma_(0),
|
||||
tac_(0)
|
||||
{}
|
||||
Tima::Tima()
|
||||
: lastUpdate_(0)
|
||||
, tmatime_(disabled_time)
|
||||
, tima_(0)
|
||||
, tma_(0)
|
||||
, tac_(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Tima::loadState(const SaveState &state, const TimaInterruptRequester timaIrq) {
|
||||
void Tima::loadState(SaveState const &state, TimaInterruptRequester timaIrq) {
|
||||
basetime_ = state.mem.timaBasetime;
|
||||
lastUpdate_ = state.mem.timaLastUpdate;
|
||||
tmatime_ = state.mem.tmatime;
|
||||
|
||||
tima_ = state.mem.ioamhram.get()[0x105];
|
||||
tma_ = state.mem.ioamhram.get()[0x106];
|
||||
tac_ = state.mem.ioamhram.get()[0x107];
|
||||
|
||||
timaIrq.setNextIrqEventTime((tac_ & 4)
|
||||
?
|
||||
(tmatime_ != disabled_time && tmatime_ > state.cpu.cycleCounter
|
||||
? tmatime_
|
||||
: lastUpdate_ + ((256u - tima_) << timaClock[tac_ & 3]) + 3)
|
||||
:
|
||||
static_cast<unsigned long>(disabled_time)
|
||||
);
|
||||
unsigned long nextIrqEventTime = disabled_time;
|
||||
if (tac_ & 4) {
|
||||
nextIrqEventTime = tmatime_ != disabled_time && tmatime_ > state.cpu.cycleCounter
|
||||
? tmatime_
|
||||
: lastUpdate_ + ((256u - tima_) << timaClock[tac_ & 3]) + 3;
|
||||
}
|
||||
|
||||
timaIrq.setNextIrqEventTime(nextIrqEventTime);
|
||||
}
|
||||
|
||||
void Tima::resetCc(const unsigned long oldCc, const unsigned long newCc, const TimaInterruptRequester timaIrq) {
|
||||
const unsigned long dec = oldCc - newCc;
|
||||
|
||||
void Tima::resetCc(unsigned long const oldCc, unsigned long const newCc, TimaInterruptRequester timaIrq) {
|
||||
if (tac_ & 0x04) {
|
||||
updateIrq(oldCc, timaIrq);
|
||||
updateTima(oldCc);
|
||||
|
||||
unsigned long const dec = oldCc - newCc;
|
||||
lastUpdate_ -= dec;
|
||||
timaIrq.setNextIrqEventTime(timaIrq.nextIrqEventTime() - dec);
|
||||
|
||||
|
@ -64,20 +64,18 @@ void Tima::resetCc(const unsigned long oldCc, const unsigned long newCc, const T
|
|||
}
|
||||
}
|
||||
|
||||
void Tima::updateTima(const unsigned long cycleCounter) {
|
||||
const unsigned long ticks = (cycleCounter - lastUpdate_) >> timaClock[tac_ & 3];
|
||||
|
||||
void Tima::updateTima(unsigned long const cc) {
|
||||
unsigned long const ticks = (cc - lastUpdate_) >> timaClock[tac_ & 3];
|
||||
lastUpdate_ += ticks << timaClock[tac_ & 3];
|
||||
|
||||
if (cycleCounter >= tmatime_) {
|
||||
if (cycleCounter >= tmatime_ + 4)
|
||||
if (cc >= tmatime_) {
|
||||
if (cc >= tmatime_ + 4)
|
||||
tmatime_ = disabled_time;
|
||||
|
||||
tima_ = tma_;
|
||||
}
|
||||
|
||||
unsigned long tmp = tima_ + ticks;
|
||||
|
||||
while (tmp > 0x100)
|
||||
tmp -= 0x100 - tma_;
|
||||
|
||||
|
@ -85,8 +83,8 @@ void Tima::updateTima(const unsigned long cycleCounter) {
|
|||
tmp = 0;
|
||||
tmatime_ = lastUpdate_ + 3;
|
||||
|
||||
if (cycleCounter >= tmatime_) {
|
||||
if (cycleCounter >= tmatime_ + 4)
|
||||
if (cc >= tmatime_) {
|
||||
if (cc >= tmatime_ + 4)
|
||||
tmatime_ = disabled_time;
|
||||
|
||||
tmp = tma_;
|
||||
|
@ -96,12 +94,12 @@ void Tima::updateTima(const unsigned long cycleCounter) {
|
|||
tima_ = tmp;
|
||||
}
|
||||
|
||||
void Tima::setTima(const unsigned data, const unsigned long cycleCounter, const TimaInterruptRequester timaIrq) {
|
||||
void Tima::setTima(unsigned const data, unsigned long const cc, TimaInterruptRequester timaIrq) {
|
||||
if (tac_ & 0x04) {
|
||||
updateIrq(cycleCounter, timaIrq);
|
||||
updateTima(cycleCounter);
|
||||
updateIrq(cc, timaIrq);
|
||||
updateTima(cc);
|
||||
|
||||
if (tmatime_ - cycleCounter < 4)
|
||||
if (tmatime_ - cc < 4)
|
||||
tmatime_ = disabled_time;
|
||||
|
||||
timaIrq.setNextIrqEventTime(lastUpdate_ + ((256u - data) << timaClock[tac_ & 3]) + 3);
|
||||
|
@ -110,44 +108,44 @@ void Tima::setTima(const unsigned data, const unsigned long cycleCounter, const
|
|||
tima_ = data;
|
||||
}
|
||||
|
||||
void Tima::setTma(const unsigned data, const unsigned long cycleCounter, const TimaInterruptRequester timaIrq) {
|
||||
void Tima::setTma(unsigned const data, unsigned long const cc, TimaInterruptRequester timaIrq) {
|
||||
if (tac_ & 0x04) {
|
||||
updateIrq(cycleCounter, timaIrq);
|
||||
updateTima(cycleCounter);
|
||||
updateIrq(cc, timaIrq);
|
||||
updateTima(cc);
|
||||
}
|
||||
|
||||
tma_ = data;
|
||||
}
|
||||
|
||||
void Tima::setTac(const unsigned data, const unsigned long cycleCounter, const TimaInterruptRequester timaIrq, bool gbIsCgb) {
|
||||
void Tima::setTac(unsigned const data, unsigned long const cc, TimaInterruptRequester timaIrq, bool gbIsCgb) {
|
||||
if (tac_ ^ data) {
|
||||
unsigned long nextIrqEventTime = timaIrq.nextIrqEventTime();
|
||||
|
||||
if (tac_ & 0x04) {
|
||||
updateIrq(cycleCounter, timaIrq);
|
||||
updateTima(cycleCounter);
|
||||
updateIrq(cc, timaIrq);
|
||||
updateTima(cc);
|
||||
|
||||
lastUpdate_ -= (1u << (timaClock[tac_ & 3] - 1)) + 3;
|
||||
tmatime_ -= (1u << (timaClock[tac_ & 3] - 1)) + 3;
|
||||
nextIrqEventTime -= (1u << (timaClock[tac_ & 3] - 1)) + 3;
|
||||
|
||||
if (cycleCounter >= nextIrqEventTime)
|
||||
if (cc >= nextIrqEventTime)
|
||||
timaIrq.flagIrq();
|
||||
|
||||
updateTima(cycleCounter);
|
||||
updateTima(cc);
|
||||
|
||||
tmatime_ = disabled_time;
|
||||
nextIrqEventTime = disabled_time;
|
||||
}
|
||||
|
||||
if (data & 4) {
|
||||
lastUpdate_ = (cycleCounter >> timaClock[data & 3]) << timaClock[data & 3];
|
||||
unsigned long diff = cycleCounter - basetime_;
|
||||
unsigned long diff = cc - basetime_;
|
||||
|
||||
if (gbIsCgb) {
|
||||
if (((diff >> (timaClock[tac_ & 3] - 1)) & 1) == 1 && ((diff >> (timaClock[data & 3] - 1)) & 1) == 0)
|
||||
tima_++;
|
||||
}
|
||||
|
||||
lastUpdate_ = basetime_ + ((diff >> timaClock[data & 3]) << timaClock[data & 3]);
|
||||
nextIrqEventTime = lastUpdate_ + ((256u - tima_) << timaClock[data & 3]) + 3;
|
||||
}
|
||||
|
@ -158,24 +156,26 @@ void Tima::setTac(const unsigned data, const unsigned long cycleCounter, const T
|
|||
tac_ = data;
|
||||
}
|
||||
|
||||
void Tima::resTac(unsigned long const cycleCounter, TimaInterruptRequester timaIrq) {
|
||||
basetime_ = cycleCounter;
|
||||
void Tima::resTac(unsigned long const cc, TimaInterruptRequester timaIrq) {
|
||||
basetime_ = cc;
|
||||
|
||||
if (tac_ & 0x04) {
|
||||
setTac(tac_ & ~0x04, cycleCounter, timaIrq, false);
|
||||
setTac(tac_ | 0x04, cycleCounter, timaIrq, false);
|
||||
setTac(tac_ & ~0x04, cc, timaIrq, false);
|
||||
setTac(tac_ | 0x04, cc, timaIrq, false);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned Tima::tima(unsigned long cycleCounter) {
|
||||
unsigned Tima::tima(unsigned long cc) {
|
||||
if (tac_ & 0x04)
|
||||
updateTima(cycleCounter);
|
||||
updateTima(cc);
|
||||
|
||||
return tima_;
|
||||
}
|
||||
|
||||
void Tima::doIrqEvent(const TimaInterruptRequester timaIrq) {
|
||||
void Tima::doIrqEvent(TimaInterruptRequester timaIrq) {
|
||||
timaIrq.flagIrq();
|
||||
timaIrq.setNextIrqEventTime(timaIrq.nextIrqEventTime() + ((256u - tma_) << timaClock[tac_ & 3]));
|
||||
timaIrq.setNextIrqEventTime(timaIrq.nextIrqEventTime()
|
||||
+ ((256u - tma_) << timaClock[tac_ & 3]));
|
||||
}
|
||||
|
||||
SYNCFUNC(Tima)
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 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) 2007 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 TIMA_H
|
||||
#define TIMA_H
|
||||
|
||||
|
@ -24,25 +24,37 @@
|
|||
namespace gambatte {
|
||||
|
||||
class TimaInterruptRequester {
|
||||
InterruptRequester &intreq;
|
||||
|
||||
public:
|
||||
explicit TimaInterruptRequester(InterruptRequester &intreq) : intreq(intreq) {}
|
||||
void flagIrq() const { intreq.flagIrq(4); }
|
||||
unsigned long nextIrqEventTime() const { return intreq.eventTime(intevent_tima); }
|
||||
void setNextIrqEventTime(const unsigned long time) const { intreq.setEventTime<intevent_tima>(time); }
|
||||
explicit TimaInterruptRequester(InterruptRequester &intreq) : intreq_(intreq) {}
|
||||
void flagIrq() const { intreq_.flagIrq(4); }
|
||||
unsigned long nextIrqEventTime() const { return intreq_.eventTime(intevent_tima); }
|
||||
void setNextIrqEventTime(unsigned long time) const { intreq_.setEventTime<intevent_tima>(time); }
|
||||
|
||||
private:
|
||||
InterruptRequester &intreq_;
|
||||
};
|
||||
|
||||
class Tima {
|
||||
public:
|
||||
Tima();
|
||||
void loadState(const SaveState &, TimaInterruptRequester timaIrq);
|
||||
void resetCc(unsigned long oldCc, unsigned long newCc, TimaInterruptRequester timaIrq);
|
||||
void setTima(unsigned tima, unsigned long cc, TimaInterruptRequester timaIrq);
|
||||
void setTma(unsigned tma, unsigned long cc, TimaInterruptRequester timaIrq);
|
||||
void setTac(unsigned tac, unsigned long cc, TimaInterruptRequester timaIrq, bool gbIsCgb);
|
||||
void resTac(unsigned long cc, TimaInterruptRequester timaIrq);
|
||||
unsigned tima(unsigned long cc);
|
||||
void doIrqEvent(TimaInterruptRequester timaIrq);
|
||||
|
||||
private:
|
||||
unsigned long basetime_;
|
||||
unsigned long lastUpdate_;
|
||||
unsigned long tmatime_;
|
||||
|
||||
unsigned char tima_;
|
||||
unsigned char tma_;
|
||||
unsigned char tac_;
|
||||
|
||||
void updateIrq(const unsigned long cc, const TimaInterruptRequester timaIrq) {
|
||||
void updateIrq(unsigned long const cc, TimaInterruptRequester timaIrq) {
|
||||
while (cc >= timaIrq.nextIrqEventTime())
|
||||
doIrqEvent(timaIrq);
|
||||
}
|
||||
|
@ -50,18 +62,6 @@ class Tima {
|
|||
void updateTima(unsigned long cc);
|
||||
|
||||
public:
|
||||
Tima();
|
||||
void loadState(const SaveState &, TimaInterruptRequester timaIrq);
|
||||
void resetCc(unsigned long oldCc, unsigned long newCc, TimaInterruptRequester timaIrq);
|
||||
|
||||
void setTima(unsigned tima, unsigned long cc, TimaInterruptRequester timaIrq);
|
||||
void setTma(unsigned tma, unsigned long cc, TimaInterruptRequester timaIrq);
|
||||
void setTac(unsigned tac, unsigned long cc, TimaInterruptRequester timaIrq, bool gbIsCgb);
|
||||
void resTac(unsigned long cc, TimaInterruptRequester timaIrq);
|
||||
unsigned tima(unsigned long cc);
|
||||
|
||||
void doIrqEvent(TimaInterruptRequester timaIrq);
|
||||
|
||||
template<bool isReader>void SyncState(NewState *ns);
|
||||
};
|
||||
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue