Skip to content

Commit

Permalink
improved compatibility, irq 48 signal check
Browse files Browse the repository at this point in the history
  • Loading branch information
drhelius committed Sep 29, 2012
1 parent b53e521 commit 5e831c1
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 45 deletions.
30 changes: 9 additions & 21 deletions src/Processor.cpp
Expand Up @@ -40,7 +40,6 @@ Processor::Processor(Memory* pMemory)
m_iSerialCycles = 0;
m_bCGB = false;
m_iUnhaltCycles = 0;
m_IRQ48Signal = 0;
m_HaltCachedIFRegister = 0;
for (int i = 0; i < 5; i++)
m_InterruptDelayCycles[i] = 0;
Expand Down Expand Up @@ -72,7 +71,6 @@ void Processor::Reset(bool bCGB)
m_iSerialCycles = 0;
m_iUnhaltCycles = 0;
m_HaltCachedIFRegister = 0;
m_IRQ48Signal = 0;
PC.SetValue(0x100);
SP.SetValue(0xFFFE);
if (m_bCGB)
Expand Down Expand Up @@ -153,16 +151,16 @@ void Processor::RequestInterrupt(Interrupts interrupt)
switch (interrupt)
{
case VBlank_Interrupt:
m_InterruptDelayCycles[0] = 12;
m_InterruptDelayCycles[0] = 4;
break;
case LCDSTAT_Interrupt:
m_InterruptDelayCycles[1] = 24;
m_InterruptDelayCycles[1] = 0;
break;
case Timer_Interrupt:
m_InterruptDelayCycles[2] = 12;
m_InterruptDelayCycles[2] = 0;
break;
case Serial_Interrupt:
m_InterruptDelayCycles[3] = 12;
m_InterruptDelayCycles[3] = 0;
break;
case Joypad_Interrupt:
m_InterruptDelayCycles[4] = 0;
Expand All @@ -184,16 +182,6 @@ void Processor::ResetDIVCycles()
m_iTIMACycles = 0;
}

u8 Processor::GetIRQ48Signal() const
{
return m_IRQ48Signal;
}

void Processor::SetIRQ48Signal(u8 signal)
{
m_IRQ48Signal = signal;
}

u8 Processor::FetchOPCode()
{
u8 opcode = m_pMemory->Read(PC.GetValue());
Expand Down Expand Up @@ -288,39 +276,39 @@ void Processor::ServeInterrupt(Interrupts interrupt)
m_bIME = false;
StackPush(&PC);
PC.SetValue(0x0040);
m_CurrentClockCycles += 20;
m_CurrentClockCycles += 24;
break;
case LCDSTAT_Interrupt:
m_InterruptDelayCycles[1] = 0;
m_pMemory->Load(0xFF0F, if_reg & 0xFD);
m_bIME = false;
StackPush(&PC);
PC.SetValue(0x0048);
m_CurrentClockCycles += 20;
m_CurrentClockCycles += 24;
break;
case Timer_Interrupt:
m_InterruptDelayCycles[2] = 0;
m_pMemory->Load(0xFF0F, if_reg & 0xFB);
m_bIME = false;
StackPush(&PC);
PC.SetValue(0x0050);
m_CurrentClockCycles += 20;
m_CurrentClockCycles += 24;
break;
case Serial_Interrupt:
m_InterruptDelayCycles[3] = 0;
m_pMemory->Load(0xFF0F, if_reg & 0xF7);
m_bIME = false;
StackPush(&PC);
PC.SetValue(0x0058);
m_CurrentClockCycles += 20;
m_CurrentClockCycles += 24;
break;
case Joypad_Interrupt:
m_InterruptDelayCycles[4] = 0;
m_pMemory->Load(0xFF0F, if_reg & 0xEF);
m_bIME = false;
StackPush(&PC);
PC.SetValue(0x0060);
m_CurrentClockCycles += 20;
m_CurrentClockCycles += 24;
break;
case None_Interrupt:
break;
Expand Down
3 changes: 0 additions & 3 deletions src/Processor.h
Expand Up @@ -48,8 +48,6 @@ class Processor
void RequestInterrupt(Interrupts interrupt);
void ResetTIMACycles();
void ResetDIVCycles();
u8 GetIRQ48Signal() const;
void SetIRQ48Signal(u8 signal);

private:
typedef void (Processor::*OPCptr) (void);
Expand Down Expand Up @@ -78,7 +76,6 @@ class Processor
bool m_bCGB;
int m_InterruptDelayCycles[5];
u8 m_HaltCachedIFRegister;
u8 m_IRQ48Signal;

private:
u8 FetchOPCode();
Expand Down
68 changes: 49 additions & 19 deletions src/Video.cpp
Expand Up @@ -40,6 +40,7 @@ Video::Video(Memory* pMemory, Processor* pProcessor)
m_bCGB = false;
m_bScanLineTransfered = false;
m_iHideFrames = 0;
m_IRQ48Signal = 0;
}

