// 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 . #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; } }