diff options
| author | Louis Burda <quent.burda@gmail.com> | 2022-06-02 15:28:40 +0200 |
|---|---|---|
| committer | Louis Burda <quent.burda@gmail.com> | 2022-06-02 15:28:40 +0200 |
| commit | 5bc16063c29aa4d3d287ebd163ccdbcbf54c4f9f (patch) | |
| tree | c131f947a37b3af2d14d41e9eda098bdec2d061c /gearboy/src/IORegistersMemoryRule.h | |
| parent | 78a5f810b22f0d8cafa05f638b0cb2e889824859 (diff) | |
| download | cscg2022-gearboy-master.tar.gz cscg2022-gearboy-master.zip | |
Diffstat (limited to 'gearboy/src/IORegistersMemoryRule.h')
| -rw-r--r-- | gearboy/src/IORegistersMemoryRule.h | 539 |
1 files changed, 539 insertions, 0 deletions
diff --git a/gearboy/src/IORegistersMemoryRule.h b/gearboy/src/IORegistersMemoryRule.h new file mode 100644 index 00000000..8c7639f3 --- /dev/null +++ b/gearboy/src/IORegistersMemoryRule.h @@ -0,0 +1,539 @@ +/* + * Gearboy - Nintendo Game Boy Emulator + * Copyright (C) 2012 Ignacio Sanchez + + * 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 + * 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 http://www.gnu.org/licenses/ + * + */ + +#ifndef IOREGISTERSMEMORYRULE_H +#define IOREGISTERSMEMORYRULE_H + +#include "definitions.h" + +class Video; +class Processor; +class Input; +class Audio; +class Memory; + +class IORegistersMemoryRule +{ +public: + IORegistersMemoryRule(Processor* pProcessor, Memory* pMemory, Video* pVideo, Input* pInput, Audio* pAudio); + ~IORegistersMemoryRule(); + u8 PerformRead(u16 address); + void PerformWrite(u16 address, u8 value); + void Reset(bool bCGB); + +private: + Processor* m_pProcessor; + Memory* m_pMemory; + Video* m_pVideo; + Input* m_pInput; + Audio* m_pAudio; + bool m_bCGB; +}; + +#include "Video.h" +#include "Processor.h" +#include "Input.h" +#include "Audio.h" +#include "Memory.h" + +inline u8 IORegistersMemoryRule::PerformRead(u16 address) +{ + switch (address) + { + case 0xFF00: + { + // P1 + return m_pInput->Read(); + } + case 0xFF03: + { + // UNDOCUMENTED + return 0xFF; + } + case 0xFF07: + { + // TAC + return m_pMemory->Retrieve(0xFF07) | 0xF8; + } + case 0xFF08: + case 0xFF09: + case 0xFF0A: + case 0xFF0B: + case 0xFF0C: + case 0xFF0D: + case 0xFF0E: + { + // UNDOCUMENTED + return 0xFF; + } + case 0xFF0F: + { + // IF + return m_pMemory->Retrieve(0xFF0F) | 0xE0; + } + case 0xFF10: + case 0xFF11: + case 0xFF12: + case 0xFF13: + case 0xFF14: + case 0xFF15: + case 0xFF16: + case 0xFF17: + case 0xFF18: + case 0xFF19: + case 0xFF1A: + case 0xFF1B: + case 0xFF1C: + case 0xFF1D: + case 0xFF1E: + case 0xFF1F: + case 0xFF20: + case 0xFF21: + case 0xFF22: + case 0xFF23: + case 0xFF24: + case 0xFF25: + case 0xFF26: + case 0xFF27: + case 0xFF28: + case 0xFF29: + case 0xFF2A: + case 0xFF2B: + case 0xFF2C: + case 0xFF2D: + case 0xFF2E: + case 0xFF2F: + case 0xFF30: + case 0xFF31: + case 0xFF32: + case 0xFF33: + case 0xFF34: + case 0xFF35: + case 0xFF36: + case 0xFF37: + case 0xFF38: + case 0xFF39: + case 0xFF3A: + case 0xFF3B: + case 0xFF3C: + case 0xFF3D: + case 0xFF3E: + case 0xFF3F: + { + // SOUND REGISTERS + return m_pAudio->ReadAudioRegister(address); + } + case 0xFF41: + { + // STAT + return m_pMemory->Retrieve(0xFF41) | 0x80; + } + case 0xFF44: + { + // LY + return (m_pVideo->IsScreenEnabled() ? m_pMemory->Retrieve(0xFF44) : 0x00); + } + case 0xFF4C: + { + // UNDOCUMENTED + return 0xFF; + } + case 0xFF4F: + { + // VBK + return m_pMemory->Retrieve(0xFF4F) | 0xFE; + } + case 0xFF51: + { + // HDMA1 + return (m_bCGB ? m_pMemory->GetHDMARegister(1) : m_pMemory->Retrieve(address)); + } + case 0xFF52: + { + // HDMA2 + return (m_bCGB ? m_pMemory->GetHDMARegister(2) : m_pMemory->Retrieve(address)); + } + case 0xFF53: + { + // HDMA3 + return (m_bCGB ? m_pMemory->GetHDMARegister(3) : m_pMemory->Retrieve(address)); + } + case 0xFF54: + { + // HDMA4 + return (m_bCGB ? m_pMemory->GetHDMARegister(4) : m_pMemory->Retrieve(address)); + } + case 0xFF55: + { + // DMA CGB + return (m_bCGB ? m_pMemory->GetHDMARegister(5) : m_pMemory->Retrieve(address)); + } + case 0xFF68: + case 0xFF6A: + { + // BCPS, OCPS + return (m_bCGB ? (m_pMemory->Retrieve(address) | 0x40) : 0xC0); + } + case 0xFF69: + case 0xFF6B: + { + // BCPD, OCPD + return (m_bCGB ? m_pMemory->Retrieve(address) : 0xFF); + } + case 0xFF70: + { + // SVBK + return (m_bCGB ? (m_pMemory->Retrieve(0xFF70) | 0xF8) : 0xFF); + } + case 0xFF76: + { + // UNDOCUMENTED + return (m_bCGB ? 0x00 : 0xFF); + } + case 0xFF77: + { + // UNDOCUMENTED + return (m_bCGB ? 0x0 : 0xFF); + } + } + + return m_pMemory->Retrieve(address); +} + +inline void IORegistersMemoryRule::PerformWrite(u16 address, u8 value) +{ + switch (address) + { + case 0xFF00: + { + // P1 + m_pInput->Write(value); + break; + } + case 0xFF04: + { + // DIV + m_pProcessor->ResetDIVCycles(); + break; + } + case 0xFF07: + { + // TAC + value &= 0x07; + u8 current_tac = m_pMemory->Retrieve(0xFF07); + if ((current_tac & 0x03) != (value & 0x03)) + { + m_pProcessor->ResetTIMACycles(); + } + m_pMemory->Load(address, value); + break; + } + case 0xFF0F: + { + // IF + m_pMemory->Load(address, value & 0x1F); + break; + } + case 0xFF10: + case 0xFF11: + case 0xFF12: + case 0xFF13: + case 0xFF14: + case 0xFF15: + case 0xFF16: + case 0xFF17: + case 0xFF18: + case 0xFF19: + case 0xFF1A: + case 0xFF1B: + case 0xFF1C: + case 0xFF1D: + case 0xFF1E: + case 0xFF1F: + case 0xFF20: + case 0xFF21: + case 0xFF22: + case 0xFF23: + case 0xFF24: + case 0xFF25: + case 0xFF26: + case 0xFF27: + case 0xFF28: + case 0xFF29: + case 0xFF2A: + case 0xFF2B: + case 0xFF2C: + case 0xFF2D: + case 0xFF2E: + case 0xFF2F: + case 0xFF30: + case 0xFF31: + case 0xFF32: + case 0xFF33: + case 0xFF34: + case 0xFF35: + case 0xFF36: + case 0xFF37: + case 0xFF38: + case 0xFF39: + case 0xFF3A: + case 0xFF3B: + case 0xFF3C: + case 0xFF3D: + case 0xFF3E: + case 0xFF3F: + { + // SOUND REGISTERS + m_pAudio->WriteAudioRegister(address, value); + break; + } + case 0xFF40: + { + // LCDC + u8 current_lcdc = m_pMemory->Retrieve(0xFF40); + u8 new_lcdc = value; + m_pMemory->Load(address, new_lcdc); + if (!IsSetBit(current_lcdc, 5) && IsSetBit(new_lcdc, 5)) + m_pVideo->ResetWindowLine(); + if (IsSetBit(new_lcdc, 7)) + m_pVideo->EnableScreen(); + else + m_pVideo->DisableScreen(); + break; + } + case 0xFF41: + { + // STAT + u8 current_stat = m_pMemory->Retrieve(0xFF41) & 0x07; + u8 new_stat = (value & 0x78) | (current_stat & 0x07); + m_pMemory->Load(address, new_stat); + u8 lcdc = m_pMemory->Retrieve(0xFF40); + u8 signal = m_pVideo->GetIRQ48Signal(); + int mode = m_pVideo->GetCurrentStatusMode(); + signal &= ((new_stat >> 3) & 0x0F); + m_pVideo->SetIRQ48Signal(signal); + + if (IsSetBit(lcdc, 7)) + { + if (IsSetBit(new_stat, 3) && (mode == 0)) + { + if (signal == 0) + { + m_pProcessor->RequestInterrupt(Processor::LCDSTAT_Interrupt); + } + signal = SetBit(signal, 0); + } + if (IsSetBit(new_stat, 4) && (mode == 1)) + { + if (signal == 0) + { + m_pProcessor->RequestInterrupt(Processor::LCDSTAT_Interrupt); + } + signal = SetBit(signal, 1); + } + if (IsSetBit(new_stat, 5) && (mode == 2)) + { + if (signal == 0) + { + m_pProcessor->RequestInterrupt(Processor::LCDSTAT_Interrupt); + } + //signal = SetBit(signal, 2); + } + m_pVideo->CompareLYToLYC(); + } + break; + } + case 0xFF44: + { + // LY + u8 current_ly = m_pMemory->Retrieve(0xFF44); + if (IsSetBit(current_ly, 7) && !IsSetBit(value, 7)) + { + m_pVideo->DisableScreen(); + } + break; + } + case 0xFF45: + { + // LYC + u8 current_lyc = m_pMemory->Retrieve(0xFF45); + if (current_lyc != value) + { + m_pMemory->Load(0xFF45, value); + u8 lcdc = m_pMemory->Retrieve(0xFF40); + if (IsSetBit(lcdc, 7)) + { + m_pVideo->CompareLYToLYC(); + } + } + break; + } + case 0xFF46: + { + // DMA + m_pMemory->Load(address, value); + m_pMemory->PerformDMA(value); + break; + } + case 0xFF4D: + { + // KEY1 + if (m_bCGB) + { + u8 current_key1 = m_pMemory->Retrieve(0xFF4D); + m_pMemory->Load(address, (current_key1 & 0x80) | (value & 0x01) | 0x7E); + } + else + m_pMemory->Load(address, value); + break; + } + case 0xFF4F: + { + // VBK + if (m_bCGB) + { + value &= 0x01; + m_pMemory->SwitchCGBLCDRAM(value); + } + m_pMemory->Load(address, value); + break; + } + case 0xFF50: + { + // BOOT + if ((value & 0x01) > 0) + { + m_pMemory->DisableBootromRegistry(); + } + break; + } + case 0xFF51: + { + // HDMA1 + if (m_bCGB) + m_pMemory->SetHDMARegister(1, value); + else + m_pMemory->Load(address, value); + break; + } + case 0xFF52: + { + // HDMA2 + if (m_bCGB) + m_pMemory->SetHDMARegister(2, value); + else + m_pMemory->Load(address, value); + break; + } + case 0xFF53: + { + // HDMA3 + if (m_bCGB) + m_pMemory->SetHDMARegister(3, value); + else + m_pMemory->Load(address, value); + break; + } + case 0xFF54: + { + // HDMA4 + if (m_bCGB) + m_pMemory->SetHDMARegister(4, value); + else + m_pMemory->Load(address, value); + break; + } + case 0xFF55: + { + // DMA CGB + if (m_bCGB) + m_pMemory->SwitchCGBDMA(value); + else + m_pMemory->Load(address, value); + break; + } + case 0xFF68: + { + // BCPS + m_pMemory->Load(address, value); + if (m_bCGB) + m_pVideo->UpdatePaletteToSpecification(true, value); + break; + } + case 0xFF69: + { + // BCPD + m_pMemory->Load(address, value); + if (m_bCGB) + m_pVideo->SetColorPalette(true, value); + break; + } + case 0xFF6A: + { + // OCPS + m_pMemory->Load(address, value); + if (m_bCGB) + m_pVideo->UpdatePaletteToSpecification(false, value); + break; + } + case 0xFF6B: + { + // OCPD + m_pMemory->Load(address, value); + if (m_bCGB) + m_pVideo->SetColorPalette(false, value); + break; + } + case 0xFF6C: + { + // UNDOCUMENTED + m_pMemory->Load(0xFF6C, value | 0xFE); + break; + } + case 0xFF70: + { + // SVBK + if (m_bCGB) + { + value &= 0x07; + m_pMemory->SwitchCGBWRAM(value); + } + m_pMemory->Load(address, value); + break; + } + case 0xFF75: + { + // UNDOCUMENTED + m_pMemory->Load(0xFF75, value | 0x8F); + break; + } + case 0xFFFF: + { + // IE + m_pMemory->Load(address, value & 0x1F); + break; + } + default: + { + m_pMemory->Load(address, value); + } + } +} + +#endif /* IOREGISTERSMEMORYRULE_H */ |
