libgambatte: refactor Tima

This commit is contained in:
MrWint 2019-05-26 12:46:17 +02:00
parent 79085f9a3a
commit 51e8ba3cf5
6 changed files with 127 additions and 125 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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.