#include #include #include "hqn.h" #include "hqn_util.h" namespace hqn { // Function to initalize the video palette int32_t *_initF_VideoPalette() { static int32_t VideoPalette[512]; const Nes_Emu::rgb_t *palette = Nes_Emu::nes_colors; for (int i = 0; i < 512; i++) { VideoPalette[i] = palette[i].red << 16 | palette[i].green << 8 | palette[i].blue | 0xff000000; } return VideoPalette; } // Initialize the video palette const int32_t *HQNState::NES_VIDEO_PALETTE = _initF_VideoPalette(); // simulate the write so we'll know how long the buffer needs to be class Sim_Writer : public Data_Writer { long size_; public: Sim_Writer() :size_(0) { } error_t write(const void *, long size) { size_ += size; return 0; } long size() const { return size_; } }; // Constructor HQNState::HQNState() { m_emu = new Nes_Emu(); joypad[0] = 0x00; joypad[1] = 0x00; m_listener = nullptr; m_romData = nullptr; m_romSize = 0; m_emu->set_sample_rate(44100); m_prevFrame = 0; m_msPerFrame = 0; m_initialFrame = SDL_GetTicks(); } // Destructor HQNState::~HQNState() { delete m_emu; } error_t HQNState::setSampleRate(int rate) { const char *ret = m_emu->set_sample_rate(rate); if (!ret) m_emu->set_equalizer(Nes_Emu::nes_eq); return ret; } error_t HQNState::saveState(void *dest, size_t size, size_t *size_out) { Mem_Writer w(dest, size, 0); Auto_File_Writer a(w); auto ret = m_emu->save_state(a); if (size_out) *size_out = w.size(); if (!ret && w.size() != size) return "Buffer Underrun!"; return ret; } error_t HQNState::saveStateSize(size_t *size) const { Sim_Writer w; Auto_File_Writer a(w); const char *ret = m_emu->save_state(a); if (size) *size = w.size(); return ret; } error_t HQNState::loadState(const char *data, size_t size) { Mem_File_Reader r(data, size); Auto_File_Reader a(r); error_t result = m_emu->load_state(a); if (m_listener) m_listener->onLoadState(this); return result; } // Advance the emulator error_t HQNState::advanceFrame(bool sleep) { Uint32 ticks; ticks = SDL_GetTicks(); Uint32 wantTicks = m_prevFrame + m_msPerFrame; if (wantTicks > ticks) { SDL_Delay(wantTicks - ticks); } // m_frameTime = wantTicks - m_prevFrame; error_t result = m_emu->emulate_frame(joypad[0], joypad[1]); if (m_listener) m_listener->onAdvanceFrame(this); ticks = SDL_GetTicks(); m_frameTime = ticks - m_prevFrame; m_prevFrame = ticks; return result; } void HQNState::setFramerate(int fps) { if (fps == 0) { m_msPerFrame = 0; } else { m_msPerFrame = (long)(1000.0 / fps); } } int HQNState::getFramerate() const { if (m_msPerFrame) { return (int)(1000.0 / m_msPerFrame); } else { return 0; } } double HQNState::getFPS() const { double ft = m_frameTime ? m_frameTime : 1; double fps = 1000.0 / ft; // round to 2 decimal places fps = std::floor(fps * 100) / 100; return fps; } } // end namespace hqn