Video::~Video()
Expand Down Expand Up @@ -79,6 +80,7 @@ void Video::Reset(bool bCGB)
m_bScanLineTransfered = false;
m_bCGB = bCGB;
m_iHideFrames = 0;
m_IRQ48Signal = 0;
}

bool Video::Tick(u8 clockCycles, GB_Color* pColorFrameBuffer)
Expand Down Expand Up @@ -116,9 +118,17 @@ bool Video::Tick(u8 clockCycles, GB_Color* pColorFrameBuffer)

m_pProcessor->RequestInterrupt(Processor::VBlank_Interrupt);

m_IRQ48Signal &= 0x09;
u8 stat = m_pMemory->Retrieve(0xFF41);
if (IsSetBit(stat, 4))
m_pProcessor->RequestInterrupt(Processor::LCDSTAT_Interrupt);
{
if (!IsSetBit(m_IRQ48Signal, 0) && !IsSetBit(m_IRQ48Signal, 3))
{
m_pProcessor->RequestInterrupt(Processor::LCDSTAT_Interrupt);
}
m_IRQ48Signal = SetBit(m_IRQ48Signal, 1);
}
m_IRQ48Signal &= 0x0E;

if (m_iHideFrames > 0)
m_iHideFrames--;
Expand All @@ -129,9 +139,17 @@ bool Video::Tick(u8 clockCycles, GB_Color* pColorFrameBuffer)
}
else
{
m_IRQ48Signal &= 0x09;
u8 stat = m_pMemory->Retrieve(0xFF41);
if (IsSetBit(stat, 5))
m_pProcessor->RequestInterrupt(Processor::LCDSTAT_Interrupt);
{
if (m_IRQ48Signal == 0)
{
m_pProcessor->RequestInterrupt(Processor::LCDSTAT_Interrupt);
}
m_IRQ48Signal = SetBit(m_IRQ48Signal, 2);
}
m_IRQ48Signal &= 0x0E;
}

UpdateStatRegister();
Expand Down Expand Up @@ -166,11 +184,20 @@ bool Video::Tick(u8 clockCycles, GB_Color* pColorFrameBuffer)
{
m_iStatusModeCounter -= 4560;
m_iStatusMode = 2;
u8 stat = m_pMemory->Retrieve(0xFF41);
if (IsSetBit(stat, 5))
m_pProcessor->RequestInterrupt(Processor::LCDSTAT_Interrupt);
UpdateStatRegister();
CompareLYToLYC();

m_IRQ48Signal &= 0x0A;
u8 stat = m_pMemory->Retrieve(0xFF41);
if (IsSetBit(stat, 5))
{
if (m_IRQ48Signal == 0)
{
m_pProcessor->RequestInterrupt(Processor::LCDSTAT_Interrupt);
}
m_IRQ48Signal = SetBit(m_IRQ48Signal, 2);
}
m_IRQ48Signal &= 0x0D;
}
break;
}
Expand All @@ -182,6 +209,7 @@ bool Video::Tick(u8 clockCycles, GB_Color* pColorFrameBuffer)
m_iStatusModeCounter -= 80;
m_iStatusMode = 3;
m_bScanLineTransfered = false;
m_IRQ48Signal &= 0x08;
UpdateStatRegister();
}
break;
Expand All @@ -200,12 +228,18 @@ bool Video::Tick(u8 clockCycles, GB_Color* pColorFrameBuffer)
ScanLine(m_iStatusModeLYCounter);
m_iStatusModeCounter -= 172;
m_iStatusMode = 0;
UpdateStatRegister();

