// Meteor - A Nintendo Gameboy Advance emulator1// Copyright (C) 2009-2011 Philippe Daouadi2//3// This program is free software: you can redistribute it and/or modify4// it under the terms of the GNU General Public License as published by5// the Free Software Foundation, either version 3 of the License, or6// (at your option) any later version.7//8// This program is distributed in the hope that it will be useful,9// but WITHOUT ANY WARRANTY; without even the implied warranty of10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the11// GNU General Public License for more details.12//13// You should have received a copy of the GNU General Public License14// along with this program. If not, see <http://www.gnu.org/licenses/>.1516#include "ameteor/clock.hpp"17#include "globals.hpp"18#include "ameteor.hpp"1920#include "debug.hpp"2122namespace AMeteor23{24void Clock::Reset ()25{26// lcd is enabled by default27m_first = m_count = m_cycles = m_lcd = m_sound = 0;28// timers and battery are disabled by default29/*m_battery =*/ m_timer[0] = m_timer[1] = m_timer[2] = m_timer[3] =30INT_MAX;31}3233void Clock::Commit ()34{35unsigned short tocommit;3637//m_count += m_cycles;3839// this loop is here because a timer can trigger a dma which will take a40// long time, during this time the lcd must draw and the timers continue41while (m_cycles >= m_first)42{43m_count += m_cycles;4445tocommit = m_cycles;46m_cycles = 0;4748m_lcd -= tocommit;49while (m_lcd <= 0)50LCD.TimeEvent();5152m_sound -= tocommit;53while (m_sound <= 0)54{55SOUND.TimeEvent();56// XXX freq57m_sound += SOUND_PERIOD;58}5960#define COMMIT(dev, obj) \61if (m_##dev != INT_MAX) \62{ \63m_##dev -= tocommit; \64while (m_##dev <= 0) \65obj.TimeEvent(); \66}67COMMIT(timer[0], TIMER0)68COMMIT(timer[1], TIMER1)69COMMIT(timer[2], TIMER2)70COMMIT(timer[3], TIMER3)71//COMMIT(battery, MEM)72#undef COMMIT7374SetFirst();75}76}7778void Clock::WaitForNext ()79{80m_cycles = m_first;81Commit();82}8384#define SETFIRST(dev) \85if (m_##dev < m_first) \86m_first = m_##dev87void Clock::SetFirst ()88{89m_first = m_lcd;90SETFIRST(timer[0]);91SETFIRST(timer[1]);92SETFIRST(timer[2]);93SETFIRST(timer[3]);94SETFIRST(sound);95//SETFIRST(battery);96}97#undef SETFIRST9899bool Clock::SaveState (std::ostream& stream)100{101SS_WRITE_VAR(m_cycles);102SS_WRITE_VAR(m_first);103SS_WRITE_VAR(m_lcd);104SS_WRITE_VAR(m_sound);105//SS_WRITE_VAR(m_battery);106107SS_WRITE_ARRAY(m_timer);108109return true;110}111112bool Clock::LoadState (std::istream& stream)113{114SS_READ_VAR(m_cycles);115SS_READ_VAR(m_first);116SS_READ_VAR(m_lcd);117SS_READ_VAR(m_sound);118//SS_READ_VAR(m_battery);119120SS_READ_ARRAY(m_timer);121122return true;123}124}125126127