BizHawk/libmeteor/source/clock.cpp

126 lines
2.7 KiB
C++

// 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/clock.hpp"
#include "globals.hpp"
#include "ameteor.hpp"
#include "debug.hpp"
namespace AMeteor
{
void Clock::Reset ()
{
// lcd is enabled by default
m_first = m_count = m_cycles = m_lcd = m_sound = 0;
// timers and battery are disabled by default
/*m_battery =*/ m_timer[0] = m_timer[1] = m_timer[2] = m_timer[3] =
INT_MAX;
}
void Clock::Commit ()
{
unsigned short tocommit;
//m_count += m_cycles;
// this loop is here because a timer can trigger a dma which will take a
// long time, during this time the lcd must draw and the timers continue
while (m_cycles >= m_first)
{
m_count += m_cycles;
tocommit = m_cycles;
m_cycles = 0;
m_lcd -= tocommit;
while (m_lcd <= 0)
LCD.TimeEvent();
m_sound -= tocommit;
while (m_sound <= 0)
{
SOUND.TimeEvent();
// XXX freq
m_sound += SOUND_PERIOD;
}
#define COMMIT(dev, obj) \
if (m_##dev != INT_MAX) \
{ \
m_##dev -= tocommit; \
while (m_##dev <= 0) \
obj.TimeEvent(); \
}
COMMIT(timer[0], TIMER0)
COMMIT(timer[1], TIMER1)
COMMIT(timer[2], TIMER2)
COMMIT(timer[3], TIMER3)
//COMMIT(battery, MEM)
#undef COMMIT
SetFirst();
}
}
void Clock::WaitForNext ()
{
m_cycles = m_first;
Commit();
}
#define SETFIRST(dev) \
if (m_##dev < m_first) \
m_first = m_##dev
void Clock::SetFirst ()
{
m_first = m_lcd;
SETFIRST(timer[0]);
SETFIRST(timer[1]);
SETFIRST(timer[2]);
SETFIRST(timer[3]);
SETFIRST(sound);
//SETFIRST(battery);
}
#undef SETFIRST
bool Clock::SaveState (std::ostream& stream)
{
SS_WRITE_VAR(m_cycles);
SS_WRITE_VAR(m_first);
SS_WRITE_VAR(m_lcd);
SS_WRITE_VAR(m_sound);
//SS_WRITE_VAR(m_battery);
SS_WRITE_ARRAY(m_timer);
return true;
}
bool Clock::LoadState (std::istream& stream)
{
SS_READ_VAR(m_cycles);
SS_READ_VAR(m_first);
SS_READ_VAR(m_lcd);
SS_READ_VAR(m_sound);
//SS_READ_VAR(m_battery);
SS_READ_ARRAY(m_timer);
return true;
}
}