m_IRQ48Signal &= 0x08;
u8 stat = m_pMemory->Retrieve(0xFF41);
if (IsSetBit(stat, 3))
m_pProcessor->RequestInterrupt(Processor::LCDSTAT_Interrupt);

UpdateStatRegister();
{
if (!IsSetBit(m_IRQ48Signal, 3))
{
m_pProcessor->RequestInterrupt(Processor::LCDSTAT_Interrupt);
}
m_IRQ48Signal = SetBit(m_IRQ48Signal, 0);
}
}
break;
}
Expand All @@ -229,17 +263,13 @@ bool Video::Tick(u8 clockCycles, GB_Color* pColorFrameBuffer)
m_iWindowLine = 0;
m_iStatusVBlankLine = 0;
m_pMemory->Load(0xFF44, m_iStatusModeLYCounter);
m_pProcessor->SetIRQ48Signal(0);
m_IRQ48Signal = 0;

u8 stat = m_pMemory->Retrieve(0xFF41);
if (IsSetBit(stat, 5))
{
u8 signal = m_pProcessor->GetIRQ48Signal();
if (signal == 0x00)
{
m_pProcessor->RequestInterrupt(Processor::LCDSTAT_Interrupt);
}
m_pProcessor->SetIRQ48Signal(SetBit(signal, 2));
m_pProcessor->RequestInterrupt(Processor::LCDSTAT_Interrupt);
m_IRQ48Signal = SetBit(m_IRQ48Signal, 2);
}

CompareLYToLYC();
Expand Down Expand Up @@ -268,6 +298,7 @@ void Video::DisableScreen()
m_iStatusModeCounter = 0;
m_iStatusModeCounterAux = 0;
m_iStatusModeLYCounter = 0;
m_IRQ48Signal = 0;
}

bool Video::IsScreenEnabled() const
Expand Down Expand Up @@ -721,18 +752,17 @@ void Video::CompareLYToLYC()
stat = SetBit(stat, 2);
if (IsSetBit(stat, 6))
{
u8 signal = m_pProcessor->GetIRQ48Signal();
if (signal == 0x00)
if (m_IRQ48Signal == 0x00)
{
m_pProcessor->RequestInterrupt(Processor::LCDSTAT_Interrupt);
}
m_pProcessor->SetIRQ48Signal(SetBit(signal, 3));
m_IRQ48Signal = SetBit(m_IRQ48Signal, 3);
}
}
else
{
stat = UnsetBit(stat, 2);
m_pProcessor->SetIRQ48Signal(UnsetBit(m_pProcessor->GetIRQ48Signal(), 3));
m_IRQ48Signal = UnsetBit(m_IRQ48Signal, 3);
}

m_pMemory->Load(0xFF41, stat);
Expand Down
5 changes: 3 additions & 2 deletions src/Video.h
Expand Up @@ -41,15 +41,15 @@ class Video
int GetCurrentStatusMode() const;
void ResetWindowLine();
void CompareLYToLYC();

private:
void ScanLine(int line);
void RenderBG(int line);
void RenderWindow(int line);
void RenderSprites(int line);
void UpdateStatRegister();
GB_Color ConvertTo8BitColor(GB_Color color);

private:
Memory* m_pMemory;
Processor* m_pProcessor;
Expand All @@ -70,6 +70,7 @@ class Video
bool m_bScanLineTransfered;
int m_iWindowLine;
int m_iHideFrames;
u8 m_IRQ48Signal;
};

#endif /* VIDEO_H */
Expand Down

0 comments on commit 5e831c1

Please sign in to comment.