// 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/lcd.hpp"17#include "ameteor/io.hpp"18#include "globals.hpp"19#include "ameteor.hpp"2021#include "debug.hpp"2223namespace AMeteor24{25Lcd::Lcd () :26m_screen(MEM, IO)27{28Reset();29}3031void Lcd::Reset ()32{33CLOCK.AddLcd(960); // call me at first H-Blank34}3536void Lcd::TimeEvent ()37{38uint16_t& dispstat = IO.GetRef16(Io::DISPSTAT);39uint16_t& vcount = IO.GetRef16(Io::VCOUNT);4041if (dispstat & 0x2) // if we were H-Blanking42{43//debug("hblank end");44// we are not anymore, we're on next line45dispstat ^= 0x2;46// call me when we are H-Blanking again47CLOCK.AddLcd(960);4849// we have finished drawing a line, do our stuff...50if (vcount == 227) // this was the last line51{52vcount = 0; // we're now at first53// we reload the reference points54m_screen.UpdateBg2RefX(IO.DRead32(Io::BG2X_L));55m_screen.UpdateBg2RefY(IO.DRead32(Io::BG2Y_L));56m_screen.UpdateBg3RefX(IO.DRead32(Io::BG3X_L));57m_screen.UpdateBg3RefY(IO.DRead32(Io::BG3Y_L));58// and we draw the line 059m_screen.DrawLine(0);60// FIXME see below, vblank finished61dispstat ^= 0x1;62}63else64{65++vcount; // we're on next line66if (vcount < 160) // we draw normally67m_screen.DrawLine(vcount);68else if (vcount == 160) // We enter V-Blank69{70dispstat |= 0x1;71if (dispstat & (0x1 << 3)) // if V-Blank irq is enabled72CPU.SendInterrupt(0x1);73DMA.CheckAll(Dma::VBlank);7475KEYPAD.VBlank();7677// we send the vblank signal78//sig_vblank.emit();79}80// NOTE : v-blank finishes on line 227, not 081// FIXME on vba, it finishes on 082//if (vcount == 227) // V-Blank finished83//dispstat ^= 0x1;84}8586// check for vcount match87if (vcount == ((dispstat >> 8) & 0xFF)) // vcount match88{89dispstat |= 0x4; // enable vcount match bit90if (dispstat & (0x1 << 5)) // if V-Counter irq is enabled91CPU.SendInterrupt(0x4);92}93else // no vcount match94dispstat &= ~(uint16_t)0x4;95// scanline callback for frontend96if (slcallbackline == vcount)97scanlinecallback_bizhawk();98}99else // if we were not H-Blanking100{101//debug("hblank vcount : " << std::dec << vcount);102// now, we are103dispstat |= 0x2;104// call me when we are not H-Blanking anymore105CLOCK.AddLcd(272);106107// NOTE : H-Blank interrupts are not generated during V-Blank108// FIXME vba generates hblank interrupts even during vblank109// if H-Blank irq is enabled //and we're not in V-Blank110if ((dispstat & 0x10) == 0x10)111CPU.SendInterrupt(0x2);112// NOTE : hblank DMAs are not triggered during vblank113// (seen on vba)114if (!(dispstat & 0x1))115// if we're not vblanking116DMA.CheckAll(Dma::HBlank);117}118}119120bool Lcd::SaveState (std::ostream& stream)121{122if (!m_screen.SaveState(stream))123return false;124125return true;126}127128bool Lcd::LoadState (std::istream& stream)129{130if (!m_screen.LoadState(stream))131return false;132133UpdateDispCnt (IO.DRead16(Io::DISPCNT));134UpdateBg0Cnt (IO.DRead16(Io::BG0CNT));135UpdateBg1Cnt (IO.DRead16(Io::BG1CNT));136UpdateBg2Cnt (IO.DRead16(Io::BG2CNT));137UpdateBg3Cnt (IO.DRead16(Io::BG3CNT));138UpdateBg0XOff (IO.DRead16(Io::BG0HOFS));139UpdateBg0YOff (IO.DRead16(Io::BG0VOFS));140UpdateBg1XOff (IO.DRead16(Io::BG1HOFS));141UpdateBg1YOff (IO.DRead16(Io::BG1VOFS));142UpdateBg2XOff (IO.DRead16(Io::BG2HOFS));143UpdateBg2YOff (IO.DRead16(Io::BG2VOFS));144UpdateBg3XOff (IO.DRead16(Io::BG3HOFS));145UpdateBg3YOff (IO.DRead16(Io::BG3VOFS));146OamWrite (0x07000000, 0x07000400);147148return true;149}150}151152153